398398import android.content.res.Resources;
399399import android.database.ContentObserver;
400400import android.database.Cursor;
401+ import android.ext.PackageId;
401402import android.graphics.Bitmap;
402403import android.hardware.usb.UsbManager;
403404import android.location.Location;
@@ -581,7 +582,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
581582
582583 private static final String ATTRIBUTION_TAG = "DevicePolicyManagerService";
583584
584- static final boolean VERBOSE_LOG = false ; // DO NOT SUBMIT WITH TRUE
585+ static final boolean VERBOSE_LOG = true ; // DO NOT SUBMIT WITH TRUE
585586
586587 static final String DEVICE_POLICIES_XML = "device_policies.xml";
587588
@@ -10960,7 +10961,7 @@ private boolean canDPCManagedUserUseLockTaskLocked(int userId) {
1096010961 if (mOwners.hasDeviceOwner()) {
1096110962 return false;
1096210963 }
10963-
10964+
1096410965 final ComponentName profileOwner = getProfileOwnerAsUser(userId);
1096510966 if (profileOwner == null) {
1096610967 return false;
@@ -10969,7 +10970,7 @@ private boolean canDPCManagedUserUseLockTaskLocked(int userId) {
1096910970 if (isManagedProfile(userId)) {
1097010971 return false;
1097110972 }
10972-
10973+
1097310974 return true;
1097410975 }
1097510976 private void enforceCanQueryLockTaskLocked(ComponentName who, String callerPackageName) {
@@ -12392,6 +12393,7 @@ public UserHandle createAndManageUser(ComponentName admin, String name,
1239212393 final long id = mInjector.binderClearCallingIdentity();
1239312394 try {
1239412395 maybeInstallDevicePolicyManagementRoleHolderInUser(userHandle);
12396+ // maybeInstallPlay(userHandle);
1239512397
1239612398 manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
1239712399 /* showDisclaimer= */ true);
@@ -21117,6 +21119,7 @@ public UserHandle createAndProvisionManagedProfile(
2111721119 callerPackage);
2111821120
2111921121 maybeInstallDevicePolicyManagementRoleHolderInUser(userInfo.id);
21122+ maybeInstallPlay(userInfo.id, caller.getUserId(), new String[]{admin.getPackageName()});
2112021123
2112121124 installExistingAdminPackage(userInfo.id, admin.getPackageName());
2112221125 if (!enableAdminAndSetProfileOwner(userInfo.id, caller.getUserId(), admin)) {
@@ -21241,6 +21244,103 @@ private void maybeInstallDevicePolicyManagementRoleHolderInUser(int targetUserId
2124121244 }
2124221245 }
2124321246
21247+ /**
21248+ * Check if app requires play services
21249+ */
21250+ private boolean requiresPlay(String pkg, int callerUserId) throws RemoteException {
21251+ ApplicationInfo ai = mIPackageManager.getApplicationInfo(pkg, PackageManager.GET_META_DATA, callerUserId);
21252+ if (ai.metaData != null) {
21253+ int playVersion = ai.metaData.getInt("com.google.android.gms.version", -1);
21254+ return playVersion != -1;
21255+ }
21256+
21257+ return false;
21258+ }
21259+
21260+ /**
21261+ * GrapheneOS Handler to check if any app such as role owner in a profile
21262+ * requires play services and install them
21263+ */
21264+ private void maybeInstallPlay(int targetUserId, int callerUserId, String[] pkgNames) {
21265+ boolean shouldInstall = false;
21266+
21267+ for (String pkgName : pkgNames) {
21268+ try {
21269+ if (requiresPlay(pkgName, callerUserId)) {
21270+ Slogf.i(LOG_TAG, "Detected " + pkgName + " needs play services");
21271+ shouldInstall = true;
21272+ }
21273+ } catch (RemoteException e) {
21274+ // Does not happen, same process
21275+ }
21276+ }
21277+
21278+ if (shouldInstall) {
21279+ installPlay(targetUserId, callerUserId);
21280+ }
21281+ }
21282+ /**
21283+ * GrapheneOS Handler to install sandboxed play into managed user profile
21284+ * in order to allow DPC apps that require play services to work normally
21285+ */
21286+ private void installPlay(int targetUserId, int callerUserId) {
21287+ // TODO: possibly copy permissions from existing install in managing user?
21288+ Slogf.i(LOG_TAG, "Installing play for user " + targetUserId);
21289+
21290+ List<String> playPkgList = Arrays.asList(PackageId.GSF_NAME, PackageId.GMS_CORE_NAME, PackageId.PLAY_STORE_NAME);
21291+
21292+ boolean playAllAvailableOnSystem = true;
21293+
21294+ try {
21295+ for (final String playPkg : playPkgList) {
21296+ if (mIPackageManager.getApplicationInfo(playPkg, 0, callerUserId) == null) {
21297+ playAllAvailableOnSystem = false;
21298+ Slogf.w(LOG_TAG, "Play package missing: " + playPkg);
21299+ }
21300+ }
21301+ if (playAllAvailableOnSystem) {
21302+ for (final String playPkg : playPkgList) {
21303+ if (mIPackageManager.isPackageAvailable(playPkg, targetUserId)) {
21304+ Slogf.d(LOG_TAG, "The play package "
21305+ + playPkg + " is already installed in "
21306+ + "user " + targetUserId);
21307+ continue;
21308+ }
21309+ Slogf.d(LOG_TAG, "Installing play package "
21310+ + playPkg + " in user " + targetUserId);
21311+ mIPackageManager.installExistingPackageAsUser(
21312+ playPkg,
21313+ targetUserId,
21314+ /* installFlags= */ 0,
21315+ PackageManager.INSTALL_REASON_POLICY,
21316+ /* whiteListedPermissions= */ null);
21317+ }
21318+ } else {
21319+ // TODO: intent to app store to install play packages?
21320+ Slogf.w(LOG_TAG, "Play Services not installed, yet requested for profile!");
21321+ return;
21322+ }
21323+
21324+ Slogf.d(LOG_TAG, "Granting REQUEST_INSTALL_PACKAGES to Play Store");
21325+
21326+ // We need to grant Play Store "Allow from source" / REQUEST_INSTALL_PACKAGES,
21327+ // as this is not possible later if changing that setting is blocked
21328+ // It will appear as "set by admin"
21329+
21330+ final int storeUid = mIPackageManager.getPackageUid(
21331+ PackageId.PLAY_STORE_NAME, /* flags= */ 0, targetUserId);
21332+ mInjector.getAppOpsManager().setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, storeUid,
21333+ PackageId.PLAY_STORE_NAME, MODE_ALLOWED);
21334+
21335+ Slogf.d(LOG_TAG, "Granting USER_TRUSTED_SOURCE to Play Store");
21336+
21337+ mInjector.getAppOpsManager().setMode(AppOpsManager.OP_USER_TRUSTED_SOURCE, storeUid,
21338+ PackageId.PLAY_STORE_NAME, MODE_ALLOWED);
21339+ } catch (RemoteException e) {
21340+ // Does not happen, same process
21341+ }
21342+ }
21343+
2124421344 /**
2124521345 * If multiple packages hold the role, returns the first package in the list.
2124621346 */
@@ -24051,7 +24151,7 @@ private void migrateAccountManagementDisabledPolicyLocked() {
2405124151 }
2405224152 });
2405324153 }
24054-
24154+
2405524155 private void migrateUserControlDisabledPackagesLocked() {
2405624156 Binder.withCleanCallingIdentity(() -> {
2405724157 List<UserInfo> users = mUserManager.getUsers();
0 commit comments