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 17 package com.android.managedprovisioning.ota; 18 19 import android.Manifest; 20 import android.app.AppOpsManager; 21 import android.app.admin.DevicePolicyManager; 22 import android.content.Context; 23 import android.content.pm.CrossProfileApps; 24 import android.content.pm.PackageManager; 25 import android.content.pm.UserInfo; 26 import android.os.UserHandle; 27 import android.os.UserManager; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.managedprovisioning.task.interactacrossprofiles.CrossProfileAppsSnapshot; 31 32 import java.util.Set; 33 import java.util.stream.Collectors; 34 35 36 /** 37 * Controller for granting the INTERACT_ACROSS_PROFILES appop at boot time. 38 */ 39 public class CrossProfileAppsPregrantController { 40 41 private final Context mContext; 42 private final UserManager mUserManager; 43 private final PackageManager mPackageManager; 44 private final DevicePolicyManager mDevicePolicyManager; 45 private final CrossProfileApps mCrossProfileApps; 46 private final CrossProfileAppsSnapshot mCrossProfileAppsSnapshot; 47 private final AppOpsManager mAppOpsManager; 48 CrossProfileAppsPregrantController(Context context)49 public CrossProfileAppsPregrantController(Context context) { 50 this(context, 51 context.getSystemService(UserManager.class), 52 context.getPackageManager(), 53 context.getSystemService(DevicePolicyManager.class), 54 context.getSystemService(CrossProfileApps.class), 55 context.getSystemService(AppOpsManager.class)); 56 } 57 58 @VisibleForTesting CrossProfileAppsPregrantController(Context context, UserManager userManager, PackageManager packageManager, DevicePolicyManager devicePolicyManager, CrossProfileApps crossProfileApps, AppOpsManager appOpsManager)59 CrossProfileAppsPregrantController(Context context, 60 UserManager userManager, 61 PackageManager packageManager, 62 DevicePolicyManager devicePolicyManager, 63 CrossProfileApps crossProfileApps, 64 AppOpsManager appOpsManager) { 65 mContext = context; 66 mUserManager = userManager; 67 mPackageManager = packageManager; 68 mDevicePolicyManager = devicePolicyManager; 69 mCrossProfileApps = crossProfileApps; 70 mAppOpsManager = appOpsManager; 71 mCrossProfileAppsSnapshot = new CrossProfileAppsSnapshot(context); 72 } 73 checkCrossProfileAppsPermissions()74 public void checkCrossProfileAppsPermissions() { 75 if (!isParentProfileOfManagedProfile()) { 76 return; 77 } 78 79 Set<String> crossProfilePackages = 80 mCrossProfileAppsSnapshot.getSnapshot(mContext.getUserId()); 81 82 String op = AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES); 83 for (String crossProfilePackageName : getConfigurableDefaultCrossProfilePackages()) { 84 if (crossProfilePackages.contains(crossProfilePackageName) && 85 !appOpIsChangedFromDefault(op, crossProfilePackageName)) { 86 mCrossProfileApps.setInteractAcrossProfilesAppOp(crossProfilePackageName, 87 AppOpsManager.MODE_ALLOWED); 88 } 89 } 90 } 91 appOpIsChangedFromDefault(String op, String packageName)92 private boolean appOpIsChangedFromDefault(String op, String packageName) { 93 try { 94 int uid = mPackageManager.getPackageUid(packageName, /* flags= */ 0); 95 return mAppOpsManager.unsafeCheckOpNoThrow(op, uid, packageName) 96 != AppOpsManager.MODE_DEFAULT; 97 } catch (PackageManager.NameNotFoundException e) { 98 return false; 99 } 100 } 101 getConfigurableDefaultCrossProfilePackages()102 private Set<String> getConfigurableDefaultCrossProfilePackages() { 103 Set<String> defaultPackages = mDevicePolicyManager.getDefaultCrossProfilePackages(); 104 return defaultPackages.stream().filter( 105 mCrossProfileApps::canConfigureInteractAcrossProfiles).collect(Collectors.toSet()); 106 } 107 isParentProfileOfManagedProfile()108 private boolean isParentProfileOfManagedProfile() { 109 int currentUserId = android.os.Process.myUserHandle().getIdentifier(); 110 for (UserInfo userInfo : mUserManager.getProfiles(currentUserId)) { 111 UserHandle userHandle = userInfo.getUserHandle(); 112 if (userInfo.isManagedProfile() && 113 mUserManager.getProfileParent(userHandle).getIdentifier() == currentUserId) { 114 return true; 115 } 116 } 117 return false; 118 } 119 } 120