Skip to content

Commit

Permalink
Android 11 release.
Browse files Browse the repository at this point in the history
  • Loading branch information
jscott1989 committed Sep 14, 2020
2 parents ddfd242 + ec83ab1 commit 0151c77
Show file tree
Hide file tree
Showing 20 changed files with 433 additions and 549 deletions.
3 changes: 1 addition & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ext {
// exactly 1 digit
versionMinor = 0
// exactly 2 digits
versionBuild = 01
versionBuild = 02
}

android {
Expand Down Expand Up @@ -49,7 +49,6 @@ android {
textOutput "stdout"
}


testOptions {
unitTests {
includeAndroidResources = true
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.REQUEST_PASSWORD_COMPLEXITY"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:banner="@drawable/ic_launcher"
android:theme="@style/AppTheme"
android:label="@string/app_name">

Expand All @@ -47,6 +49,10 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.app.action.CHECK_POLICY_COMPLIANCE"/>
<category android:name="android.intent.category.DEFAULT"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.afwsamples.testdpc;

import android.annotation.TargetApi;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.Collections;
import java.util.Set;

/**
* This fragment provides the ability to whitelist cross profile packages
*
* <p>APIs exercised:
* <ul>
* <li> {@link DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)} </li>
* <li> {@link DevicePolicyManager#getCrossProfilePackages(ComponentName)} </li>
* </ul>
*/
@TargetApi(VERSION_CODES.R)
public class CrossProfileAppsWhitelistFragment extends Fragment {
private static final String DELIMITER = "\n";

private View mInflatedView;
private EditText mAppNameEditText;
private Button mResetButton;
private Button mAddButton;
private Button mRemoveButton;
private TextView mAppsList;

private DevicePolicyManager mDevicePolicyManager;
private ComponentName mAdminComponent;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mDevicePolicyManager = getActivity().getSystemService(DevicePolicyManager.class);
mAdminComponent = DeviceAdminReceiver.getComponentName(getActivity());
mInflatedView = inflater.inflate(
R.layout.cross_profile_apps_whitelist, container, false);

mAppNameEditText = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_input);
mResetButton = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_reset_button);
mAddButton = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_add_button);
mRemoveButton = mInflatedView.findViewById(R.id.cross_profile_app_whitelist_remove_button);
mAppsList = mInflatedView.findViewById(R.id.cross_profile_app_list);

setOnClickListeners();
updateCrossProfileAppsList();

return mInflatedView;
}

private void setOnClickListeners() {
mResetButton.setOnClickListener(view -> resetApps());
mAddButton.setOnClickListener(
view -> addApp(mAppNameEditText.getText().toString().toLowerCase().trim()));
mRemoveButton.setOnClickListener(
view -> removeApp(mAppNameEditText.getText().toString().toLowerCase().trim()));
}

private void resetApps() {
mDevicePolicyManager.setCrossProfilePackages(mAdminComponent, Collections.emptySet());
updateCrossProfileAppsList();
}

private void addApp(String app) {
Set<String> currentApps = mDevicePolicyManager.getCrossProfilePackages(mAdminComponent);
currentApps.add(app);
mDevicePolicyManager.setCrossProfilePackages(mAdminComponent, currentApps);
updateCrossProfileAppsList();
}

private void removeApp(String app) {
Set<String> currentApps = mDevicePolicyManager.getCrossProfilePackages(mAdminComponent);
currentApps.remove(app);
mDevicePolicyManager.setCrossProfilePackages(mAdminComponent, currentApps);
updateCrossProfileAppsList();
}

private void updateCrossProfileAppsList(){
Set<String> currentApps = mDevicePolicyManager.getCrossProfilePackages(mAdminComponent);
if (currentApps.isEmpty()) {
mAppsList.setText(R.string.cross_profile_apps_no_whitelisted_apps);
} else {
mAppsList.setText(String.join(DELIMITER, currentApps));
}
}
}
60 changes: 18 additions & 42 deletions app/src/main/java/com/afwsamples/testdpc/common/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@

import android.annotation.TargetApi;
import android.app.Service;
import android.app.UiModeManager;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.preference.PreferenceFragment;
Expand All @@ -52,11 +53,6 @@ public class Util {
private static final String TAG = "Util";
private static final int DEFAULT_BUFFER_SIZE = 4096;

private static final String BROADCAST_ACTION_FRP_CONFIG_CHANGED =
"com.google.android.gms.auth.FRP_CONFIG_CHANGED";
private static final String GMSCORE_PACKAGE = "com.google.android.gms";
private static final String PERSISTENT_DEVICE_OWNER_STATE = "persistentDeviceOwnerState";

// TODO: Update to S when VERSION_CODES.R becomes available.
public static final int R_VERSION_CODE = 30;

Expand Down Expand Up @@ -205,42 +201,6 @@ public static boolean installCaCertificate(InputStream certificateInputStream,
return false;
}

/**
* Returns the persistent device owner state which has been set by the device owner as an app
* restriction on GmsCore or null if there is no such restriction set.
*/
@TargetApi(VERSION_CODES.O)
public static String getPersistentDoStateFromApplicationRestriction(
DevicePolicyManager dpm, ComponentName admin) {
Bundle restrictions = dpm.getApplicationRestrictions(admin, GMSCORE_PACKAGE);
return restrictions.getString(PERSISTENT_DEVICE_OWNER_STATE);
}

/**
* Sets the persistent device owner state by setting a special app restriction on GmsCore and
* notifies GmsCore about the change by sending a broadcast.
*
* @param state The device owner state to be preserved across factory resets. If null, the
* persistent device owner state and the corresponding restiction are cleared.
*/
@TargetApi(VERSION_CODES.O)
public static void setPersistentDoStateWithApplicationRestriction(
Context context, DevicePolicyManager dpm, ComponentName admin, String state) {
Bundle restrictions = dpm.getApplicationRestrictions(admin, GMSCORE_PACKAGE);
if (state == null) {
// Clear the restriction
restrictions.remove(PERSISTENT_DEVICE_OWNER_STATE);
} else {
// Set the restriction
restrictions.putString(PERSISTENT_DEVICE_OWNER_STATE, state);
}
dpm.setApplicationRestrictions(admin, GMSCORE_PACKAGE, restrictions);
Intent broadcastIntent = new Intent(BROADCAST_ACTION_FRP_CONFIG_CHANGED);
broadcastIntent.setPackage(GMSCORE_PACKAGE);
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
context.sendBroadcast(broadcastIntent);
}

/** @return Intent for the default home activity */
public static Intent getHomeIntent() {
final Intent intent = new Intent(Intent.ACTION_MAIN);
Expand All @@ -257,6 +217,17 @@ public static IntentFilter getHomeIntentFilter() {
return filter;
}

/** @return Intent for a launcher activity */
public static Intent getLauncherIntent(Context context) {
Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
if (Util.isRunningOnTvDevice(context)) {
launcherIntent.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
} else {
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
}
return launcherIntent;
}

private static DevicePolicyManager getDevicePolicyManager(Context context) {
return (DevicePolicyManager)context.getSystemService(Service.DEVICE_POLICY_SERVICE);
}
Expand All @@ -268,4 +239,9 @@ public static boolean hasDelegation(Context context, String delegation) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
return dpm.getDelegatedScopes(null, context.getPackageName()).contains(delegation);
}

public static boolean isRunningOnTvDevice(Context context) {
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,31 @@ protected void addNewRow() {
//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.
Bundle bundle = new Bundle();

if(mBundleList != null && mBundleList.size() > 0) {
if (mBundleList != null && mBundleList.size() > 0) {
bundle = clearBundleValues((Bundle) mBundleList.get(0).clone());
}

mAdapter.add(bundle);
showEditDialog(bundle);
}

private Bundle clearBundleValues(Bundle bundle) {
Set<String> keySet = bundle.keySet();
for(String key : keySet) {
Object valueObject = bundle.get(key);
if(valueObject instanceof String) {
bundle.putString(key, "");
} else if(valueObject instanceof Integer) {
bundle.putInt(key, 0);
} else if(valueObject instanceof Boolean) {
bundle.putBoolean(key, false);
} else if(valueObject instanceof Bundle) {
bundle.putBundle(key, clearBundleValues((Bundle) valueObject));
}
}
return bundle;
}

@Override
protected void loadDefault() {}

Expand Down Expand Up @@ -196,22 +214,4 @@ protected String getDisplayName(Bundle entry) {
return String.valueOf("Bundle #" + mBundleList.indexOf(entry));
}
}

private Bundle clearBundleValues(Bundle bundle) {

Set<String> keySet = bundle.keySet();
for(String key : keySet) {
Object valueObject = bundle.get(key);
if(valueObject instanceof String) {
bundle.putString(key, "");
} else if(valueObject instanceof Integer) {
bundle.putInt(key, 0);
} else if(valueObject instanceof Boolean) {
bundle.putBoolean(key, false);
} else if(valueObject instanceof Bundle) {
bundle.putBundle(key, clearBundleValues((Bundle) valueObject));
}
}
return bundle;
}
}

This file was deleted.

Loading

0 comments on commit 0151c77

Please sign in to comment.