Skip to content

Commit d600491

Browse files
committed
Merge /usr/local/google/home/ascull/projects/ub-testdpc-oc-release/vendor/unbundled_google/packages/TestDPC into dp2
2 parents e46b5de + a832bee commit d600491

28 files changed

+517
-378
lines changed

app/build.gradle

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ext {
77
// exactly 1 digit
88
versionMinor = 0
99
// exactly 2 digits
10-
versionBuild = 0
10+
versionBuild = 01
1111
}
1212

1313
android {
@@ -17,7 +17,7 @@ android {
1717
defaultConfig {
1818
applicationId "com.afwsamples.testdpc"
1919
minSdkVersion 21
20-
targetSdkVersion 25
20+
targetSdkVersion 26
2121
versionCode versionMajor * 1000 + versionMinor * 100 + versionBuild
2222
versionName "${versionMajor}.${versionMinor}.${versionBuild}"
2323
jackOptions {
@@ -32,6 +32,16 @@ android {
3232
}
3333
}
3434

35+
productFlavors {
36+
target25 {
37+
targetSdkVersion 25
38+
}
39+
40+
targetO {
41+
targetSdkVersion 'O'
42+
}
43+
}
44+
3545
lintOptions {
3646
check 'NewApi'
3747
abortOnError true
@@ -53,9 +63,9 @@ android {
5363
}
5464

5565
dependencies {
56-
compile 'com.android.support:preference-v14:25.+'
57-
compile 'com.android.support:recyclerview-v7:25.+'
58-
compile "com.android.support:support-v13:25.+"
66+
compile 'com.android.support:preference-v14:26.+'
67+
compile 'com.android.support:recyclerview-v7:26.+'
68+
compile 'com.android.support:support-v13:26.+'
5969
compile 'com.google.android.gms:play-services-safetynet:+'
6070
compile(name:'setup-wizard-lib-platform-release', ext:'aar')
6171
}
157 KB
Binary file not shown.

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120

121121
<receiver android:name=".FirstAccountReadyBroadcastReceiver"
122122
android:exported="true"
123-
android:enabled="false">
123+
android:enabled="true">
124124
<intent-filter>
125125
<action android:name="com.google.android.work.action.FIRST_ACCOUNT_READY"/>
126126
</intent-filter>

app/src/main/java/com/afwsamples/testdpc/FirstAccountReadyBroadcastReceiver.java

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@
1919
import android.app.AlarmManager;
2020
import android.app.PendingIntent;
2121
import android.content.BroadcastReceiver;
22-
import android.content.ComponentName;
2322
import android.content.Context;
2423
import android.content.Intent;
25-
import android.content.pm.PackageManager;
2624
import android.os.SystemClock;
2725
import android.util.Log;
2826

27+
import com.afwsamples.testdpc.common.Util;
2928
import com.afwsamples.testdpc.provision.CheckInState;
3029
import com.afwsamples.testdpc.provision.ProvisioningUtil;
3130

32-
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
33-
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
34-
import static android.content.pm.PackageManager.DONT_KILL_APP;
31+
import java.util.Arrays;
32+
import java.util.HashSet;
33+
import java.util.Set;
3534

3635
/**
3736
* Receiver for FIRST_ACCOUNT_READY_ACTION from Google Play Service.
37+
* Receiver only matters for Managed Profile flow, so we ignore the broadcast in other cases.
3838
*/
3939
public class FirstAccountReadyBroadcastReceiver extends BroadcastReceiver {
4040
private static final String TAG = "FirstAccountReady";
@@ -45,34 +45,32 @@ public class FirstAccountReadyBroadcastReceiver extends BroadcastReceiver {
4545
public static final String FIRST_ACCOUNT_READY_TIMEOUT_ACTION =
4646
"com.afwsamples.testdpc.FIRST_ACCOUNT_READY_TIMEOUT";
4747

48+
private static final Set<String> SUPPORTED_ACTIONS = new HashSet<>(
49+
Arrays.asList(FIRST_ACCOUNT_READY_ACTION, FIRST_ACCOUNT_READY_TIMEOUT_ACTION));
50+
4851
public void onReceive(Context context, Intent intent) {
4952
final String action = intent.getAction();
5053
Log.d(TAG, "Received: " + action);
51-
if (FIRST_ACCOUNT_READY_ACTION.equals(action) ||
52-
FIRST_ACCOUNT_READY_TIMEOUT_ACTION.equals(action)) {
53-
CheckInState checkInState = new CheckInState(context);
54-
if (checkInState.getFirstAccountState() == CheckInState.FIRST_ACCOUNT_STATE_PENDING) {
55-
int nextState;
56-
if (FIRST_ACCOUNT_READY_ACTION.equals(action)) {
57-
nextState = CheckInState.FIRST_ACCOUNT_STATE_READY;
58-
} else {
59-
nextState = CheckInState.FIRST_ACCOUNT_STATE_TIMEOUT;
60-
}
61-
checkInState.setFirstAccountState(nextState);
62-
ProvisioningUtil.enableProfile(context);
63-
}
64-
// This receiver is disabled in ProvisioningUtil.enableProfile, no more code should
65-
// be put after it.
54+
55+
if (!Util.isManagedProfileOwner(context)) {
56+
Log.d(TAG, "Not a Managed Profile case. Ignoring broadcast.");
57+
return;
6658
}
67-
}
6859

69-
public static void setEnabled(Context context, boolean enabled) {
70-
PackageManager pm = context.getPackageManager();
71-
pm.setComponentEnabledSetting(
72-
new ComponentName(context, FirstAccountReadyBroadcastReceiver.class),
73-
(enabled) ? COMPONENT_ENABLED_STATE_ENABLED : COMPONENT_ENABLED_STATE_DISABLED,
74-
DONT_KILL_APP
75-
);
60+
if (!SUPPORTED_ACTIONS.contains(action)) {
61+
Log.d(TAG, String.format("Action %s not supported by receiver %s. Ignoring broadcast.",
62+
action, getClass().getName()));
63+
return;
64+
}
65+
66+
CheckInState checkInState = new CheckInState(context);
67+
if (checkInState.getFirstAccountState() == CheckInState.FIRST_ACCOUNT_STATE_PENDING) {
68+
checkInState.setFirstAccountState(FIRST_ACCOUNT_READY_ACTION.equals(action)
69+
? CheckInState.FIRST_ACCOUNT_STATE_READY
70+
: CheckInState.FIRST_ACCOUNT_STATE_TIMEOUT);
71+
72+
ProvisioningUtil.enableProfile(context);
73+
}
7674
}
7775

7876
/**

app/src/main/java/com/afwsamples/testdpc/common/BaseSearchablePolicyPreferenceFragment.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.afwsamples.testdpc.common;
22

3-
import android.app.admin.DevicePolicyManager;
43
import android.content.Context;
54
import android.os.Bundle;
65
import android.support.v14.preference.PreferenceFragment;
@@ -162,8 +161,6 @@ public void onBindViewHolder(PreferenceViewHolder holder, int position) {
162161
}
163162
}
164163

165-
public abstract int getPreferenceXml();
166-
167164
/**
168165
* The implementation must not use any variable that only initialzied in life-cycle callback.
169166
* @return whether the preference fragment is available.

app/src/main/java/com/afwsamples/testdpc/common/ProfileOrParentFragment.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@
2323
import android.content.Context;
2424
import android.os.Build.VERSION_CODES;
2525
import android.os.Bundle;
26-
import android.os.UserManager;
2726
import android.support.v13.app.FragmentTabHost;
2827
import android.support.v4.os.BuildCompat;
2928
import android.support.v7.preference.PreferenceManager;
30-
import android.util.Log;
3129
import android.view.LayoutInflater;
3230
import android.view.View;
3331
import android.view.ViewGroup;
@@ -68,7 +66,7 @@ public View onCreateView(
6866
tabHost.setup(getActivity(), getChildFragmentManager(), View.generateViewId());
6967

7068
final boolean showDualTabs =
71-
Util.isManagedProfile(getActivity()) && BuildCompat.isAtLeastN();
69+
Util.isManagedProfileOwner(getActivity()) && BuildCompat.isAtLeastN();
7270

7371
// Tab for the parent profile
7472
if (showDualTabs) {

app/src/main/java/com/afwsamples/testdpc/common/ReflectionUtil.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ public class ReflectionUtil {
2222
* {@link #invoke(Object, String, Class[], Object[])}.
2323
* @return The result of the invocation. {@code null} if {@code void}.
2424
*/
25-
public static Object invoke(Object obj, String methodName, Object... args) {
25+
public static Object invoke(Object obj, String methodName, Object... args)
26+
throws ReflectionIsTemporaryException {
2627
return invoke(obj.getClass(), obj, methodName, args);
2728
}
2829

2930
/**
3031
* Same as {@link #invoke(Object, String, Object...)} but for static methods.
3132
*/
32-
public static Object invoke(Class<?> clazz, String methodName, Object... args) {
33+
public static Object invoke(Class<?> clazz, String methodName, Object... args)
34+
throws ReflectionIsTemporaryException {
3335
return invoke(clazz, null, methodName, args);
3436
}
3537

@@ -48,20 +50,21 @@ public static Object invoke(Class<?> clazz, String methodName, Object... args) {
4850
* @return The result of the invocation. {@code null} if {@code void}.
4951
*/
5052
public static Object invoke(Object obj, String methodName, Class<?>[] parameterTypes,
51-
Object... args) {
53+
Object... args) throws ReflectionIsTemporaryException {
5254
return invoke(obj.getClass(), obj, methodName, parameterTypes, args);
5355
}
5456

5557
/**
5658
* Same as {@link #invoke(Object, String, Class[], Object...)} but for static methods.
5759
*/
5860
public static Object invoke(Class<?> clazz, String methodName, Class<?>[] parameterTypes,
59-
Object... args) {
61+
Object... args) throws ReflectionIsTemporaryException {
6062
return invoke(clazz, null, methodName, parameterTypes, args);
6163
}
6264

6365
/** Resolve the parameter types and invoke the method. */
64-
private static Object invoke(Class<?> clazz, Object obj, String methodName, Object... args) {
66+
private static Object invoke(Class<?> clazz, Object obj, String methodName, Object... args)
67+
throws ReflectionIsTemporaryException {
6568
Class<?> parameterTypes[] = new Class<?>[args.length];
6669
for (int i = 0; i < args.length; ++i) {
6770
parameterTypes[i] = args[i].getClass();
@@ -71,12 +74,13 @@ private static Object invoke(Class<?> clazz, Object obj, String methodName, Obje
7174

7275
/** Resolve the method and invoke it. */
7376
private static Object invoke(Class<?> clazz, Object obj, String methodName,
74-
Class<?>[] parameterTypes, Object... args) {
77+
Class<?>[] parameterTypes, Object... args)
78+
throws ReflectionIsTemporaryException {
7579
try {
7680
return clazz.getMethod(methodName, parameterTypes).invoke(obj, args);
7781
} catch (SecurityException | NoSuchMethodException | IllegalArgumentException
7882
| IllegalAccessException | InvocationTargetException e) {
79-
throw new RuntimeException("Failed to invoke method", e);
83+
throw new ReflectionIsTemporaryException("Failed to invoke method", e);
8084
}
8185
}
8286

@@ -90,11 +94,12 @@ private static Object invoke(Class<?> clazz, Object obj, String methodName,
9094
* @param fieldName The name of the constant field.
9195
* @return The value of the constant.
9296
*/
93-
public static int intConstant(Class<?> clazz, String fieldName) {
97+
public static int intConstant(Class<?> clazz, String fieldName)
98+
throws ReflectionIsTemporaryException {
9499
try {
95100
return clazz.getField(fieldName).getInt(null);
96101
} catch (NoSuchFieldException | IllegalAccessException e) {
97-
throw new RuntimeException("Failed to retrieve constant", e);
102+
throw new ReflectionIsTemporaryException("Failed to retrieve constant", e);
98103
}
99104
}
100105

@@ -108,11 +113,27 @@ public static int intConstant(Class<?> clazz, String fieldName) {
108113
* @param fieldName The name of the constant field.
109114
* @return The value of the constant.
110115
*/
111-
public static String stringConstant(Class<?> clazz, String fieldName) {
116+
public static String stringConstant(Class<?> clazz, String fieldName)
117+
throws ReflectionIsTemporaryException {
112118
try {
113119
return (String) clazz.getField(fieldName).get(null);
114120
} catch (NoSuchFieldException | IllegalAccessException e) {
115-
throw new RuntimeException("Failed to retrieve constant", e);
121+
throw new ReflectionIsTemporaryException("Failed to retrieve constant", e);
122+
}
123+
}
124+
125+
/**
126+
* Thrown when the temporary use of reflection fails to find and use a new API.
127+
*
128+
* This will happen when the API is not yet available in the SDK and TestDPC is running on
129+
* device that isn't running the latest version of the framework and therefore doesn't support
130+
* the API.
131+
*
132+
* To handle this, gracefully fail the operation in progress.
133+
*/
134+
public static class ReflectionIsTemporaryException extends Exception {
135+
public ReflectionIsTemporaryException(String message, Throwable cause) {
136+
super(message, cause);
116137
}
117138
}
118139
}

app/src/main/java/com/afwsamples/testdpc/common/Util.java

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import android.annotation.TargetApi;
2020
import android.app.Notification;
2121
import android.app.NotificationManager;
22+
import android.app.Service;
2223
import android.app.admin.DevicePolicyManager;
2324
import android.content.ActivityNotFoundException;
2425
import android.content.ComponentName;
@@ -112,25 +113,24 @@ public static void updateImageView(Context context, ImageView imageView, Uri uri
112113
}
113114
}
114115

116+
/**
117+
* Return {@code true} iff we are the profile owner of a managed profile.
118+
* Note that profile owner can be in primary user and secondary user too.
119+
*/
115120
@TargetApi(VERSION_CODES.N)
116-
public static boolean isManagedProfile(Context context) {
121+
public static boolean isManagedProfileOwner(Context context) {
122+
final DevicePolicyManager dpm = getDevicePolicyManager(context);
123+
117124
if (BuildCompat.isAtLeastN()) {
118-
DevicePolicyManager devicePolicyManager =
119-
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
120125
try {
121-
return devicePolicyManager.isManagedProfile(
122-
DeviceAdminReceiver.getComponentName(context));
123-
} catch (SecurityException e) {
124-
// This is thrown if there is no active admin so not the managed profile
126+
return dpm.isManagedProfile(DeviceAdminReceiver.getComponentName(context));
127+
} catch (SecurityException ex) {
128+
// This is thrown if we are neither profile owner nor device owner.
125129
return false;
126130
}
127-
} else {
128-
// If user has more than one profile, then we deal with managed profile.
129-
// Unfortunately there is no public API available to distinguish user profile owner
130-
// and managed profile owner. Thus using this hack.
131-
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
132-
return userManager.getUserProfiles().size() > 1;
133131
}
132+
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
133+
return isProfileOwner(context) && userManager.getUserProfiles().size() > 1;
134134
}
135135

136136
@TargetApi(VERSION_CODES.M)
@@ -147,15 +147,13 @@ public static boolean isPrimaryUser(Context context) {
147147

148148
@TargetApi(VERSION_CODES.LOLLIPOP)
149149
public static boolean isDeviceOwner(Context context) {
150-
final DevicePolicyManager dpm =
151-
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
150+
final DevicePolicyManager dpm = getDevicePolicyManager(context);
152151
return dpm.isDeviceOwnerApp(context.getPackageName());
153152
}
154153

155154
@TargetApi(VERSION_CODES.LOLLIPOP)
156155
public static boolean isProfileOwner(Context context) {
157-
final DevicePolicyManager dpm =
158-
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
156+
final DevicePolicyManager dpm = getDevicePolicyManager(context);
159157
return dpm.isProfileOwnerApp(context.getPackageName());
160158
}
161159

@@ -169,8 +167,7 @@ public static List<UserHandle> getBindDeviceAdminTargetUsers(Context context) {
169167
return Collections.emptyList();
170168
}
171169

172-
final DevicePolicyManager dpm =
173-
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
170+
final DevicePolicyManager dpm = getDevicePolicyManager(context);
174171
return dpm.getBindDeviceAdminTargetUsers(DeviceAdminReceiver.getComponentName(context));
175172
}
176173

@@ -206,4 +203,8 @@ public static boolean installCaCertificate(InputStream certificateInputStream,
206203
}
207204
return false;
208205
}
209-
}
206+
207+
private static DevicePolicyManager getDevicePolicyManager(Context context) {
208+
return (DevicePolicyManager)context.getSystemService(Service.DEVICE_POLICY_SERVICE);
209+
}
210+
}

app/src/main/java/com/afwsamples/testdpc/common/preference/DpcPreferenceHelper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ public void disableIfConstraintsNotMet() {
220220
*/
221221
private CharSequence findConstraintViolation() {
222222
if (getDeviceSdkInt() < mMinSdkVersion) {
223-
if (mMinSdkVersion == Build.VERSION_CODES.O) {
223+
// FIXME: Remove this special checking once O is out.
224+
if (mMinSdkVersion >= 26) {
224225
return mContext.getString(R.string.requires_preview_release);
225226
}
226227
return mContext.getString(R.string.requires_android_api_level, mMinSdkVersion);
@@ -262,7 +263,7 @@ private int getCurrentUser() {
262263
return USER_PRIMARY_USER;
263264
}
264265

265-
if (Util.isManagedProfile(mContext)) {
266+
if (Util.isManagedProfileOwner(mContext)) {
266267

267268
return USER_MANAGED_PROFILE;
268269
}

0 commit comments

Comments
 (0)