Skip to content

Commit 4993f91

Browse files
committed
Add AppStatesService to TestDPC.
Change-Id: I5480c1c7e627efd42c3a10f7ee85add1ed3b009e (cherry picked from commit 565a824d078b3ed6a35118e9957bc01df2dc7b5b)
1 parent 13d31da commit 4993f91

File tree

6 files changed

+125
-0
lines changed

6 files changed

+125
-0
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>
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: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
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;
@@ -65,6 +66,7 @@
6566
import android.support.v7.preference.EditTextPreference;
6667
import android.support.v7.preference.ListPreference;
6768
import android.support.v7.preference.Preference;
69+
import android.support.v7.preference.PreferenceManager;
6870
import android.telephony.TelephonyManager;
6971
import android.text.InputType;
7072
import android.text.TextUtils;
@@ -269,6 +271,7 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
269271
private static final String DISABLE_SCREEN_CAPTURE_KEY = "disable_screen_capture";
270272
private static final String DISABLE_STATUS_BAR = "disable_status_bar";
271273
private static final String ENABLE_BACKUP_SERVICE = "enable_backup_service";
274+
private static final String APP_FEEDBACK_NOTIFICATIONS = "app_feedback_notifications";
272275
private static final String ENABLE_SECURITY_LOGGING = "enable_security_logging";
273276
private static final String ENABLE_NETWORK_LOGGING = "enable_network_logging";
274277
private static final String ENABLE_SYSTEM_APPS_BY_INTENT_KEY = "enable_system_apps_by_intent";
@@ -457,6 +460,8 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
457460

458461
private DpcSwitchPreference mAutoBrightnessPreference;
459462

463+
private DpcSwitchPreference mEnableAppFeedbackNotificationsPreference;
464+
460465
private GetAccessibilityServicesTask mGetAccessibilityServicesTask = null;
461466
private GetInputMethodsTask mGetInputMethodsTask = null;
462467
private GetNotificationListenersTask mGetNotificationListenersTask = null;
@@ -595,6 +600,9 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
595600
findPreference(REMOVE_ACCOUNT_KEY).setOnPreferenceClickListener(this);
596601
findPreference(BLOCK_UNINSTALLATION_BY_PKG_KEY).setOnPreferenceClickListener(this);
597602
findPreference(BLOCK_UNINSTALLATION_LIST_KEY).setOnPreferenceClickListener(this);
603+
findPreference(APP_FEEDBACK_NOTIFICATIONS).setOnPreferenceChangeListener(this);
604+
mEnableAppFeedbackNotificationsPreference =
605+
(DpcSwitchPreference) findPreference(APP_FEEDBACK_NOTIFICATIONS);
598606
findPreference(ENABLE_SYSTEM_APPS_KEY).setOnPreferenceClickListener(this);
599607
findPreference(ENABLE_SYSTEM_APPS_BY_PACKAGE_NAME_KEY).setOnPreferenceClickListener(this);
600608
findPreference(ENABLE_SYSTEM_APPS_BY_INTENT_KEY).setOnPreferenceClickListener(this);
@@ -682,6 +690,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
682690
constrainSpecialCasePreferences();
683691

684692
maybeDisableLockTaskPreferences();
693+
loadAppFeedbackNotifications();
685694
loadAppStatus();
686695
loadSecurityPatch();
687696
loadIsEphemeralUserUi();
@@ -1326,6 +1335,14 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
13261335
Integer.parseInt((String) newValue));
13271336
startActivity(intent);
13281337
return true;
1338+
case APP_FEEDBACK_NOTIFICATIONS:
1339+
SharedPreferences.Editor editor =
1340+
PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
1341+
editor.putBoolean(
1342+
getString(
1343+
R.string.app_feedback_notifications), newValue.equals(true));
1344+
editor.commit();
1345+
return true;
13291346
}
13301347
return false;
13311348
}
@@ -2080,6 +2097,13 @@ public void onClick(DialogInterface dialogInterface, int i) {
20802097
.show();
20812098
}
20822099

2100+
@TargetApi(Build.VERSION_CODES.M)
2101+
private void loadAppFeedbackNotifications() {
2102+
mEnableAppFeedbackNotificationsPreference.setChecked(
2103+
PreferenceManager.getDefaultSharedPreferences(getContext())
2104+
.getBoolean(getString(R.string.app_feedback_notifications), false));
2105+
}
2106+
20832107
private void loadAppStatus() {
20842108
final @StringRes int appStatusStringId;
20852109
if (mDevicePolicyManager.isProfileOwnerApp(mPackageName)) {

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,10 @@
548548
<string name="plus">+</string>
549549
<string name="app_restrictions_managing_package">App restrictions manager</string>
550550

551+
<!-- Strings for app feedback -->
552+
<!-- [CHAR LIMIT=40] Settings label. A user can toggle this setting to turn on notifications for app feedback. -->
553+
<string name="app_feedback_notifications">App feedback notifications</string>
554+
551555
<!-- Strings for metered data restriction -->
552556
<string name="metered_data_restriction">Disable metered data</string>
553557
<string name="update_pkgs">Update</string>

app/src/main/res/xml/device_policy_header.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@
178178
android:title="@string/metered_data_restriction"
179179
testdpc:admin="deviceOwner|profileOwner"
180180
testdpc:minSdkVersion="P" />
181+
<com.afwsamples.testdpc.common.preference.DpcSwitchPreference
182+
android:key="app_feedback_notifications"
183+
android:title="@string/app_feedback_notifications"
184+
testdpc:admin="deviceOwner|profileOwner"
185+
testdpc:minSdkVersion="N" />
181186
</PreferenceCategory>
182187

183188
<PreferenceCategory android:title="@string/delegation_title">

0 commit comments

Comments
 (0)