1 /* 2 * Copyright (C) 2022 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.car.settings.privacy; 18 19 import android.Manifest; 20 import android.car.drivingstate.CarUxRestrictions; 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.hardware.SensorPrivacyManager; 24 import android.os.UserHandle; 25 import android.os.UserManager; 26 import android.permission.PermissionControllerManager; 27 28 import androidx.preference.Preference; 29 30 import com.android.car.settings.R; 31 import com.android.car.settings.common.FragmentController; 32 import com.android.car.settings.common.Logger; 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.settingslib.utils.StringUtil; 35 36 import java.util.Collections; 37 import java.util.HashMap; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.concurrent.atomic.AtomicInteger; 41 42 /** 43 * This controller displays the number of non-system apps that have access to camera. 44 */ 45 public class ManageCameraPermissionsPreferenceController extends 46 CameraPrivacyBasePreferenceController<Preference> { 47 private static final Logger LOG = new Logger( 48 ManageCameraPermissionsPreferenceController.class); 49 50 private final AtomicInteger mLoadingInProgress = new AtomicInteger(0); 51 private int mNumTotal = 0; 52 private int mNumHasAccess = 0; 53 54 private final UserManager mUserManager; 55 ManageCameraPermissionsPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)56 public ManageCameraPermissionsPreferenceController(Context context, String preferenceKey, 57 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 58 this(context, preferenceKey, fragmentController, uxRestrictions, 59 SensorPrivacyManager.getInstance(context), 60 context.getSystemService(UserManager.class)); 61 } 62 63 @VisibleForTesting ManageCameraPermissionsPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, SensorPrivacyManager sensorPrivacyManager, UserManager userManager)64 ManageCameraPermissionsPreferenceController(Context context, String preferenceKey, 65 FragmentController fragmentController, CarUxRestrictions uxRestrictions, 66 SensorPrivacyManager sensorPrivacyManager, UserManager userManager) { 67 super(context, preferenceKey, fragmentController, uxRestrictions, sensorPrivacyManager); 68 mUserManager = userManager; 69 } 70 71 @Override getPreferenceType()72 protected Class<Preference> getPreferenceType() { 73 return Preference.class; 74 } 75 76 @Override updateState(Preference preference)77 public void updateState(Preference preference) { 78 super.updateState(preference); 79 if (getSensorPrivacyManager().isSensorPrivacyEnabled( 80 SensorPrivacyManager.Sensors.CAMERA)) { 81 getPreference().setSummary(getContext().getString( 82 R.string.camera_app_permission_summary_camera_off)); 83 return; 84 } 85 // Bail out if there's another loading request in progress. 86 if (mLoadingInProgress.get() != 0) { 87 return; 88 } 89 getPreference().setSummary( 90 getContext().getString(R.string.camera_settings_loading_app_permission_stats)); 91 92 mNumTotal = 0; 93 mNumHasAccess = 0; 94 // Retrieve a list of users inside the current user profile group. 95 List<UserHandle> users = mUserManager.getUserProfiles(); 96 // need to asynchronously load 2 callbacks for each profile 97 mLoadingInProgress.set(2 * users.size()); 98 for (UserHandle user : users) { 99 Context userContext = createPackageContextAsUser(getContext(), user); 100 if (userContext == null) { 101 // remove the two callbacks that we would normally expect for this user 102 if (mLoadingInProgress.addAndGet(-2) == 0) { 103 setAppCounts(mNumTotal, mNumHasAccess); 104 } 105 continue; 106 } 107 PermissionControllerManager permController = 108 userContext.getSystemService(PermissionControllerManager.class); 109 permController.countPermissionApps( 110 Collections.singletonList(Manifest.permission.CAMERA), /* flags= */ 0, 111 (numApps) -> { 112 mNumTotal += numApps; 113 if (mLoadingInProgress.decrementAndGet() == 0) { 114 setAppCounts(mNumTotal, mNumHasAccess); 115 } 116 }, /* handler= */ null); 117 permController.countPermissionApps( 118 Collections.singletonList(Manifest.permission.CAMERA), 119 PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED, 120 (numApps) -> { 121 mNumHasAccess += numApps; 122 if (mLoadingInProgress.decrementAndGet() == 0) { 123 setAppCounts(mNumTotal, mNumHasAccess); 124 } 125 }, /* handler= */ null); 126 } 127 128 } 129 setAppCounts(int numTotal, int numHasAccess)130 private void setAppCounts(int numTotal, int numHasAccess) { 131 Map<String, Object> arguments = new HashMap<>(); 132 arguments.put("count", numHasAccess); 133 arguments.put("total_count", numTotal); 134 getPreference().setSummary(StringUtil.getIcuPluralsString(getContext(), arguments, 135 R.string.camera_app_permission_summary_camera_on)); 136 } 137 138 139 /** 140 * Returns a context created from the given context for the given user, or null if it fails. 141 */ createPackageContextAsUser(Context context, UserHandle userHandle)142 private Context createPackageContextAsUser(Context context, UserHandle userHandle) { 143 try { 144 return context.createPackageContextAsUser( 145 context.getPackageName(), /* flags= */ 0, userHandle); 146 } catch (PackageManager.NameNotFoundException e) { 147 LOG.e("Failed to create user context", e); 148 } 149 return null; 150 } 151 } 152 153