Skip to content

Commit 0151c77

Browse files
committed
Android 11 release.
2 parents ddfd242 + ec83ab1 commit 0151c77

20 files changed

+433
-549
lines changed

app/build.gradle

+1-2
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 = 01
10+
versionBuild = 02
1111
}
1212

1313
android {
@@ -49,7 +49,6 @@ android {
4949
textOutput "stdout"
5050
}
5151

52-
5352
testOptions {
5453
unitTests {
5554
includeAndroidResources = true

app/src/main/AndroidManifest.xml

+6
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3232
<uses-permission android:name="android.permission.REQUEST_PASSWORD_COMPLEXITY"/>
3333
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
34+
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
3435

3536
<application
3637
android:allowBackup="true"
3738
android:icon="@drawable/ic_launcher"
39+
android:banner="@drawable/ic_launcher"
3840
android:theme="@style/AppTheme"
3941
android:label="@string/app_name">
4042

@@ -47,6 +49,10 @@
4749
<action android:name="android.intent.action.MAIN"/>
4850
<category android:name="android.intent.category.LAUNCHER"/>
4951
</intent-filter>
52+
<intent-filter>
53+
<action android:name="android.intent.action.MAIN"/>
54+
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
55+
</intent-filter>
5056
<intent-filter>
5157
<action android:name="android.app.action.CHECK_POLICY_COMPLIANCE"/>
5258
<category android:name="android.intent.category.DEFAULT"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (C) 2020 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.afwsamples.testdpc;
17+
18+
import android.annotation.TargetApi;
19+
import android.app.Fragment;
20+
import android.app.admin.DevicePolicyManager;
21+
import android.content.ComponentName;
22+
import android.os.Build.VERSION_CODES;
23+
import android.os.Bundle;
24+
import android.view.LayoutInflater;
25+
import android.view.View;
26+
import android.view.ViewGroup;
27+
import android.widget.Button;
28+
import android.widget.EditText;
29+
import android.widget.TextView;
30+
import java.util.Collections;
31+
import java.util.Set;
32+
33+
/**
34+
* This fragment provides the ability to whitelist cross profile packages
35+
*
36+
* <p>APIs exercised:
37+
* <ul>
38+
* <li> {@link DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)} </li>
39+
* <li> {@link DevicePolicyManager#getCrossProfilePackages(ComponentName)} </li>
40+
* </ul>
41+
*/
42+
@TargetApi(VERSION_CODES.R)
43+
public class CrossProfileAppsWhitelistFragment extends Fragment {
44+
private static final String DELIMITER = "\n";
45+
46+
private View mInflatedView;
47+
private EditText mAppNameEditText;
48+
private Button mResetButton;
49+
private Button mAddButton;
50+
private Button mRemoveButton;
51+
private TextView mAppsList;
52+
53+
private DevicePolicyManager mDevicePolicyManager;
54+
private ComponentName mAdminComponent;
55+
56+
@Override
57+
public View onCreateView(LayoutInflater inflater, ViewGroup container,
58+
Bundle savedInstanceState) {
59+
mDevicePolicyManager = getActivity().getSystemService(DevicePolicyManager.class);
60+
mAdminComponent = DeviceAdminReceiver.getComponentName(getActivity());
61+
mInflatedView = inflater.inflate(
62+
R.layout.cross_profile_apps_whitelist, container, false);
63+
64+
mAppNameEditText = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_input);
65+
mResetButton = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_reset_button);
66+
mAddButton = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_add_button);
67+
mRemoveButton = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_remove_button);
68+
mAppsList = mInflatedView.findViewById(R.id.cross_profile_app_list);
69+
70+
setOnClickListeners();
71+
updateCrossProfileAppsList();
72+
73+
return mInflatedView;
74+
}
75+
76+
private void setOnClickListeners() {
77+
mResetButton.setOnClickListener(view -> resetApps());
78+
mAddButton.setOnClickListener(
79+
view -> addApp(mAppNameEditText.getText().toString().toLowerCase().trim()));
80+
mRemoveButton.setOnClickListener(
81+
view -> removeApp(mAppNameEditText.getText().toString().toLowerCase().trim()));
82+
}
83+
84+
private void resetApps() {
85+
mDevicePolicyManager.setCrossProfilePackages(mAdminComponent, Collections.emptySet());
86+
updateCrossProfileAppsList();
87+
}
88+
89+
private void addApp(String app) {
90+
Set<String> currentApps = mDevicePolicyManager.getCrossProfilePackages(mAdminComponent);
91+
currentApps.add(app);
92+
mDevicePolicyManager.setCrossProfilePackages(mAdminComponent, currentApps);
93+
updateCrossProfileAppsList();
94+
}
95+
96+
private void removeApp(String app) {
97+
Set<String> currentApps = mDevicePolicyManager.getCrossProfilePackages(mAdminComponent);
98+
currentApps.remove(app);
99+
mDevicePolicyManager.setCrossProfilePackages(mAdminComponent, currentApps);
100+
updateCrossProfileAppsList();
101+
}
102+
103+
private void updateCrossProfileAppsList(){
104+
Set<String> currentApps = mDevicePolicyManager.getCrossProfilePackages(mAdminComponent);
105+
if (currentApps.isEmpty()) {
106+
mAppsList.setText(R.string.cross_profile_apps_no_whitelisted_apps);
107+
} else {
108+
mAppsList.setText(String.join(DELIMITER, currentApps));
109+
}
110+
}
111+
}

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

+18-42
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@
1818

1919
import android.annotation.TargetApi;
2020
import android.app.Service;
21+
import android.app.UiModeManager;
2122
import android.app.admin.DevicePolicyManager;
2223
import android.content.ActivityNotFoundException;
2324
import android.content.ComponentName;
2425
import android.content.Context;
2526
import android.content.Intent;
2627
import android.content.IntentFilter;
28+
import android.content.res.Configuration;
2729
import android.graphics.BitmapFactory;
2830
import android.net.Uri;
2931
import android.os.Build.VERSION;
3032
import android.os.Build.VERSION_CODES;
31-
import android.os.Bundle;
3233
import android.os.UserHandle;
3334
import android.os.UserManager;
3435
import androidx.preference.PreferenceFragment;
@@ -52,11 +53,6 @@ public class Util {
5253
private static final String TAG = "Util";
5354
private static final int DEFAULT_BUFFER_SIZE = 4096;
5455

55-
private static final String BROADCAST_ACTION_FRP_CONFIG_CHANGED =
56-
"com.google.android.gms.auth.FRP_CONFIG_CHANGED";
57-
private static final String GMSCORE_PACKAGE = "com.google.android.gms";
58-
private static final String PERSISTENT_DEVICE_OWNER_STATE = "persistentDeviceOwnerState";
59-
6056
// TODO: Update to S when VERSION_CODES.R becomes available.
6157
public static final int R_VERSION_CODE = 30;
6258

@@ -205,42 +201,6 @@ public static boolean installCaCertificate(InputStream certificateInputStream,
205201
return false;
206202
}
207203

208-
/**
209-
* Returns the persistent device owner state which has been set by the device owner as an app
210-
* restriction on GmsCore or null if there is no such restriction set.
211-
*/
212-
@TargetApi(VERSION_CODES.O)
213-
public static String getPersistentDoStateFromApplicationRestriction(
214-
DevicePolicyManager dpm, ComponentName admin) {
215-
Bundle restrictions = dpm.getApplicationRestrictions(admin, GMSCORE_PACKAGE);
216-
return restrictions.getString(PERSISTENT_DEVICE_OWNER_STATE);
217-
}
218-
219-
/**
220-
* Sets the persistent device owner state by setting a special app restriction on GmsCore and
221-
* notifies GmsCore about the change by sending a broadcast.
222-
*
223-
* @param state The device owner state to be preserved across factory resets. If null, the
224-
* persistent device owner state and the corresponding restiction are cleared.
225-
*/
226-
@TargetApi(VERSION_CODES.O)
227-
public static void setPersistentDoStateWithApplicationRestriction(
228-
Context context, DevicePolicyManager dpm, ComponentName admin, String state) {
229-
Bundle restrictions = dpm.getApplicationRestrictions(admin, GMSCORE_PACKAGE);
230-
if (state == null) {
231-
// Clear the restriction
232-
restrictions.remove(PERSISTENT_DEVICE_OWNER_STATE);
233-
} else {
234-
// Set the restriction
235-
restrictions.putString(PERSISTENT_DEVICE_OWNER_STATE, state);
236-
}
237-
dpm.setApplicationRestrictions(admin, GMSCORE_PACKAGE, restrictions);
238-
Intent broadcastIntent = new Intent(BROADCAST_ACTION_FRP_CONFIG_CHANGED);
239-
broadcastIntent.setPackage(GMSCORE_PACKAGE);
240-
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
241-
context.sendBroadcast(broadcastIntent);
242-
}
243-
244204
/** @return Intent for the default home activity */
245205
public static Intent getHomeIntent() {
246206
final Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -257,6 +217,17 @@ public static IntentFilter getHomeIntentFilter() {
257217
return filter;
258218
}
259219

220+
/** @return Intent for a launcher activity */
221+
public static Intent getLauncherIntent(Context context) {
222+
Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
223+
if (Util.isRunningOnTvDevice(context)) {
224+
launcherIntent.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
225+
} else {
226+
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
227+
}
228+
return launcherIntent;
229+
}
230+
260231
private static DevicePolicyManager getDevicePolicyManager(Context context) {
261232
return (DevicePolicyManager)context.getSystemService(Service.DEVICE_POLICY_SERVICE);
262233
}
@@ -268,4 +239,9 @@ public static boolean hasDelegation(Context context, String delegation) {
268239
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
269240
return dpm.getDelegatedScopes(null, context.getPackageName()).contains(delegation);
270241
}
242+
243+
public static boolean isRunningOnTvDevice(Context context) {
244+
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
245+
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
246+
}
271247
}

app/src/main/java/com/afwsamples/testdpc/common/keyvaluepair/KeyValueBundleArrayFragment.java

+19-19
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,31 @@ protected void addNewRow() {
135135
//no need to re-create all the keys again in new created bundle, just automatically copy all keys from the existing one. This is extremely useful when the first bundle contains lots of keys.
136136
Bundle bundle = new Bundle();
137137

138-
if(mBundleList != null && mBundleList.size() > 0) {
138+
if (mBundleList != null && mBundleList.size() > 0) {
139139
bundle = clearBundleValues((Bundle) mBundleList.get(0).clone());
140140
}
141+
141142
mAdapter.add(bundle);
142143
showEditDialog(bundle);
143144
}
144145

146+
private Bundle clearBundleValues(Bundle bundle) {
147+
Set<String> keySet = bundle.keySet();
148+
for(String key : keySet) {
149+
Object valueObject = bundle.get(key);
150+
if(valueObject instanceof String) {
151+
bundle.putString(key, "");
152+
} else if(valueObject instanceof Integer) {
153+
bundle.putInt(key, 0);
154+
} else if(valueObject instanceof Boolean) {
155+
bundle.putBoolean(key, false);
156+
} else if(valueObject instanceof Bundle) {
157+
bundle.putBundle(key, clearBundleValues((Bundle) valueObject));
158+
}
159+
}
160+
return bundle;
161+
}
162+
145163
@Override
146164
protected void loadDefault() {}
147165

@@ -196,22 +214,4 @@ protected String getDisplayName(Bundle entry) {
196214
return String.valueOf("Bundle #" + mBundleList.indexOf(entry));
197215
}
198216
}
199-
200-
private Bundle clearBundleValues(Bundle bundle) {
201-
202-
Set<String> keySet = bundle.keySet();
203-
for(String key : keySet) {
204-
Object valueObject = bundle.get(key);
205-
if(valueObject instanceof String) {
206-
bundle.putString(key, "");
207-
} else if(valueObject instanceof Integer) {
208-
bundle.putInt(key, 0);
209-
} else if(valueObject instanceof Boolean) {
210-
bundle.putBoolean(key, false);
211-
} else if(valueObject instanceof Bundle) {
212-
bundle.putBundle(key, clearBundleValues((Bundle) valueObject));
213-
}
214-
}
215-
return bundle;
216-
}
217217
}

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

-77
This file was deleted.

0 commit comments

Comments
 (0)