Skip to content

Commit ca648d0

Browse files
author
android-build-team Robot
committed
Snap for 5477216 from 351bc563f87a9b6bc201d2cf369bcc263594f6ba to ub-testdpc-qt-release
Change-Id: Ief1ba6ac17b33396831b44c2c3017ce806f2a18d
2 parents 84bd104 + 9e0578f commit ca648d0

17 files changed

+220
-33
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ private void stripTestOnlyForBuild(flavor, buildType) {
125125
}
126126

127127
dependencies {
128+
implementation 'androidx.enterprise:enterprise-feedback:1.0.0-alpha01'
128129
implementation 'com.android.support:multidex:1.0.1'
129130
implementation 'com.android.support:preference-v14:28.0.0-SNAPSHOT'
130131
implementation 'com.android.support:recyclerview-v7:28.0.0-SNAPSHOT'

app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@
197197
</intent-filter>
198198
</service>
199199

200+
<service android:name=".feedback.AppStatesService">
201+
<intent-filter>
202+
<action android:name="androidx.enterprise.feedback.action.APP_STATES" />
203+
</intent-filter>
204+
</service>
205+
200206
</application>
201207

202208
</manifest>

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public void setCustomConstraint(@Nullable CustomConstraint customConstraint) {
103103
mHelper.setCustomConstraint(customConstraint);
104104
}
105105

106+
@Override
107+
public void addCustomConstraint(@Nullable CustomConstraint customConstraint) {
108+
mHelper.addCustomConstraint(customConstraint);
109+
}
110+
106111
@Override
107112
public void refreshEnabledState() {
108113
mHelper.disableIfConstraintsNotMet();

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public void setCustomConstraint(@Nullable CustomConstraint customConstraint) {
103103
mHelper.setCustomConstraint(customConstraint);
104104
}
105105

106+
@Override
107+
public void addCustomConstraint(@Nullable CustomConstraint customConstraint) {
108+
mHelper.addCustomConstraint(customConstraint);
109+
}
110+
106111
@Override
107112
public void refreshEnabledState() {
108113
mHelper.disableIfConstraintsNotMet();

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public void setCustomConstraint(@Nullable CustomConstraint customConstraint) {
103103
mHelper.setCustomConstraint(customConstraint);
104104
}
105105

106+
@Override
107+
public void addCustomConstraint(@Nullable CustomConstraint customConstraint) {
108+
mHelper.addCustomConstraint(customConstraint);
109+
}
110+
106111
@Override
107112
public void refreshEnabledState() {
108113
mHelper.disableIfConstraintsNotMet();

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public interface DpcPreferenceBase {
2929
void clearUserConstraint();
3030
void clearNonCustomConstraints();
3131
void setCustomConstraint(@Nullable CustomConstraint customConstraint);
32+
void addCustomConstraint(@Nullable CustomConstraint customConstraint);
3233
/**
3334
* To re-check is the constraint met and enable/disable the preference accordingly.
3435
*/

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public class DpcPreferenceHelper {
8181
private Preference mPreference;
8282

8383
private CharSequence mConstraintViolationSummary = null;
84-
private CustomConstraint mCustomConstraint = null;
84+
private List<CustomConstraint> mCustomConstraints = new ArrayList<>();
8585
private int mMinSdkVersion;
8686
private @AdminKind int mAdminConstraint;
8787
private @UserKind int mUserConstraint;
@@ -194,19 +194,37 @@ public void clearNonCustomConstraints() {
194194
/**
195195
* Specify a custom constraint by setting a {{@link CustomConstraint}} object. The enabled
196196
* state of the preference will be updated accordingly.
197+
*
198+
* <p>This will remove all previously set custom constraints. If you do not want to do this, use
199+
* {@link #addCustomConstraint(CustomConstraint)}.
197200
*/
198201
public void setCustomConstraint(CustomConstraint customConstraint) {
199-
mCustomConstraint = customConstraint;
202+
clearCustomConstraints();
203+
addCustomConstraint(customConstraint);
204+
}
205+
206+
/**
207+
* Add a {@link CustomConstraint} to be evaluated in addition to existing custom constraints.
208+
*
209+
* <p>The enabled state of the preference will be updated accordingly.
210+
*
211+
* <p>The new constraint will be enforced in addition to any previously set custom constraints.
212+
* If you'd prefer that this constraint replaces previous constraints,
213+
* use {@link #setCustomConstraint(CustomConstraint)}.
214+
*/
215+
public void addCustomConstraint(CustomConstraint customConstraint) {
216+
mCustomConstraints.add(customConstraint);
200217
disableIfConstraintsNotMet();
201218
}
202219

203220
/**
204-
* Remove any custom constraints set by {@link #setCustomConstraint(CustomConstraint)}.
205-
* <p/>
206-
* This method is safe to call if there is no current custom constraint.
221+
* Remove any custom constraints set by {@link #setCustomConstraint(CustomConstraint)} and
222+
* {@link #addCustomConstraint(CustomConstraint)}.
223+
*
224+
* <p>This method is safe to call if there is no current custom constraint.
207225
*/
208-
public void clearCustomConstraint() {
209-
setCustomConstraint(null);
226+
public void clearCustomConstraints() {
227+
mCustomConstraints.clear();
210228
}
211229

212230
public void disableIfConstraintsNotMet() {
@@ -233,8 +251,8 @@ private CharSequence findConstraintViolation() {
233251
return getUserConstraintSummary();
234252
}
235253

236-
if (mCustomConstraint != null) {
237-
@StringRes int strRes = mCustomConstraint.validateConstraint();
254+
for (CustomConstraint customConstraint : mCustomConstraints) {
255+
@StringRes int strRes = customConstraint.validateConstraint();
238256
if (strRes != NO_CUSTOM_CONSTRIANT) {
239257
return mContext.getString(strRes);
240258
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public void setCustomConstraint(@Nullable CustomConstraint customConstraint) {
103103
mHelper.setCustomConstraint(customConstraint);
104104
}
105105

106+
@Override
107+
public void addCustomConstraint(@Nullable CustomConstraint customConstraint) {
108+
mHelper.addCustomConstraint(customConstraint);
109+
}
110+
106111
@Override
107112
public void refreshEnabledState() {
108113
mHelper.disableIfConstraintsNotMet();
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.afwsamples.testdpc.feedback;
2+
3+
import android.app.NotificationChannel;
4+
import android.app.NotificationManager;
5+
import android.os.Build;
6+
import android.support.v4.app.NotificationCompat;
7+
import android.support.v4.app.NotificationManagerCompat;
8+
import android.support.v7.preference.PreferenceManager;
9+
import android.util.Log;
10+
import androidx.enterprise.feedback.KeyedAppState;
11+
import androidx.enterprise.feedback.KeyedAppStatesService;
12+
import androidx.enterprise.feedback.ReceivedKeyedAppState;
13+
import com.afwsamples.testdpc.R;
14+
import java.util.Collection;
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
18+
/**
19+
* Receive {@link KeyedAppState} instances and show them as a notification.
20+
*
21+
* <p>Also logs received keyed app states using the tag "KeyedAppStates".
22+
*/
23+
public class AppStatesService extends KeyedAppStatesService {
24+
25+
private static final String CHANNEL_ID = "KeyedAppStates";
26+
private static final String CHANNEL_NAME = "Keyed App States";
27+
28+
private int nextNotificationId = 0;
29+
private Map<String, Integer> idMapping = new HashMap<>();
30+
31+
@Override
32+
public void onReceive(Collection<ReceivedKeyedAppState> states, boolean requestSync) {
33+
boolean shouldNotify =
34+
PreferenceManager.getDefaultSharedPreferences(this)
35+
.getBoolean(getString(R.string.app_feedback_notifications), false);
36+
37+
if (!shouldNotify) {
38+
return;
39+
}
40+
41+
createNotificationChannel();
42+
43+
for (ReceivedKeyedAppState state : states) {
44+
showNotification(state, requestSync);
45+
}
46+
}
47+
48+
private void showNotification(ReceivedKeyedAppState state, boolean requestSync) {
49+
Log.i("KeyedAppStates",
50+
state.timestamp() + " " +
51+
state.packageName() + ":" +
52+
state.key() + "=" +
53+
state.data() + " (" +
54+
state.message() + ")" + (requestSync ? " - SYNC REQUESTED" : ""));
55+
56+
NotificationCompat.Builder notificationBuilder =
57+
new NotificationCompat.Builder(this, CHANNEL_ID)
58+
.setSmallIcon(R.drawable.arrow_down)
59+
.setContentTitle(state.packageName() + ":" + state.key())
60+
.setContentText(state.timestamp() + " " +
61+
state.data() +
62+
" (" + state.message() +")" +
63+
(requestSync ? "\nSYNC REQUESTED" : ""));
64+
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
65+
notificationManager.notify(getIdForState(state), notificationBuilder.build());
66+
}
67+
68+
private void createNotificationChannel() {
69+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
70+
NotificationChannel channel =
71+
new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
72+
NotificationManager notificationManager = getSystemService(NotificationManager.class);
73+
notificationManager.createNotificationChannel(channel);
74+
}
75+
}
76+
77+
private int getIdForState(ReceivedKeyedAppState state) {
78+
String key = state.packageName() + ":" + state.key();
79+
80+
if (!idMapping.containsKey(key)) {
81+
idMapping.put(key, nextNotificationId++);
82+
}
83+
return idMapping.get(key);
84+
}
85+
}

app/src/main/java/com/afwsamples/testdpc/policy/PolicyManagementFragment.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@
3434
import android.app.Fragment;
3535
import android.app.FragmentManager;
3636
import android.app.admin.DevicePolicyManager;
37-
import android.app.admin.DevicePolicyManager.InstallUpdateCallback;
37+
import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback;
3838
import android.app.admin.SystemUpdateInfo;
3939
import android.content.ComponentName;
4040
import android.content.ContentResolver;
4141
import android.content.Context;
4242
import android.content.DialogInterface;
4343
import android.content.Intent;
44+
import android.content.SharedPreferences;
4445
import android.content.pm.ApplicationInfo;
4546
import android.content.pm.PackageManager;
4647
import android.content.pm.ResolveInfo;
@@ -49,6 +50,7 @@
4950
import android.os.AsyncTask;
5051
import android.os.BatteryManager;
5152
import android.os.Build;
53+
import android.os.Build.VERSION_CODES;
5254
import android.os.Bundle;
5355
import android.os.UserHandle;
5456
import android.os.UserManager;
@@ -65,6 +67,7 @@
6567
import android.support.v7.preference.EditTextPreference;
6668
import android.support.v7.preference.ListPreference;
6769
import android.support.v7.preference.Preference;
70+
import android.support.v7.preference.PreferenceManager;
6871
import android.telephony.TelephonyManager;
6972
import android.text.InputType;
7073
import android.text.TextUtils;
@@ -269,6 +272,7 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
269272
private static final String DISABLE_SCREEN_CAPTURE_KEY = "disable_screen_capture";
270273
private static final String DISABLE_STATUS_BAR = "disable_status_bar";
271274
private static final String ENABLE_BACKUP_SERVICE = "enable_backup_service";
275+
private static final String APP_FEEDBACK_NOTIFICATIONS = "app_feedback_notifications";
272276
private static final String ENABLE_SECURITY_LOGGING = "enable_security_logging";
273277
private static final String ENABLE_NETWORK_LOGGING = "enable_network_logging";
274278
private static final String ENABLE_SYSTEM_APPS_BY_INTENT_KEY = "enable_system_apps_by_intent";
@@ -457,6 +461,8 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
457461

458462
private DpcSwitchPreference mAutoBrightnessPreference;
459463

464+
private DpcSwitchPreference mEnableAppFeedbackNotificationsPreference;
465+
460466
private GetAccessibilityServicesTask mGetAccessibilityServicesTask = null;
461467
private GetInputMethodsTask mGetInputMethodsTask = null;
462468
private GetNotificationListenersTask mGetNotificationListenersTask = null;
@@ -545,15 +551,19 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
545551
mDisableStatusBarPreference = (DpcPreference) findPreference(DISABLE_STATUS_BAR);
546552
mDisableStatusBarPreference.setOnPreferenceClickListener(this);
547553
mDisableStatusBarPreference.setCustomConstraint(this::validateAffiliatedUserAfterP);
554+
mDisableStatusBarPreference.addCustomConstraint(this::validateDeviceOwnerBeforeP);
548555
mReenableStatusBarPreference = (DpcPreference) findPreference(REENABLE_STATUS_BAR);
549556
mReenableStatusBarPreference.setOnPreferenceClickListener(this);
550557
mReenableStatusBarPreference.setCustomConstraint(this::validateAffiliatedUserAfterP);
558+
mReenableStatusBarPreference.addCustomConstraint(this::validateDeviceOwnerBeforeP);
551559
mDisableKeyguardPreference = (DpcPreference) findPreference(DISABLE_KEYGUARD);
552560
mDisableKeyguardPreference.setOnPreferenceClickListener(this);
553561
mDisableKeyguardPreference.setCustomConstraint(this::validateAffiliatedUserAfterP);
562+
mDisableKeyguardPreference.addCustomConstraint(this::validateDeviceOwnerBeforeP);
554563
mReenableKeyguardPreference = (DpcPreference) findPreference(REENABLE_KEYGUARD);
555564
mReenableKeyguardPreference.setOnPreferenceClickListener(this);
556565
mReenableKeyguardPreference.setCustomConstraint(this::validateAffiliatedUserAfterP);
566+
mReenableKeyguardPreference.addCustomConstraint(this::validateDeviceOwnerBeforeP);
557567
findPreference(START_KIOSK_MODE).setOnPreferenceClickListener(this);
558568
mStayOnWhilePluggedInSwitchPreference = (SwitchPreference) findPreference(
559569
STAY_ON_WHILE_PLUGGED_IN);
@@ -595,6 +605,9 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
595605
findPreference(REMOVE_ACCOUNT_KEY).setOnPreferenceClickListener(this);
596606
findPreference(BLOCK_UNINSTALLATION_BY_PKG_KEY).setOnPreferenceClickListener(this);
597607
findPreference(BLOCK_UNINSTALLATION_LIST_KEY).setOnPreferenceClickListener(this);
608+
findPreference(APP_FEEDBACK_NOTIFICATIONS).setOnPreferenceChangeListener(this);
609+
mEnableAppFeedbackNotificationsPreference =
610+
(DpcSwitchPreference) findPreference(APP_FEEDBACK_NOTIFICATIONS);
598611
findPreference(ENABLE_SYSTEM_APPS_KEY).setOnPreferenceClickListener(this);
599612
findPreference(ENABLE_SYSTEM_APPS_BY_PACKAGE_NAME_KEY).setOnPreferenceClickListener(this);
600613
findPreference(ENABLE_SYSTEM_APPS_BY_INTENT_KEY).setOnPreferenceClickListener(this);
@@ -682,6 +695,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
682695
constrainSpecialCasePreferences();
683696

684697
maybeDisableLockTaskPreferences();
698+
loadAppFeedbackNotifications();
685699
loadAppStatus();
686700
loadSecurityPatch();
687701
loadIsEphemeralUserUi();
@@ -1151,7 +1165,7 @@ private void installUpdate() {
11511165
mAdminComponentName,
11521166
uri,
11531167
new MainThreadExecutor(),
1154-
new InstallUpdateCallback() {
1168+
new InstallSystemUpdateCallback() {
11551169
@Override
11561170
public void onInstallUpdateError(int errorCode, String errorMessage) {
11571171
showToast("Error code: " + errorCode);
@@ -1326,6 +1340,14 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
13261340
Integer.parseInt((String) newValue));
13271341
startActivity(intent);
13281342
return true;
1343+
case APP_FEEDBACK_NOTIFICATIONS:
1344+
SharedPreferences.Editor editor =
1345+
PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
1346+
editor.putBoolean(
1347+
getString(
1348+
R.string.app_feedback_notifications), newValue.equals(true));
1349+
editor.commit();
1350+
return true;
13291351
}
13301352
return false;
13311353
}
@@ -2080,6 +2102,13 @@ public void onClick(DialogInterface dialogInterface, int i) {
20802102
.show();
20812103
}
20822104

2105+
@TargetApi(Build.VERSION_CODES.M)
2106+
private void loadAppFeedbackNotifications() {
2107+
mEnableAppFeedbackNotificationsPreference.setChecked(
2108+
PreferenceManager.getDefaultSharedPreferences(getContext())
2109+
.getBoolean(getString(R.string.app_feedback_notifications), false));
2110+
}
2111+
20832112
private void loadAppStatus() {
20842113
final @StringRes int appStatusStringId;
20852114
if (mDevicePolicyManager.isProfileOwnerApp(mPackageName)) {
@@ -3575,19 +3604,21 @@ private void removeAccount(Account account) {
35753604

35763605
@TargetApi(28)
35773606
private int validateAffiliatedUserAfterP() {
3578-
if (BuildCompat.isAtLeastP()) {
3579-
if (mDevicePolicyManager.isAffiliatedUser()) {
3580-
return NO_CUSTOM_CONSTRIANT;
3581-
} else {
3607+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
3608+
if (!mDevicePolicyManager.isAffiliatedUser()) {
35823609
return R.string.require_affiliated_user;
35833610
}
3584-
} else {
3585-
if (mDevicePolicyManager.isDeviceOwnerApp(mPackageName)) {
3586-
return NO_CUSTOM_CONSTRIANT;
3587-
} else {
3611+
}
3612+
return NO_CUSTOM_CONSTRIANT;
3613+
}
3614+
3615+
private int validateDeviceOwnerBeforeP() {
3616+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
3617+
if (!mDevicePolicyManager.isDeviceOwnerApp(mPackageName)) {
35883618
return R.string.requires_device_owner;
35893619
}
35903620
}
3621+
return NO_CUSTOM_CONSTRIANT;
35913622
}
35923623

35933624
abstract class ManageLockTaskListCallback {

0 commit comments

Comments
 (0)