1 /* 2 * Copyright (C) 2018 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.server; 18 19 import static android.Manifest.permission.MANAGE_SENSOR_PRIVACY; 20 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; 21 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; 22 import static android.app.ActivityManager.RunningServiceInfo; 23 import static android.app.ActivityManager.RunningTaskInfo; 24 import static android.app.AppOpsManager.MODE_IGNORED; 25 import static android.app.AppOpsManager.OP_CAMERA; 26 import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA; 27 import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; 28 import static android.app.AppOpsManager.OP_RECORD_AUDIO; 29 import static android.content.Intent.EXTRA_PACKAGE_NAME; 30 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 31 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; 32 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 33 import static android.hardware.SensorPrivacyManager.EXTRA_ALL_SENSORS; 34 import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR; 35 import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; 36 import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; 37 import static android.hardware.SensorPrivacyManager.Sources.DIALOG; 38 import static android.hardware.SensorPrivacyManager.Sources.OTHER; 39 import static android.hardware.SensorPrivacyManager.Sources.QS_TILE; 40 import static android.hardware.SensorPrivacyManager.Sources.SETTINGS; 41 import static android.hardware.SensorPrivacyManager.Sources.SHELL; 42 import static android.os.UserHandle.USER_NULL; 43 import static android.os.UserHandle.USER_SYSTEM; 44 import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN; 45 46 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION; 47 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_OFF; 48 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_ON; 49 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__CAMERA; 50 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__MICROPHONE; 51 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__SENSOR_UNKNOWN; 52 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__DIALOG; 53 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__QS_TILE; 54 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SETTINGS; 55 import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SOURCE_UNKNOWN; 56 import static com.android.internal.util.FrameworkStatsLog.write; 57 58 import android.annotation.NonNull; 59 import android.annotation.Nullable; 60 import android.annotation.UserIdInt; 61 import android.app.ActivityManager; 62 import android.app.ActivityManagerInternal; 63 import android.app.ActivityOptions; 64 import android.app.ActivityTaskManager; 65 import android.app.AppOpsManager; 66 import android.app.AppOpsManagerInternal; 67 import android.app.KeyguardManager; 68 import android.app.Notification; 69 import android.app.NotificationChannel; 70 import android.app.NotificationManager; 71 import android.app.PendingIntent; 72 import android.content.BroadcastReceiver; 73 import android.content.ComponentName; 74 import android.content.Context; 75 import android.content.Intent; 76 import android.content.IntentFilter; 77 import android.content.pm.PackageManager; 78 import android.content.res.Configuration; 79 import android.graphics.drawable.Icon; 80 import android.hardware.ISensorPrivacyListener; 81 import android.hardware.ISensorPrivacyManager; 82 import android.hardware.SensorPrivacyManager; 83 import android.hardware.SensorPrivacyManagerInternal; 84 import android.os.Binder; 85 import android.os.Bundle; 86 import android.os.Environment; 87 import android.os.Handler; 88 import android.os.IBinder; 89 import android.os.Looper; 90 import android.os.Process; 91 import android.os.RemoteCallbackList; 92 import android.os.RemoteException; 93 import android.os.ResultReceiver; 94 import android.os.ShellCallback; 95 import android.os.ShellCommand; 96 import android.os.SystemClock; 97 import android.os.UserHandle; 98 import android.os.UserManager; 99 import android.provider.Settings; 100 import android.service.SensorPrivacyIndividualEnabledSensorProto; 101 import android.service.SensorPrivacyServiceDumpProto; 102 import android.service.SensorPrivacyUserProto; 103 import android.service.voice.VoiceInteractionManagerInternal; 104 import android.telephony.TelephonyCallback; 105 import android.telephony.TelephonyManager; 106 import android.telephony.emergency.EmergencyNumber; 107 import android.text.Html; 108 import android.text.TextUtils; 109 import android.util.ArrayMap; 110 import android.util.ArraySet; 111 import android.util.AtomicFile; 112 import android.util.IndentingPrintWriter; 113 import android.util.Log; 114 import android.util.Pair; 115 import android.util.SparseArray; 116 import android.util.SparseBooleanArray; 117 import android.util.TypedXmlPullParser; 118 import android.util.TypedXmlSerializer; 119 import android.util.Xml; 120 import android.util.proto.ProtoOutputStream; 121 122 import com.android.internal.R; 123 import com.android.internal.annotations.GuardedBy; 124 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 125 import com.android.internal.os.BackgroundThread; 126 import com.android.internal.util.DumpUtils; 127 import com.android.internal.util.FunctionalUtils; 128 import com.android.internal.util.XmlUtils; 129 import com.android.internal.util.dump.DualDumpOutputStream; 130 import com.android.internal.util.function.pooled.PooledLambda; 131 import com.android.server.pm.UserManagerInternal; 132 133 import org.xmlpull.v1.XmlPullParser; 134 import org.xmlpull.v1.XmlPullParserException; 135 136 import java.io.File; 137 import java.io.FileDescriptor; 138 import java.io.FileInputStream; 139 import java.io.FileOutputStream; 140 import java.io.IOException; 141 import java.io.PrintWriter; 142 import java.util.ArrayList; 143 import java.util.List; 144 import java.util.NoSuchElementException; 145 import java.util.Objects; 146 147 /** @hide */ 148 public final class SensorPrivacyService extends SystemService { 149 150 private static final String TAG = SensorPrivacyService.class.getSimpleName(); 151 private static final boolean DEBUG = false; 152 private static final boolean DEBUG_LOGGING = false; 153 154 /** Version number indicating compatibility parsing the persisted file */ 155 private static final int CURRENT_PERSISTENCE_VERSION = 1; 156 /** Version number indicating the persisted data needs upgraded to match new internal data 157 * structures and features */ 158 private static final int CURRENT_VERSION = 1; 159 160 private static final String SENSOR_PRIVACY_XML_FILE = "sensor_privacy.xml"; 161 private static final String XML_TAG_SENSOR_PRIVACY = "sensor-privacy"; 162 private static final String XML_TAG_USER = "user"; 163 private static final String XML_TAG_INDIVIDUAL_SENSOR_PRIVACY = "individual-sensor-privacy"; 164 private static final String XML_ATTRIBUTE_ID = "id"; 165 private static final String XML_ATTRIBUTE_PERSISTENCE_VERSION = "persistence-version"; 166 private static final String XML_ATTRIBUTE_VERSION = "version"; 167 private static final String XML_ATTRIBUTE_ENABLED = "enabled"; 168 private static final String XML_ATTRIBUTE_LAST_CHANGE = "last-change"; 169 private static final String XML_ATTRIBUTE_SENSOR = "sensor"; 170 171 private static final String SENSOR_PRIVACY_CHANNEL_ID = Context.SENSOR_PRIVACY_SERVICE; 172 private static final String ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY = 173 SensorPrivacyService.class.getName() + ".action.disable_sensor_privacy"; 174 175 // These are associated with fields that existed for older persisted versions of files 176 private static final int VER0_ENABLED = 0; 177 private static final int VER0_INDIVIDUAL_ENABLED = 1; 178 private static final int VER1_ENABLED = 0; 179 private static final int VER1_INDIVIDUAL_ENABLED = 1; 180 public static final int REMINDER_DIALOG_DELAY_MILLIS = 500; 181 182 private final Context mContext; 183 private final SensorPrivacyServiceImpl mSensorPrivacyServiceImpl; 184 private final UserManagerInternal mUserManagerInternal; 185 private final ActivityManager mActivityManager; 186 private final ActivityManagerInternal mActivityManagerInternal; 187 private final ActivityTaskManager mActivityTaskManager; 188 private final AppOpsManager mAppOpsManager; 189 private final AppOpsManagerInternal mAppOpsManagerInternal; 190 private final TelephonyManager mTelephonyManager; 191 192 private final IBinder mAppOpsRestrictionToken = new Binder(); 193 194 private SensorPrivacyManagerInternalImpl mSensorPrivacyManagerInternal; 195 196 private EmergencyCallHelper mEmergencyCallHelper; 197 private KeyguardManager mKeyguardManager; 198 199 private int mCurrentUser = USER_NULL; 200 SensorPrivacyService(Context context)201 public SensorPrivacyService(Context context) { 202 super(context); 203 mContext = context; 204 mAppOpsManager = context.getSystemService(AppOpsManager.class); 205 mAppOpsManagerInternal = getLocalService(AppOpsManagerInternal.class); 206 mUserManagerInternal = getLocalService(UserManagerInternal.class); 207 mActivityManager = context.getSystemService(ActivityManager.class); 208 mActivityManagerInternal = getLocalService(ActivityManagerInternal.class); 209 mActivityTaskManager = context.getSystemService(ActivityTaskManager.class); 210 mTelephonyManager = context.getSystemService(TelephonyManager.class); 211 mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl(); 212 } 213 214 @Override onStart()215 public void onStart() { 216 publishBinderService(Context.SENSOR_PRIVACY_SERVICE, mSensorPrivacyServiceImpl); 217 mSensorPrivacyManagerInternal = new SensorPrivacyManagerInternalImpl(); 218 publishLocalService(SensorPrivacyManagerInternal.class, 219 mSensorPrivacyManagerInternal); 220 } 221 222 @Override onBootPhase(int phase)223 public void onBootPhase(int phase) { 224 if (phase == PHASE_SYSTEM_SERVICES_READY) { 225 mKeyguardManager = mContext.getSystemService(KeyguardManager.class); 226 mEmergencyCallHelper = new EmergencyCallHelper(); 227 } 228 } 229 230 @Override onUserStarting(TargetUser user)231 public void onUserStarting(TargetUser user) { 232 if (mCurrentUser == USER_NULL) { 233 mCurrentUser = user.getUserIdentifier(); 234 mSensorPrivacyServiceImpl.userSwitching(USER_NULL, user.getUserIdentifier()); 235 } 236 } 237 238 @Override onUserSwitching(TargetUser from, TargetUser to)239 public void onUserSwitching(TargetUser from, TargetUser to) { 240 mCurrentUser = to.getUserIdentifier(); 241 mSensorPrivacyServiceImpl.userSwitching(from.getUserIdentifier(), to.getUserIdentifier()); 242 } 243 244 class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements 245 AppOpsManager.OnOpNotedListener, AppOpsManager.OnOpStartedListener, 246 IBinder.DeathRecipient, UserManagerInternal.UserRestrictionsListener { 247 248 private final SensorPrivacyHandler mHandler; 249 private final Object mLock = new Object(); 250 @GuardedBy("mLock") 251 private final AtomicFile mAtomicFile; 252 @GuardedBy("mLock") 253 private SparseBooleanArray mEnabled = new SparseBooleanArray(); 254 @GuardedBy("mLock") 255 private SparseArray<SparseArray<SensorState>> mIndividualEnabled = new SparseArray<>(); 256 257 /** 258 * Packages for which not to show sensor use reminders. 259 * 260 * <Package, User> -> list of suppressor tokens 261 */ 262 @GuardedBy("mLock") 263 private ArrayMap<Pair<Integer, UserHandle>, ArrayList<IBinder>> mSuppressReminders = 264 new ArrayMap<>(); 265 266 private final ArrayMap<SensorUseReminderDialogInfo, ArraySet<Integer>> 267 mQueuedSensorUseReminderDialogs = new ArrayMap<>(); 268 269 private class SensorState { 270 private boolean mEnabled; 271 private long mLastChange; 272 SensorState(boolean enabled)273 SensorState(boolean enabled) { 274 mEnabled = enabled; 275 mLastChange = getCurrentTimeMillis(); 276 } 277 SensorState(boolean enabled, long lastChange)278 SensorState(boolean enabled, long lastChange) { 279 mEnabled = enabled; 280 if (lastChange < 0) { 281 mLastChange = getCurrentTimeMillis(); 282 } else { 283 mLastChange = lastChange; 284 } 285 } 286 setEnabled(boolean enabled)287 boolean setEnabled(boolean enabled) { 288 if (mEnabled != enabled) { 289 mEnabled = enabled; 290 mLastChange = getCurrentTimeMillis(); 291 return true; 292 } 293 return false; 294 } 295 } 296 297 private class SensorUseReminderDialogInfo { 298 private int mTaskId; 299 private UserHandle mUser; 300 private String mPackageName; 301 SensorUseReminderDialogInfo(int taskId, UserHandle user, String packageName)302 SensorUseReminderDialogInfo(int taskId, UserHandle user, String packageName) { 303 mTaskId = taskId; 304 mUser = user; 305 mPackageName = packageName; 306 } 307 308 @Override equals(Object o)309 public boolean equals(Object o) { 310 if (this == o) return true; 311 if (o == null || !(o instanceof SensorUseReminderDialogInfo)) return false; 312 SensorUseReminderDialogInfo that = (SensorUseReminderDialogInfo) o; 313 return mTaskId == that.mTaskId 314 && Objects.equals(mUser, that.mUser) 315 && Objects.equals(mPackageName, that.mPackageName); 316 } 317 318 @Override hashCode()319 public int hashCode() { 320 return Objects.hash(mTaskId, mUser, mPackageName); 321 } 322 } 323 SensorPrivacyServiceImpl()324 SensorPrivacyServiceImpl() { 325 mHandler = new SensorPrivacyHandler(FgThread.get().getLooper(), mContext); 326 File sensorPrivacyFile = new File(Environment.getDataSystemDirectory(), 327 SENSOR_PRIVACY_XML_FILE); 328 mAtomicFile = new AtomicFile(sensorPrivacyFile); 329 synchronized (mLock) { 330 if (readPersistedSensorPrivacyStateLocked()) { 331 persistSensorPrivacyStateLocked(); 332 } 333 } 334 335 int[] micAndCameraOps = new int[]{OP_RECORD_AUDIO, OP_PHONE_CALL_MICROPHONE, 336 OP_CAMERA, OP_PHONE_CALL_CAMERA}; 337 mAppOpsManager.startWatchingNoted(micAndCameraOps, this); 338 mAppOpsManager.startWatchingStarted(micAndCameraOps, this); 339 340 341 342 mContext.registerReceiver(new BroadcastReceiver() { 343 @Override 344 public void onReceive(Context context, Intent intent) { 345 setIndividualSensorPrivacy( 346 ((UserHandle) intent.getParcelableExtra( 347 Intent.EXTRA_USER)).getIdentifier(), OTHER, 348 intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false); 349 } 350 }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY), 351 MANAGE_SENSOR_PRIVACY, null); 352 mUserManagerInternal.addUserRestrictionsListener(this); 353 } 354 355 @Override onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions)356 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, 357 Bundle prevRestrictions) { 358 // Reset sensor privacy when restriction is added 359 if (!prevRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE) 360 && newRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)) { 361 setIndividualSensorPrivacyUnchecked(userId, OTHER, CAMERA, false); 362 } 363 if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE) 364 && newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) { 365 setIndividualSensorPrivacyUnchecked(userId, OTHER, MICROPHONE, false); 366 } 367 } 368 369 @Override onOpStarted(int code, int uid, String packageName, String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result)370 public void onOpStarted(int code, int uid, String packageName, String attributionTag, 371 @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) { 372 onOpNoted(code, uid, packageName, attributionTag, flags, result); 373 } 374 375 @Override onOpNoted(int code, int uid, String packageName, String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result)376 public void onOpNoted(int code, int uid, String packageName, 377 String attributionTag, @AppOpsManager.OpFlags int flags, 378 @AppOpsManager.Mode int result) { 379 if ((flags & AppOpsManager.OP_FLAGS_ALL_TRUSTED) == 0) { 380 return; 381 } 382 383 int sensor; 384 if (result == MODE_IGNORED) { 385 if (code == OP_RECORD_AUDIO || code == OP_PHONE_CALL_MICROPHONE) { 386 sensor = MICROPHONE; 387 } else if (code == OP_CAMERA || code == OP_PHONE_CALL_CAMERA) { 388 sensor = CAMERA; 389 } else { 390 return; 391 } 392 } else { 393 return; 394 } 395 396 long token = Binder.clearCallingIdentity(); 397 try { 398 onSensorUseStarted(uid, packageName, sensor); 399 } finally { 400 Binder.restoreCallingIdentity(token); 401 } 402 } 403 404 /** 405 * Called when a sensor protected by individual sensor privacy is attempting to get used. 406 * 407 * @param uid The uid of the app using the sensor 408 * @param packageName The package name of the app using the sensor 409 * @param sensor The sensor that is attempting to be used 410 */ onSensorUseStarted(int uid, String packageName, int sensor)411 private void onSensorUseStarted(int uid, String packageName, int sensor) { 412 UserHandle user = UserHandle.getUserHandleForUid(uid); 413 if (!isIndividualSensorPrivacyEnabled(user.getIdentifier(), sensor)) { 414 return; 415 } 416 417 if (uid == Process.SYSTEM_UID) { 418 // If the system uid is being blamed for sensor access, the ui must be shown 419 // explicitly using SensorPrivacyManager#showSensorUseDialog 420 return; 421 } 422 423 synchronized (mLock) { 424 UserHandle parentUser = UserHandle.of(mUserManagerInternal 425 .getProfileParentId(user.getIdentifier())); 426 if (mSuppressReminders.containsKey(new Pair<>(sensor, parentUser))) { 427 Log.d(TAG, 428 "Suppressed sensor privacy reminder for " + packageName + "/" 429 + parentUser); 430 return; 431 } 432 } 433 434 // TODO: Handle reminders with multiple sensors 435 436 // - If we have a likely activity that triggered the sensor use overlay a dialog over 437 // it. This should be the most common case. 438 // - If there is no use visible entity that triggered the sensor don't show anything as 439 // this is - from the point of the user - a background usage 440 // - Otherwise show a notification as we are not quite sure where to display the dialog. 441 442 List<RunningTaskInfo> tasksOfPackageUsingSensor = new ArrayList<>(); 443 444 List<RunningTaskInfo> tasks = mActivityTaskManager.getTasks(Integer.MAX_VALUE); 445 int numTasks = tasks.size(); 446 for (int taskNum = 0; taskNum < numTasks; taskNum++) { 447 RunningTaskInfo task = tasks.get(taskNum); 448 449 if (task.isVisible) { 450 if (task.topActivity.getPackageName().equals(packageName)) { 451 if (task.isFocused) { 452 // There is the one focused activity 453 enqueueSensorUseReminderDialogAsync(task.taskId, user, packageName, 454 sensor); 455 return; 456 } 457 458 tasksOfPackageUsingSensor.add(task); 459 } else if (task.topActivity.flattenToString().equals(mContext.getResources() 460 .getString(R.string.config_sensorUseStartedActivity)) 461 && task.isFocused) { 462 enqueueSensorUseReminderDialogAsync(task.taskId, user, packageName, 463 sensor); 464 } 465 } 466 } 467 468 // TODO: Test this case 469 // There is one or more non-focused activity 470 if (tasksOfPackageUsingSensor.size() == 1) { 471 enqueueSensorUseReminderDialogAsync(tasksOfPackageUsingSensor.get(0).taskId, user, 472 packageName, sensor); 473 return; 474 } else if (tasksOfPackageUsingSensor.size() > 1) { 475 showSensorUseReminderNotification(user, packageName, sensor); 476 return; 477 } 478 479 // TODO: Test this case 480 // Check if there is a foreground service for this package 481 List<RunningServiceInfo> services = mActivityManager.getRunningServices( 482 Integer.MAX_VALUE); 483 int numServices = services.size(); 484 for (int serviceNum = 0; serviceNum < numServices; serviceNum++) { 485 RunningServiceInfo service = services.get(serviceNum); 486 487 if (service.foreground && service.service.getPackageName().equals(packageName)) { 488 showSensorUseReminderNotification(user, packageName, sensor); 489 return; 490 } 491 } 492 493 String inputMethodComponent = Settings.Secure.getString(mContext.getContentResolver(), 494 Settings.Secure.DEFAULT_INPUT_METHOD); 495 String inputMethodPackageName = null; 496 if (inputMethodComponent != null) { 497 inputMethodPackageName = ComponentName.unflattenFromString( 498 inputMethodComponent).getPackageName(); 499 } 500 501 int capability; 502 try { 503 capability = mActivityManagerInternal.getUidCapability(uid); 504 } catch (IllegalArgumentException e) { 505 Log.w(TAG, e); 506 return; 507 } 508 509 if (sensor == MICROPHONE) { 510 VoiceInteractionManagerInternal voiceInteractionManagerInternal = 511 LocalServices.getService(VoiceInteractionManagerInternal.class); 512 if (voiceInteractionManagerInternal != null 513 && voiceInteractionManagerInternal.hasActiveSession(packageName)) { 514 enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor); 515 return; 516 } 517 518 if (TextUtils.equals(packageName, inputMethodPackageName) 519 && (capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) { 520 enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor); 521 return; 522 } 523 } 524 525 if (sensor == CAMERA && TextUtils.equals(packageName, inputMethodPackageName) 526 && (capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) { 527 enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor); 528 return; 529 } 530 531 Log.i(TAG, packageName + "/" + uid + " started using sensor " + sensor 532 + " but no activity or foreground service was running. The user will not be" 533 + " informed. System components should check if sensor privacy is enabled for" 534 + " the sensor before accessing it."); 535 } 536 537 /** 538 * Show a dialog that informs the user that a sensor use or a blocked sensor started. 539 * The user can then react to this event. 540 * 541 * @param taskId The task this dialog should be overlaid on. 542 * @param user The user of the package using the sensor. 543 * @param packageName The name of the package using the sensor. 544 * @param sensor The sensor that is being used. 545 */ enqueueSensorUseReminderDialogAsync(int taskId, @NonNull UserHandle user, @NonNull String packageName, int sensor)546 private void enqueueSensorUseReminderDialogAsync(int taskId, @NonNull UserHandle user, 547 @NonNull String packageName, int sensor) { 548 mHandler.sendMessage(PooledLambda.obtainMessage( 549 this:: enqueueSensorUseReminderDialog, taskId, user, packageName, sensor)); 550 } 551 enqueueSensorUseReminderDialog(int taskId, @NonNull UserHandle user, @NonNull String packageName, int sensor)552 private void enqueueSensorUseReminderDialog(int taskId, @NonNull UserHandle user, 553 @NonNull String packageName, int sensor) { 554 SensorUseReminderDialogInfo info = 555 new SensorUseReminderDialogInfo(taskId, user, packageName); 556 if (!mQueuedSensorUseReminderDialogs.containsKey(info)) { 557 ArraySet<Integer> sensors = new ArraySet<>(); 558 if (sensor == MICROPHONE && mSuppressReminders.containsKey(new Pair<>(CAMERA, user)) 559 || sensor == CAMERA && mSuppressReminders 560 .containsKey(new Pair<>(MICROPHONE, user))) { 561 sensors.add(MICROPHONE); 562 sensors.add(CAMERA); 563 } else { 564 sensors.add(sensor); 565 } 566 mQueuedSensorUseReminderDialogs.put(info, sensors); 567 mHandler.sendMessageDelayed( 568 PooledLambda.obtainMessage(this::showSensorUserReminderDialog, info), 569 REMINDER_DIALOG_DELAY_MILLIS); 570 return; 571 } 572 ArraySet<Integer> sensors = mQueuedSensorUseReminderDialogs.get(info); 573 sensors.add(sensor); 574 } 575 showSensorUserReminderDialog(@onNull SensorUseReminderDialogInfo info)576 private void showSensorUserReminderDialog(@NonNull SensorUseReminderDialogInfo info) { 577 ArraySet<Integer> sensors = mQueuedSensorUseReminderDialogs.get(info); 578 mQueuedSensorUseReminderDialogs.remove(info); 579 if (sensors == null) { 580 Log.e(TAG, "Unable to show sensor use dialog because sensor set is null." 581 + " Was the dialog queue modified from outside the handler thread?"); 582 return; 583 } 584 Intent dialogIntent = new Intent(); 585 dialogIntent.setComponent(ComponentName.unflattenFromString( 586 mContext.getResources().getString( 587 R.string.config_sensorUseStartedActivity))); 588 589 ActivityOptions options = ActivityOptions.makeBasic(); 590 options.setLaunchTaskId(info.mTaskId); 591 options.setTaskOverlay(true, true); 592 593 dialogIntent.addFlags( 594 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | FLAG_ACTIVITY_NO_USER_ACTION); 595 596 dialogIntent.putExtra(EXTRA_PACKAGE_NAME, info.mPackageName); 597 if (sensors.size() == 1) { 598 dialogIntent.putExtra(EXTRA_SENSOR, sensors.valueAt(0)); 599 } else if (sensors.size() == 2) { 600 dialogIntent.putExtra(EXTRA_ALL_SENSORS, true); 601 } else { 602 // Currently the only cases can be 1 or two 603 Log.e(TAG, "Attempted to show sensor use dialog for " + sensors.size() 604 + " sensors"); 605 return; 606 } 607 mContext.startActivityAsUser(dialogIntent, options.toBundle(), info.mUser); 608 } 609 610 /** 611 * Show a notification that informs the user that a sensor use or a blocked sensor started. 612 * The user can then react to this event. 613 * 614 * @param user The user of the package using the sensor. 615 * @param packageName The name of the package using the sensor. 616 * @param sensor The sensor that is being used. 617 */ showSensorUseReminderNotification(@onNull UserHandle user, @NonNull String packageName, int sensor)618 private void showSensorUseReminderNotification(@NonNull UserHandle user, 619 @NonNull String packageName, int sensor) { 620 int iconRes; 621 int messageRes; 622 int notificationId; 623 624 CharSequence packageLabel; 625 try { 626 packageLabel = getUiContext().getPackageManager() 627 .getApplicationInfoAsUser(packageName, 0, user) 628 .loadLabel(mContext.getPackageManager()); 629 } catch (PackageManager.NameNotFoundException e) { 630 Log.e(TAG, "Cannot show sensor use notification for " + packageName); 631 return; 632 } 633 634 if (sensor == MICROPHONE) { 635 iconRes = R.drawable.ic_mic_blocked; 636 messageRes = R.string.sensor_privacy_start_use_mic_notification_content_title; 637 notificationId = SystemMessage.NOTE_UNBLOCK_MIC_TOGGLE; 638 } else { 639 iconRes = R.drawable.ic_camera_blocked; 640 messageRes = R.string.sensor_privacy_start_use_camera_notification_content_title; 641 notificationId = SystemMessage.NOTE_UNBLOCK_CAM_TOGGLE; 642 } 643 644 NotificationManager notificationManager = 645 mContext.getSystemService(NotificationManager.class); 646 NotificationChannel channel = new NotificationChannel( 647 SENSOR_PRIVACY_CHANNEL_ID, 648 getUiContext().getString(R.string.sensor_privacy_notification_channel_label), 649 NotificationManager.IMPORTANCE_HIGH); 650 channel.setSound(null, null); 651 channel.setBypassDnd(true); 652 channel.enableVibration(false); 653 channel.setBlockable(false); 654 655 notificationManager.createNotificationChannel(channel); 656 657 Icon icon = Icon.createWithResource(getUiContext().getResources(), iconRes); 658 notificationManager.notify(notificationId, 659 new Notification.Builder(mContext, SENSOR_PRIVACY_CHANNEL_ID) 660 .setContentTitle(getUiContext().getString(messageRes)) 661 .setContentText(Html.fromHtml(getUiContext().getString( 662 R.string.sensor_privacy_start_use_notification_content_text, 663 packageLabel),0)) 664 .setSmallIcon(icon) 665 .addAction(new Notification.Action.Builder(icon, 666 getUiContext().getString( 667 R.string.sensor_privacy_start_use_dialog_turn_on_button), 668 PendingIntent.getBroadcast(mContext, sensor, 669 new Intent(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY) 670 .setPackage(mContext.getPackageName()) 671 .putExtra(EXTRA_SENSOR, sensor) 672 .putExtra(Intent.EXTRA_USER, user), 673 PendingIntent.FLAG_IMMUTABLE 674 | PendingIntent.FLAG_UPDATE_CURRENT)) 675 .build()) 676 .setContentIntent(PendingIntent.getActivity(mContext, sensor, 677 new Intent(Settings.ACTION_PRIVACY_SETTINGS), 678 PendingIntent.FLAG_IMMUTABLE 679 | PendingIntent.FLAG_UPDATE_CURRENT)) 680 .extend(new Notification.TvExtender()) 681 .setTimeoutAfter(isTelevision(mContext) 682 ? /* dismiss immediately */ 1 683 : /* no timeout */ 0) 684 .build()); 685 } 686 isTelevision(Context context)687 private boolean isTelevision(Context context) { 688 int uiMode = context.getResources().getConfiguration().uiMode; 689 return (uiMode & Configuration.UI_MODE_TYPE_MASK) 690 == Configuration.UI_MODE_TYPE_TELEVISION; 691 } 692 693 /** 694 * Sets the sensor privacy to the provided state and notifies all listeners of the new 695 * state. 696 */ 697 @Override setSensorPrivacy(boolean enable)698 public void setSensorPrivacy(boolean enable) { 699 enforceManageSensorPrivacyPermission(); 700 // Keep the state consistent between all users to make it a single global state 701 forAllUsers(userId -> setSensorPrivacy(userId, enable)); 702 } 703 setSensorPrivacy(@serIdInt int userId, boolean enable)704 private void setSensorPrivacy(@UserIdInt int userId, boolean enable) { 705 synchronized (mLock) { 706 mEnabled.put(userId, enable); 707 persistSensorPrivacyStateLocked(); 708 } 709 mHandler.onSensorPrivacyChanged(enable); 710 } 711 712 @Override setIndividualSensorPrivacy(@serIdInt int userId, @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable)713 public void setIndividualSensorPrivacy(@UserIdInt int userId, 714 @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable) { 715 if (DEBUG) { 716 Log.d(TAG, "callingUid=" + Binder.getCallingUid() 717 + " callingPid=" + Binder.getCallingPid() 718 + " setIndividualSensorPrivacy(" 719 + "userId=" + userId 720 + " source=" + source 721 + " sensor=" + sensor 722 + " enable=" + enable 723 + ")"); 724 } 725 enforceManageSensorPrivacyPermission(); 726 if (userId == UserHandle.USER_CURRENT) { 727 userId = mCurrentUser; 728 } 729 if (!canChangeIndividualSensorPrivacy(userId, sensor)) { 730 return; 731 } 732 733 setIndividualSensorPrivacyUnchecked(userId, source, sensor, enable); 734 } 735 setIndividualSensorPrivacyUnchecked(int userId, int source, int sensor, boolean enable)736 private void setIndividualSensorPrivacyUnchecked(int userId, int source, int sensor, 737 boolean enable) { 738 synchronized (mLock) { 739 SparseArray<SensorState> userIndividualEnabled = mIndividualEnabled.get(userId, 740 new SparseArray<>()); 741 SensorState sensorState = userIndividualEnabled.get(sensor); 742 long lastChange; 743 if (sensorState != null) { 744 lastChange = sensorState.mLastChange; 745 if (!sensorState.setEnabled(enable)) { 746 // State not changing 747 return; 748 } 749 } else { 750 sensorState = new SensorState(enable); 751 lastChange = sensorState.mLastChange; 752 userIndividualEnabled.put(sensor, sensorState); 753 } 754 mIndividualEnabled.put(userId, userIndividualEnabled); 755 756 if (userId == mUserManagerInternal.getProfileParentId(userId)) { 757 logSensorPrivacyToggle(source, sensor, sensorState.mEnabled, lastChange); 758 } 759 760 if (!enable) { 761 long token = Binder.clearCallingIdentity(); 762 try { 763 // Remove any notifications prompting the user to disable sensory privacy 764 NotificationManager notificationManager = 765 mContext.getSystemService(NotificationManager.class); 766 767 notificationManager.cancel(sensor); 768 } finally { 769 Binder.restoreCallingIdentity(token); 770 } 771 } 772 persistSensorPrivacyState(); 773 } 774 mHandler.onSensorPrivacyChanged(userId, sensor, enable); 775 } 776 canChangeIndividualSensorPrivacy(@serIdInt int userId, int sensor)777 private boolean canChangeIndividualSensorPrivacy(@UserIdInt int userId, int sensor) { 778 if (sensor == MICROPHONE && mEmergencyCallHelper.isInEmergencyCall()) { 779 // During emergency call the microphone toggle managed automatically 780 Log.i(TAG, "Can't change mic toggle during an emergency call"); 781 return false; 782 } 783 784 if (mKeyguardManager != null && mKeyguardManager.isDeviceLocked(userId)) { 785 Log.i(TAG, "Can't change mic/cam toggle while device is locked"); 786 return false; 787 } 788 789 if (sensor == MICROPHONE && mUserManagerInternal.getUserRestriction(userId, 790 UserManager.DISALLOW_MICROPHONE_TOGGLE)) { 791 Log.i(TAG, "Can't change mic toggle due to admin restriction"); 792 return false; 793 } 794 795 if (sensor == CAMERA && mUserManagerInternal.getUserRestriction(userId, 796 UserManager.DISALLOW_CAMERA_TOGGLE)) { 797 Log.i(TAG, "Can't change camera toggle due to admin restriction"); 798 return false; 799 } 800 return true; 801 } 802 logSensorPrivacyToggle(int source, int sensor, boolean enabled, long lastChange)803 private void logSensorPrivacyToggle(int source, int sensor, boolean enabled, 804 long lastChange) { 805 long logMins = Math.max(0, (getCurrentTimeMillis() - lastChange) / (1000 * 60)); 806 807 int logAction = -1; 808 if (enabled) { 809 logAction = PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_OFF; 810 } else { 811 logAction = PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_ON; 812 } 813 814 int logSensor = -1; 815 switch(sensor) { 816 case CAMERA: 817 logSensor = PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__CAMERA; 818 break; 819 case MICROPHONE: 820 logSensor = PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__MICROPHONE; 821 break; 822 default: 823 logSensor = PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__SENSOR_UNKNOWN; 824 } 825 826 int logSource = -1; 827 switch(source) { 828 case QS_TILE : 829 logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__QS_TILE; 830 break; 831 case DIALOG : 832 logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__DIALOG; 833 break; 834 case SETTINGS: 835 logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SETTINGS; 836 break; 837 default: 838 logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SOURCE_UNKNOWN; 839 } 840 841 if (DEBUG || DEBUG_LOGGING) { 842 Log.d(TAG, "Logging sensor toggle interaction:" + " logSensor=" + logSensor 843 + " logAction=" + logAction + " logSource=" + logSource + " logMins=" 844 + logMins); 845 } 846 write(PRIVACY_SENSOR_TOGGLE_INTERACTION, logSensor, logAction, logSource, logMins); 847 848 } 849 850 @Override setIndividualSensorPrivacyForProfileGroup(@serIdInt int userId, @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable)851 public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId, 852 @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable) { 853 enforceManageSensorPrivacyPermission(); 854 if (userId == UserHandle.USER_CURRENT) { 855 userId = mCurrentUser; 856 } 857 int parentId = mUserManagerInternal.getProfileParentId(userId); 858 forAllUsers(userId2 -> { 859 if (parentId == mUserManagerInternal.getProfileParentId(userId2)) { 860 setIndividualSensorPrivacy(userId2, source, sensor, enable); 861 } 862 }); 863 } 864 865 /** 866 * Enforces the caller contains the necessary permission to change the state of sensor 867 * privacy. 868 */ enforceManageSensorPrivacyPermission()869 private void enforceManageSensorPrivacyPermission() { 870 enforcePermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY, 871 "Changing sensor privacy requires the following permission: " 872 + MANAGE_SENSOR_PRIVACY); 873 } 874 875 /** 876 * Enforces the caller contains the necessary permission to observe changes to the sate of 877 * sensor privacy. 878 */ enforceObserveSensorPrivacyPermission()879 private void enforceObserveSensorPrivacyPermission() { 880 enforcePermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY, 881 "Observing sensor privacy changes requires the following permission: " 882 + android.Manifest.permission.OBSERVE_SENSOR_PRIVACY); 883 } 884 enforcePermission(String permission, String message)885 private void enforcePermission(String permission, String message) { 886 if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { 887 return; 888 } 889 throw new SecurityException(message); 890 } 891 892 /** 893 * Returns whether sensor privacy is enabled. 894 */ 895 @Override isSensorPrivacyEnabled()896 public boolean isSensorPrivacyEnabled() { 897 enforceObserveSensorPrivacyPermission(); 898 return isSensorPrivacyEnabled(USER_SYSTEM); 899 } 900 isSensorPrivacyEnabled(@serIdInt int userId)901 private boolean isSensorPrivacyEnabled(@UserIdInt int userId) { 902 synchronized (mLock) { 903 return mEnabled.get(userId, false); 904 } 905 } 906 907 @Override isIndividualSensorPrivacyEnabled(@serIdInt int userId, int sensor)908 public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) { 909 if (DEBUG) { 910 Log.d(TAG, "callingUid=" + Binder.getCallingUid() 911 + " callingPid=" + Binder.getCallingPid() 912 + " isIndividualSensorPrivacyEnabled(" 913 + "userId=" + userId 914 + " sensor=" + sensor 915 + ")"); 916 } 917 enforceObserveSensorPrivacyPermission(); 918 if (userId == UserHandle.USER_CURRENT) { 919 userId = mCurrentUser; 920 } 921 synchronized (mLock) { 922 return isIndividualSensorPrivacyEnabledLocked(userId, sensor); 923 } 924 } 925 isIndividualSensorPrivacyEnabledLocked(int userId, int sensor)926 private boolean isIndividualSensorPrivacyEnabledLocked(int userId, int sensor) { 927 SparseArray<SensorState> states = mIndividualEnabled.get(userId); 928 if (states == null) { 929 return false; 930 } 931 SensorState state = states.get(sensor); 932 if (state == null) { 933 return false; 934 } 935 return state.mEnabled; 936 } 937 938 /** 939 * Returns the state of sensor privacy from persistent storage. 940 */ readPersistedSensorPrivacyStateLocked()941 private boolean readPersistedSensorPrivacyStateLocked() { 942 // if the file does not exist then sensor privacy has not yet been enabled on 943 // the device. 944 945 SparseArray<Object> map = new SparseArray<>(); 946 int version = -1; 947 948 if (mAtomicFile.exists()) { 949 try (FileInputStream inputStream = mAtomicFile.openRead()) { 950 TypedXmlPullParser parser = Xml.resolvePullParser(inputStream); 951 XmlUtils.beginDocument(parser, XML_TAG_SENSOR_PRIVACY); 952 final int persistenceVersion = parser.getAttributeInt(null, 953 XML_ATTRIBUTE_PERSISTENCE_VERSION, 0); 954 955 // Use inline string literals for xml tags/attrs when parsing old versions since 956 // these should never be changed even with refactorings. 957 if (persistenceVersion == 0) { 958 boolean enabled = parser.getAttributeBoolean(null, "enabled", false); 959 SparseArray<SensorState> individualEnabled = new SparseArray<>(); 960 version = 0; 961 962 XmlUtils.nextElement(parser); 963 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { 964 String tagName = parser.getName(); 965 if ("individual-sensor-privacy".equals(tagName)) { 966 int sensor = XmlUtils.readIntAttribute(parser, "sensor"); 967 boolean indEnabled = XmlUtils.readBooleanAttribute(parser, 968 "enabled"); 969 individualEnabled.put(sensor, new SensorState(indEnabled)); 970 XmlUtils.skipCurrentTag(parser); 971 } else { 972 XmlUtils.nextElement(parser); 973 } 974 } 975 map.put(VER0_ENABLED, enabled); 976 map.put(VER0_INDIVIDUAL_ENABLED, individualEnabled); 977 } else if (persistenceVersion == CURRENT_PERSISTENCE_VERSION) { 978 SparseBooleanArray enabled = new SparseBooleanArray(); 979 SparseArray<SparseArray<SensorState>> individualEnabled = 980 new SparseArray<>(); 981 version = parser.getAttributeInt(null, 982 XML_ATTRIBUTE_VERSION, 1); 983 984 int currentUserId = -1; 985 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { 986 XmlUtils.nextElement(parser); 987 String tagName = parser.getName(); 988 if (XML_TAG_USER.equals(tagName)) { 989 currentUserId = parser.getAttributeInt(null, XML_ATTRIBUTE_ID); 990 boolean isEnabled = parser.getAttributeBoolean(null, 991 XML_ATTRIBUTE_ENABLED); 992 if (enabled.indexOfKey(currentUserId) >= 0) { 993 Log.e(TAG, "User listed multiple times in file.", 994 new RuntimeException()); 995 mAtomicFile.delete(); 996 version = -1; 997 break; 998 } 999 1000 if (mUserManagerInternal.getUserInfo(currentUserId) == null) { 1001 // User may no longer exist, skip this user 1002 currentUserId = -1; 1003 continue; 1004 } 1005 1006 enabled.put(currentUserId, isEnabled); 1007 } 1008 if (XML_TAG_INDIVIDUAL_SENSOR_PRIVACY.equals(tagName)) { 1009 if (mUserManagerInternal.getUserInfo(currentUserId) == null) { 1010 // User may no longer exist or isn't set 1011 continue; 1012 } 1013 int sensor = parser.getAttributeInt(null, XML_ATTRIBUTE_SENSOR); 1014 boolean isEnabled = parser.getAttributeBoolean(null, 1015 XML_ATTRIBUTE_ENABLED); 1016 long lastChange = parser 1017 .getAttributeLong(null, XML_ATTRIBUTE_LAST_CHANGE, -1); 1018 SparseArray<SensorState> userIndividualEnabled = 1019 individualEnabled.get(currentUserId, new SparseArray<>()); 1020 1021 userIndividualEnabled 1022 .put(sensor, new SensorState(isEnabled, lastChange)); 1023 individualEnabled.put(currentUserId, userIndividualEnabled); 1024 } 1025 } 1026 1027 map.put(VER1_ENABLED, enabled); 1028 map.put(VER1_INDIVIDUAL_ENABLED, individualEnabled); 1029 } else { 1030 Log.e(TAG, "Unknown persistence version: " + persistenceVersion 1031 + ". Deleting.", 1032 new RuntimeException()); 1033 mAtomicFile.delete(); 1034 version = -1; 1035 } 1036 1037 } catch (IOException | XmlPullParserException e) { 1038 Log.e(TAG, "Caught an exception reading the state from storage: ", e); 1039 // Delete the file to prevent the same error on subsequent calls and assume 1040 // sensor privacy is not enabled. 1041 mAtomicFile.delete(); 1042 version = -1; 1043 } 1044 } 1045 1046 try { 1047 return upgradeAndInit(version, map); 1048 } catch (Exception e) { 1049 Log.wtf(TAG, "Failed to upgrade and set sensor privacy state," 1050 + " resetting to default.", e); 1051 mEnabled = new SparseBooleanArray(); 1052 mIndividualEnabled = new SparseArray<>(); 1053 return true; 1054 } 1055 } 1056 upgradeAndInit(int version, SparseArray map)1057 private boolean upgradeAndInit(int version, SparseArray map) { 1058 if (version == -1) { 1059 // New file, default state for current version goes here. 1060 mEnabled = new SparseBooleanArray(); 1061 mIndividualEnabled = new SparseArray<>(); 1062 forAllUsers(userId -> mEnabled.put(userId, false)); 1063 forAllUsers(userId -> mIndividualEnabled.put(userId, new SparseArray<>())); 1064 return true; 1065 } 1066 boolean upgraded = false; 1067 final int[] users = getLocalService(UserManagerInternal.class).getUserIds(); 1068 if (version == 0) { 1069 final boolean enabled = (boolean) map.get(VER0_ENABLED); 1070 final SparseArray<SensorState> individualEnabled = 1071 (SparseArray<SensorState>) map.get(VER0_INDIVIDUAL_ENABLED); 1072 1073 final SparseBooleanArray perUserEnabled = new SparseBooleanArray(); 1074 final SparseArray<SparseArray<SensorState>> perUserIndividualEnabled = 1075 new SparseArray<>(); 1076 1077 // Copy global state to each user 1078 for (int i = 0; i < users.length; i++) { 1079 int user = users[i]; 1080 perUserEnabled.put(user, enabled); 1081 SparseArray<SensorState> userIndividualSensorEnabled = new SparseArray<>(); 1082 perUserIndividualEnabled.put(user, userIndividualSensorEnabled); 1083 for (int j = 0; j < individualEnabled.size(); j++) { 1084 final int sensor = individualEnabled.keyAt(j); 1085 final SensorState isSensorEnabled = individualEnabled.valueAt(j); 1086 userIndividualSensorEnabled.put(sensor, isSensorEnabled); 1087 } 1088 } 1089 1090 map.clear(); 1091 map.put(VER1_ENABLED, perUserEnabled); 1092 map.put(VER1_INDIVIDUAL_ENABLED, perUserIndividualEnabled); 1093 1094 version = 1; 1095 upgraded = true; 1096 } 1097 if (version == CURRENT_VERSION) { 1098 mEnabled = (SparseBooleanArray) map.get(VER1_ENABLED); 1099 mIndividualEnabled = 1100 (SparseArray<SparseArray<SensorState>>) map.get(VER1_INDIVIDUAL_ENABLED); 1101 } 1102 return upgraded; 1103 } 1104 1105 /** 1106 * Persists the state of sensor privacy. 1107 */ persistSensorPrivacyState()1108 private void persistSensorPrivacyState() { 1109 synchronized (mLock) { 1110 persistSensorPrivacyStateLocked(); 1111 } 1112 } 1113 persistSensorPrivacyStateLocked()1114 private void persistSensorPrivacyStateLocked() { 1115 FileOutputStream outputStream = null; 1116 try { 1117 outputStream = mAtomicFile.startWrite(); 1118 TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream); 1119 serializer.startDocument(null, true); 1120 serializer.startTag(null, XML_TAG_SENSOR_PRIVACY); 1121 serializer.attributeInt( 1122 null, XML_ATTRIBUTE_PERSISTENCE_VERSION, CURRENT_PERSISTENCE_VERSION); 1123 serializer.attributeInt(null, XML_ATTRIBUTE_VERSION, CURRENT_VERSION); 1124 forAllUsers(userId -> { 1125 serializer.startTag(null, XML_TAG_USER); 1126 serializer.attributeInt(null, XML_ATTRIBUTE_ID, userId); 1127 serializer.attributeBoolean( 1128 null, XML_ATTRIBUTE_ENABLED, isSensorPrivacyEnabled(userId)); 1129 1130 SparseArray<SensorState> individualEnabled = 1131 mIndividualEnabled.get(userId, new SparseArray<>()); 1132 int numIndividual = individualEnabled.size(); 1133 for (int i = 0; i < numIndividual; i++) { 1134 serializer.startTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY); 1135 int sensor = individualEnabled.keyAt(i); 1136 SensorState sensorState = individualEnabled.valueAt(i); 1137 boolean enabled = sensorState.mEnabled; 1138 long lastChange = sensorState.mLastChange; 1139 serializer.attributeInt(null, XML_ATTRIBUTE_SENSOR, sensor); 1140 serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enabled); 1141 serializer.attributeLong(null, XML_ATTRIBUTE_LAST_CHANGE, lastChange); 1142 serializer.endTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY); 1143 } 1144 serializer.endTag(null, XML_TAG_USER); 1145 1146 }); 1147 serializer.endTag(null, XML_TAG_SENSOR_PRIVACY); 1148 serializer.endDocument(); 1149 mAtomicFile.finishWrite(outputStream); 1150 } catch (IOException e) { 1151 Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e); 1152 mAtomicFile.failWrite(outputStream); 1153 } 1154 } 1155 1156 @Override supportsSensorToggle(int sensor)1157 public boolean supportsSensorToggle(int sensor) { 1158 if (sensor == MICROPHONE) { 1159 return mContext.getResources().getBoolean(R.bool.config_supportsMicToggle); 1160 } else if (sensor == CAMERA) { 1161 return mContext.getResources().getBoolean(R.bool.config_supportsCamToggle); 1162 } 1163 throw new IllegalArgumentException("Unable to find value " + sensor); 1164 } 1165 1166 /** 1167 * Registers a listener to be notified when the sensor privacy state changes. 1168 */ 1169 @Override addSensorPrivacyListener(ISensorPrivacyListener listener)1170 public void addSensorPrivacyListener(ISensorPrivacyListener listener) { 1171 enforceObserveSensorPrivacyPermission(); 1172 if (listener == null) { 1173 throw new NullPointerException("listener cannot be null"); 1174 } 1175 mHandler.addListener(listener); 1176 } 1177 1178 /** 1179 * Registers a listener to be notified when the sensor privacy state changes. 1180 */ 1181 @Override addIndividualSensorPrivacyListener(int userId, int sensor, ISensorPrivacyListener listener)1182 public void addIndividualSensorPrivacyListener(int userId, int sensor, 1183 ISensorPrivacyListener listener) { 1184 enforceObserveSensorPrivacyPermission(); 1185 if (listener == null) { 1186 throw new IllegalArgumentException("listener cannot be null"); 1187 } 1188 mHandler.addListener(userId, sensor, listener); 1189 } 1190 1191 1192 /** 1193 * Registers a listener to be notified when the sensor privacy state changes. The callback 1194 * can be called if the user changes and the setting is different between the transitioning 1195 * users. 1196 */ 1197 @Override addUserGlobalIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener)1198 public void addUserGlobalIndividualSensorPrivacyListener(int sensor, 1199 ISensorPrivacyListener listener) { 1200 enforceObserveSensorPrivacyPermission(); 1201 if (listener == null) { 1202 throw new IllegalArgumentException("listener cannot be null"); 1203 } 1204 mHandler.addUserGlobalListener(sensor, listener); 1205 } 1206 1207 /** 1208 * Unregisters a listener from sensor privacy state change notifications. 1209 */ 1210 @Override removeSensorPrivacyListener(ISensorPrivacyListener listener)1211 public void removeSensorPrivacyListener(ISensorPrivacyListener listener) { 1212 enforceObserveSensorPrivacyPermission(); 1213 if (listener == null) { 1214 throw new NullPointerException("listener cannot be null"); 1215 } 1216 mHandler.removeListener(listener); 1217 } 1218 1219 /** 1220 * Unregisters a listener from sensor privacy state change notifications. 1221 */ 1222 @Override removeIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener)1223 public void removeIndividualSensorPrivacyListener(int sensor, 1224 ISensorPrivacyListener listener) { 1225 enforceObserveSensorPrivacyPermission(); 1226 if (listener == null) { 1227 throw new IllegalArgumentException("listener cannot be null"); 1228 } 1229 mHandler.removeListener(sensor, listener); 1230 } 1231 1232 @Override removeUserGlobalIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener)1233 public void removeUserGlobalIndividualSensorPrivacyListener(int sensor, 1234 ISensorPrivacyListener listener) { 1235 enforceObserveSensorPrivacyPermission(); 1236 if (listener == null) { 1237 throw new IllegalArgumentException("listener cannot be null"); 1238 } 1239 mHandler.removeUserGlobalListener(sensor, listener); 1240 } 1241 1242 @Override suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress)1243 public void suppressIndividualSensorPrivacyReminders(int userId, int sensor, 1244 IBinder token, boolean suppress) { 1245 enforceManageSensorPrivacyPermission(); 1246 if (userId == UserHandle.USER_CURRENT) { 1247 userId = mCurrentUser; 1248 } 1249 Objects.requireNonNull(token); 1250 1251 Pair<Integer, UserHandle> key = new Pair<>(sensor, UserHandle.of(userId)); 1252 1253 synchronized (mLock) { 1254 if (suppress) { 1255 try { 1256 token.linkToDeath(this, 0); 1257 } catch (RemoteException e) { 1258 Log.e(TAG, "Could not suppress sensor use reminder", e); 1259 return; 1260 } 1261 1262 ArrayList<IBinder> suppressPackageReminderTokens = mSuppressReminders.get(key); 1263 if (suppressPackageReminderTokens == null) { 1264 suppressPackageReminderTokens = new ArrayList<>(1); 1265 mSuppressReminders.put(key, suppressPackageReminderTokens); 1266 } 1267 1268 suppressPackageReminderTokens.add(token); 1269 } else { 1270 mHandler.removeSuppressPackageReminderToken(key, token); 1271 } 1272 } 1273 } 1274 1275 @Override showSensorUseDialog(int sensor)1276 public void showSensorUseDialog(int sensor) { 1277 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 1278 throw new SecurityException("Can only be called by the system uid"); 1279 } 1280 if (!isIndividualSensorPrivacyEnabled(mCurrentUser, sensor)) { 1281 return; 1282 } 1283 enqueueSensorUseReminderDialogAsync( 1284 -1, UserHandle.of(mCurrentUser), "android", sensor); 1285 } 1286 userSwitching(int from, int to)1287 private void userSwitching(int from, int to) { 1288 boolean micState; 1289 boolean camState; 1290 boolean prevMicState; 1291 boolean prevCamState; 1292 synchronized (mLock) { 1293 prevMicState = isIndividualSensorPrivacyEnabledLocked(from, MICROPHONE); 1294 prevCamState = isIndividualSensorPrivacyEnabledLocked(from, CAMERA); 1295 micState = isIndividualSensorPrivacyEnabledLocked(to, MICROPHONE); 1296 camState = isIndividualSensorPrivacyEnabledLocked(to, CAMERA); 1297 } 1298 if (from == USER_NULL || prevMicState != micState) { 1299 mHandler.onUserGlobalSensorPrivacyChanged(MICROPHONE, micState); 1300 setGlobalRestriction(MICROPHONE, micState); 1301 } 1302 if (from == USER_NULL || prevCamState != camState) { 1303 mHandler.onUserGlobalSensorPrivacyChanged(CAMERA, camState); 1304 setGlobalRestriction(CAMERA, camState); 1305 } 1306 } 1307 setGlobalRestriction(int sensor, boolean enabled)1308 private void setGlobalRestriction(int sensor, boolean enabled) { 1309 switch(sensor) { 1310 case MICROPHONE: 1311 mAppOpsManagerInternal.setGlobalRestriction(OP_RECORD_AUDIO, enabled, 1312 mAppOpsRestrictionToken); 1313 mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled, 1314 mAppOpsRestrictionToken); 1315 break; 1316 case CAMERA: 1317 mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled, 1318 mAppOpsRestrictionToken); 1319 mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_CAMERA, enabled, 1320 mAppOpsRestrictionToken); 1321 break; 1322 } 1323 } 1324 1325 /** 1326 * Remove a sensor use reminder suppression token. 1327 * 1328 * @param key Key the token is in 1329 * @param token The token to remove 1330 */ removeSuppressPackageReminderToken(@onNull Pair<Integer, UserHandle> key, @NonNull IBinder token)1331 private void removeSuppressPackageReminderToken(@NonNull Pair<Integer, UserHandle> key, 1332 @NonNull IBinder token) { 1333 synchronized (mLock) { 1334 ArrayList<IBinder> suppressPackageReminderTokens = 1335 mSuppressReminders.get(key); 1336 if (suppressPackageReminderTokens == null) { 1337 Log.e(TAG, "No tokens for " + key); 1338 return; 1339 } 1340 1341 boolean wasRemoved = suppressPackageReminderTokens.remove(token); 1342 if (wasRemoved) { 1343 token.unlinkToDeath(this, 0); 1344 1345 if (suppressPackageReminderTokens.isEmpty()) { 1346 mSuppressReminders.remove(key); 1347 } 1348 } else { 1349 Log.w(TAG, "Could not remove sensor use reminder suppression token " + token 1350 + " from " + key); 1351 } 1352 } 1353 } 1354 1355 /** 1356 * A owner of a suppressor token died. Clean up. 1357 * 1358 * @param token The token that is invalid now. 1359 */ 1360 @Override binderDied(@onNull IBinder token)1361 public void binderDied(@NonNull IBinder token) { 1362 synchronized (mLock) { 1363 for (Pair<Integer, UserHandle> key : mSuppressReminders.keySet()) { 1364 removeSuppressPackageReminderToken(key, token); 1365 } 1366 } 1367 } 1368 1369 @Override binderDied()1370 public void binderDied() { 1371 // Handled in binderDied(IBinder) 1372 } 1373 1374 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1375 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1376 Objects.requireNonNull(fd); 1377 1378 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1379 1380 int opti = 0; 1381 boolean dumpAsProto = false; 1382 while (opti < args.length) { 1383 String opt = args[opti]; 1384 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 1385 break; 1386 } 1387 opti++; 1388 if ("--proto".equals(opt)) { 1389 dumpAsProto = true; 1390 } else { 1391 pw.println("Unknown argument: " + opt + "; use -h for help"); 1392 } 1393 } 1394 1395 final long identity = Binder.clearCallingIdentity(); 1396 try { 1397 if (dumpAsProto) { 1398 dump(new DualDumpOutputStream(new ProtoOutputStream(fd))); 1399 } else { 1400 pw.println("SENSOR PRIVACY MANAGER STATE (dumpsys " 1401 + Context.SENSOR_PRIVACY_SERVICE + ")"); 1402 1403 dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " "))); 1404 } 1405 } finally { 1406 Binder.restoreCallingIdentity(identity); 1407 } 1408 } 1409 1410 /** 1411 * Dump state to {@link DualDumpOutputStream}. 1412 * 1413 * @param dumpStream The destination to dump to 1414 */ dump(@onNull DualDumpOutputStream dumpStream)1415 private void dump(@NonNull DualDumpOutputStream dumpStream) { 1416 synchronized (mLock) { 1417 1418 forAllUsers(userId -> { 1419 long userToken = dumpStream.start("users", SensorPrivacyServiceDumpProto.USER); 1420 dumpStream.write("user_id", SensorPrivacyUserProto.USER_ID, userId); 1421 dumpStream.write("is_enabled", SensorPrivacyUserProto.IS_ENABLED, 1422 mEnabled.get(userId, false)); 1423 1424 SparseArray<SensorState> individualEnabled = mIndividualEnabled.get(userId); 1425 if (individualEnabled != null) { 1426 int numIndividualEnabled = individualEnabled.size(); 1427 for (int i = 0; i < numIndividualEnabled; i++) { 1428 long individualToken = dumpStream.start("individual_enabled_sensor", 1429 SensorPrivacyUserProto.INDIVIDUAL_ENABLED_SENSOR); 1430 1431 dumpStream.write("sensor", 1432 SensorPrivacyIndividualEnabledSensorProto.SENSOR, 1433 individualEnabled.keyAt(i)); 1434 dumpStream.write("is_enabled", 1435 SensorPrivacyIndividualEnabledSensorProto.IS_ENABLED, 1436 individualEnabled.valueAt(i).mEnabled); 1437 // TODO dump last change 1438 1439 dumpStream.end(individualToken); 1440 } 1441 } 1442 dumpStream.end(userToken); 1443 }); 1444 } 1445 1446 dumpStream.flush(); 1447 } 1448 1449 /** 1450 * Convert a string into a {@link SensorPrivacyManager.Sensors.Sensor id}. 1451 * 1452 * @param sensor The name to convert 1453 * 1454 * @return The id corresponding to the name 1455 */ sensorStrToId(@ullable String sensor)1456 private @SensorPrivacyManager.Sensors.Sensor int sensorStrToId(@Nullable String sensor) { 1457 if (sensor == null) { 1458 return UNKNOWN; 1459 } 1460 1461 switch (sensor) { 1462 case "microphone": 1463 return MICROPHONE; 1464 case "camera": 1465 return CAMERA; 1466 default: { 1467 return UNKNOWN; 1468 } 1469 } 1470 } 1471 1472 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1473 public void onShellCommand(FileDescriptor in, FileDescriptor out, 1474 FileDescriptor err, String[] args, ShellCallback callback, 1475 ResultReceiver resultReceiver) { 1476 (new ShellCommand() { 1477 @Override 1478 public int onCommand(String cmd) { 1479 if (cmd == null) { 1480 return handleDefaultCommands(cmd); 1481 } 1482 1483 int userId = Integer.parseInt(getNextArgRequired()); 1484 1485 final PrintWriter pw = getOutPrintWriter(); 1486 switch (cmd) { 1487 case "enable" : { 1488 int sensor = sensorStrToId(getNextArgRequired()); 1489 if (sensor == UNKNOWN) { 1490 pw.println("Invalid sensor"); 1491 return -1; 1492 } 1493 1494 setIndividualSensorPrivacy(userId, SHELL, sensor, true); 1495 } 1496 break; 1497 case "disable" : { 1498 int sensor = sensorStrToId(getNextArgRequired()); 1499 if (sensor == UNKNOWN) { 1500 pw.println("Invalid sensor"); 1501 return -1; 1502 } 1503 1504 setIndividualSensorPrivacy(userId, SHELL, sensor, false); 1505 } 1506 break; 1507 case "reset": { 1508 int sensor = sensorStrToId(getNextArgRequired()); 1509 if (sensor == UNKNOWN) { 1510 pw.println("Invalid sensor"); 1511 return -1; 1512 } 1513 1514 enforceManageSensorPrivacyPermission(); 1515 1516 synchronized (mLock) { 1517 SparseArray<SensorState> individualEnabled = 1518 mIndividualEnabled.get(userId); 1519 if (individualEnabled != null) { 1520 individualEnabled.delete(sensor); 1521 } 1522 persistSensorPrivacyState(); 1523 } 1524 } 1525 break; 1526 default: 1527 return handleDefaultCommands(cmd); 1528 } 1529 1530 return 0; 1531 } 1532 1533 @Override 1534 public void onHelp() { 1535 final PrintWriter pw = getOutPrintWriter(); 1536 1537 pw.println("Sensor privacy manager (" + Context.SENSOR_PRIVACY_SERVICE 1538 + ") commands:"); 1539 pw.println(" help"); 1540 pw.println(" Print this help text."); 1541 pw.println(""); 1542 pw.println(" enable USER_ID SENSOR"); 1543 pw.println(" Enable privacy for a certain sensor."); 1544 pw.println(""); 1545 pw.println(" disable USER_ID SENSOR"); 1546 pw.println(" Disable privacy for a certain sensor."); 1547 pw.println(""); 1548 pw.println(" reset USER_ID SENSOR"); 1549 pw.println(" Reset privacy state for a certain sensor."); 1550 pw.println(""); 1551 } 1552 }).exec(this, in, out, err, args, callback, resultReceiver); 1553 } 1554 } 1555 1556 /** 1557 * Handles sensor privacy state changes and notifying listeners of the change. 1558 */ 1559 private final class SensorPrivacyHandler extends Handler { 1560 private static final int MESSAGE_SENSOR_PRIVACY_CHANGED = 1; 1561 1562 private final Object mListenerLock = new Object(); 1563 1564 @GuardedBy("mListenerLock") 1565 private final RemoteCallbackList<ISensorPrivacyListener> mListeners = 1566 new RemoteCallbackList<>(); 1567 @GuardedBy("mListenerLock") 1568 private final SparseArray<SparseArray<RemoteCallbackList<ISensorPrivacyListener>>> 1569 mIndividualSensorListeners = new SparseArray<>(); 1570 @GuardedBy("mListenerLock") 1571 private final SparseArray<RemoteCallbackList<ISensorPrivacyListener>> 1572 mUserGlobalIndividualSensorListeners = new SparseArray<>(); 1573 @GuardedBy("mListenerLock") 1574 private final ArrayMap<ISensorPrivacyListener, Pair<DeathRecipient, Integer>> 1575 mDeathRecipients; 1576 private final Context mContext; 1577 SensorPrivacyHandler(Looper looper, Context context)1578 SensorPrivacyHandler(Looper looper, Context context) { 1579 super(looper); 1580 mDeathRecipients = new ArrayMap<>(); 1581 mContext = context; 1582 } 1583 onSensorPrivacyChanged(boolean enabled)1584 public void onSensorPrivacyChanged(boolean enabled) { 1585 sendMessage(PooledLambda.obtainMessage(SensorPrivacyHandler::handleSensorPrivacyChanged, 1586 this, enabled)); 1587 sendMessage( 1588 PooledLambda.obtainMessage(SensorPrivacyServiceImpl::persistSensorPrivacyState, 1589 mSensorPrivacyServiceImpl)); 1590 } 1591 onSensorPrivacyChanged(int userId, int sensor, boolean enabled)1592 public void onSensorPrivacyChanged(int userId, int sensor, boolean enabled) { 1593 sendMessage(PooledLambda.obtainMessage(SensorPrivacyHandler::handleSensorPrivacyChanged, 1594 this, userId, sensor, enabled)); 1595 sendMessage( 1596 PooledLambda.obtainMessage(SensorPrivacyServiceImpl::persistSensorPrivacyState, 1597 mSensorPrivacyServiceImpl)); 1598 } 1599 onUserGlobalSensorPrivacyChanged(int sensor, boolean enabled)1600 public void onUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) { 1601 sendMessage(PooledLambda.obtainMessage( 1602 SensorPrivacyHandler::handleUserGlobalSensorPrivacyChanged, 1603 this, sensor, enabled)); 1604 } 1605 addListener(ISensorPrivacyListener listener)1606 public void addListener(ISensorPrivacyListener listener) { 1607 synchronized (mListenerLock) { 1608 if (mListeners.register(listener)) { 1609 addDeathRecipient(listener); 1610 } 1611 } 1612 } 1613 addListener(int userId, int sensor, ISensorPrivacyListener listener)1614 public void addListener(int userId, int sensor, ISensorPrivacyListener listener) { 1615 synchronized (mListenerLock) { 1616 SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = 1617 mIndividualSensorListeners.get(userId); 1618 if (listenersForUser == null) { 1619 listenersForUser = new SparseArray<>(); 1620 mIndividualSensorListeners.put(userId, listenersForUser); 1621 } 1622 RemoteCallbackList<ISensorPrivacyListener> listeners = listenersForUser.get(sensor); 1623 if (listeners == null) { 1624 listeners = new RemoteCallbackList<>(); 1625 listenersForUser.put(sensor, listeners); 1626 } 1627 if (listeners.register(listener)) { 1628 addDeathRecipient(listener); 1629 } 1630 } 1631 } 1632 addUserGlobalListener(int sensor, ISensorPrivacyListener listener)1633 public void addUserGlobalListener(int sensor, ISensorPrivacyListener listener) { 1634 synchronized (mListenerLock) { 1635 RemoteCallbackList<ISensorPrivacyListener> listeners = 1636 mUserGlobalIndividualSensorListeners.get(sensor); 1637 if (listeners == null) { 1638 listeners = new RemoteCallbackList<>(); 1639 mUserGlobalIndividualSensorListeners.put(sensor, listeners); 1640 } 1641 if (listeners.register(listener)) { 1642 addDeathRecipient(listener); 1643 } 1644 } 1645 } 1646 removeListener(ISensorPrivacyListener listener)1647 public void removeListener(ISensorPrivacyListener listener) { 1648 synchronized (mListenerLock) { 1649 if (mListeners.unregister(listener)) { 1650 removeDeathRecipient(listener); 1651 } 1652 } 1653 } 1654 removeListener(int sensor, ISensorPrivacyListener listener)1655 public void removeListener(int sensor, ISensorPrivacyListener listener) { 1656 synchronized (mListenerLock) { 1657 for (int i = 0, numUsers = mIndividualSensorListeners.size(); i < numUsers; i++) { 1658 RemoteCallbackList callbacks = 1659 mIndividualSensorListeners.valueAt(i).get(sensor); 1660 if (callbacks != null) { 1661 if (callbacks.unregister(listener)) { 1662 removeDeathRecipient(listener); 1663 } 1664 } 1665 } 1666 } 1667 } 1668 removeUserGlobalListener(int sensor, ISensorPrivacyListener listener)1669 public void removeUserGlobalListener(int sensor, ISensorPrivacyListener listener) { 1670 synchronized (mListenerLock) { 1671 RemoteCallbackList callbacks = 1672 mUserGlobalIndividualSensorListeners.get(sensor); 1673 if (callbacks != null) { 1674 if (callbacks.unregister(listener)) { 1675 removeDeathRecipient(listener); 1676 } 1677 } 1678 } 1679 } 1680 handleSensorPrivacyChanged(boolean enabled)1681 public void handleSensorPrivacyChanged(boolean enabled) { 1682 final int count = mListeners.beginBroadcast(); 1683 for (int i = 0; i < count; i++) { 1684 ISensorPrivacyListener listener = mListeners.getBroadcastItem(i); 1685 try { 1686 listener.onSensorPrivacyChanged(enabled); 1687 } catch (RemoteException e) { 1688 Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e); 1689 } 1690 } 1691 mListeners.finishBroadcast(); 1692 } 1693 handleSensorPrivacyChanged(int userId, int sensor, boolean enabled)1694 public void handleSensorPrivacyChanged(int userId, int sensor, boolean enabled) { 1695 mSensorPrivacyManagerInternal.dispatch(userId, sensor, enabled); 1696 SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = 1697 mIndividualSensorListeners.get(userId); 1698 1699 if (userId == mCurrentUser) { 1700 mSensorPrivacyServiceImpl.setGlobalRestriction(sensor, enabled); 1701 } 1702 1703 if (userId == mCurrentUser) { 1704 onUserGlobalSensorPrivacyChanged(sensor, enabled); 1705 } 1706 1707 if (listenersForUser == null) { 1708 return; 1709 } 1710 RemoteCallbackList<ISensorPrivacyListener> listeners = listenersForUser.get(sensor); 1711 if (listeners == null) { 1712 return; 1713 } 1714 try { 1715 final int count = listeners.beginBroadcast(); 1716 for (int i = 0; i < count; i++) { 1717 ISensorPrivacyListener listener = listeners.getBroadcastItem(i); 1718 try { 1719 listener.onSensorPrivacyChanged(enabled); 1720 } catch (RemoteException e) { 1721 Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e); 1722 } 1723 } 1724 } finally { 1725 listeners.finishBroadcast(); 1726 } 1727 } 1728 handleUserGlobalSensorPrivacyChanged(int sensor, boolean enabled)1729 public void handleUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) { 1730 RemoteCallbackList<ISensorPrivacyListener> listeners = 1731 mUserGlobalIndividualSensorListeners.get(sensor); 1732 1733 if (listeners == null) { 1734 return; 1735 } 1736 1737 try { 1738 final int count = listeners.beginBroadcast(); 1739 for (int i = 0; i < count; i++) { 1740 ISensorPrivacyListener listener = listeners.getBroadcastItem(i); 1741 try { 1742 listener.onSensorPrivacyChanged(enabled); 1743 } catch (RemoteException e) { 1744 Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e); 1745 } 1746 } 1747 } finally { 1748 listeners.finishBroadcast(); 1749 } 1750 } 1751 removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key, IBinder token)1752 public void removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key, 1753 IBinder token) { 1754 sendMessage(PooledLambda.obtainMessage( 1755 SensorPrivacyServiceImpl::removeSuppressPackageReminderToken, 1756 mSensorPrivacyServiceImpl, key, token)); 1757 } 1758 addDeathRecipient(ISensorPrivacyListener listener)1759 private void addDeathRecipient(ISensorPrivacyListener listener) { 1760 Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener); 1761 if (deathRecipient == null) { 1762 deathRecipient = new Pair<>(new DeathRecipient(listener), 1); 1763 } else { 1764 int newRefCount = deathRecipient.second + 1; 1765 deathRecipient = new Pair<>(deathRecipient.first, newRefCount); 1766 } 1767 mDeathRecipients.put(listener, deathRecipient); 1768 } 1769 removeDeathRecipient(ISensorPrivacyListener listener)1770 private void removeDeathRecipient(ISensorPrivacyListener listener) { 1771 Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener); 1772 if (deathRecipient == null) { 1773 return; 1774 } else { 1775 int newRefCount = deathRecipient.second - 1; 1776 if (newRefCount == 0) { 1777 mDeathRecipients.remove(listener); 1778 deathRecipient.first.destroy(); 1779 return; 1780 } 1781 deathRecipient = new Pair<>(deathRecipient.first, newRefCount); 1782 } 1783 mDeathRecipients.put(listener, deathRecipient); 1784 } 1785 } 1786 1787 private final class DeathRecipient implements IBinder.DeathRecipient { 1788 1789 private ISensorPrivacyListener mListener; 1790 DeathRecipient(ISensorPrivacyListener listener)1791 DeathRecipient(ISensorPrivacyListener listener) { 1792 mListener = listener; 1793 try { 1794 mListener.asBinder().linkToDeath(this, 0); 1795 } catch (RemoteException e) { 1796 } 1797 } 1798 1799 @Override binderDied()1800 public void binderDied() { 1801 mSensorPrivacyServiceImpl.removeSensorPrivacyListener(mListener); 1802 } 1803 destroy()1804 public void destroy() { 1805 try { 1806 mListener.asBinder().unlinkToDeath(this, 0); 1807 } catch (NoSuchElementException e) { 1808 } 1809 } 1810 } 1811 forAllUsers(FunctionalUtils.ThrowingConsumer<Integer> c)1812 private void forAllUsers(FunctionalUtils.ThrowingConsumer<Integer> c) { 1813 int[] userIds = mUserManagerInternal.getUserIds(); 1814 for (int i = 0; i < userIds.length; i++) { 1815 c.accept(userIds[i]); 1816 } 1817 } 1818 1819 private class SensorPrivacyManagerInternalImpl extends SensorPrivacyManagerInternal { 1820 1821 private ArrayMap<Integer, ArrayMap<Integer, ArraySet<OnSensorPrivacyChangedListener>>> 1822 mListeners = new ArrayMap<>(); 1823 private ArrayMap<Integer, ArraySet<OnUserSensorPrivacyChangedListener>> mAllUserListeners = 1824 new ArrayMap<>(); 1825 1826 private final Object mLock = new Object(); 1827 dispatch(int userId, int sensor, boolean enabled)1828 private void dispatch(int userId, int sensor, boolean enabled) { 1829 synchronized (mLock) { 1830 ArraySet<OnUserSensorPrivacyChangedListener> allUserSensorListeners = 1831 mAllUserListeners.get(sensor); 1832 if (allUserSensorListeners != null) { 1833 for (int i = 0; i < allUserSensorListeners.size(); i++) { 1834 OnUserSensorPrivacyChangedListener listener = 1835 allUserSensorListeners.valueAt(i); 1836 BackgroundThread.getHandler().post(() -> 1837 listener.onSensorPrivacyChanged(userId, enabled)); 1838 } 1839 } 1840 1841 ArrayMap<Integer, ArraySet<OnSensorPrivacyChangedListener>> userSensorListeners = 1842 mListeners.get(userId); 1843 if (userSensorListeners != null) { 1844 ArraySet<OnSensorPrivacyChangedListener> sensorListeners = 1845 userSensorListeners.get(sensor); 1846 if (sensorListeners != null) { 1847 for (int i = 0; i < sensorListeners.size(); i++) { 1848 OnSensorPrivacyChangedListener listener = sensorListeners.valueAt(i); 1849 BackgroundThread.getHandler().post(() -> 1850 listener.onSensorPrivacyChanged(enabled)); 1851 } 1852 } 1853 } 1854 } 1855 } 1856 1857 @Override isSensorPrivacyEnabled(int userId, int sensor)1858 public boolean isSensorPrivacyEnabled(int userId, int sensor) { 1859 return SensorPrivacyService.this 1860 .mSensorPrivacyServiceImpl.isIndividualSensorPrivacyEnabled(userId, sensor); 1861 } 1862 1863 @Override addSensorPrivacyListener(int userId, int sensor, OnSensorPrivacyChangedListener listener)1864 public void addSensorPrivacyListener(int userId, int sensor, 1865 OnSensorPrivacyChangedListener listener) { 1866 synchronized (mLock) { 1867 ArrayMap<Integer, ArraySet<OnSensorPrivacyChangedListener>> userSensorListeners = 1868 mListeners.get(userId); 1869 if (userSensorListeners == null) { 1870 userSensorListeners = new ArrayMap<>(); 1871 mListeners.put(userId, userSensorListeners); 1872 } 1873 1874 ArraySet<OnSensorPrivacyChangedListener> sensorListeners = 1875 userSensorListeners.get(sensor); 1876 if (sensorListeners == null) { 1877 sensorListeners = new ArraySet<>(); 1878 userSensorListeners.put(sensor, sensorListeners); 1879 } 1880 1881 sensorListeners.add(listener); 1882 } 1883 } 1884 1885 @Override addSensorPrivacyListenerForAllUsers(int sensor, OnUserSensorPrivacyChangedListener listener)1886 public void addSensorPrivacyListenerForAllUsers(int sensor, 1887 OnUserSensorPrivacyChangedListener listener) { 1888 synchronized (mLock) { 1889 ArraySet<OnUserSensorPrivacyChangedListener> sensorListeners = 1890 mAllUserListeners.get(sensor); 1891 if (sensorListeners == null) { 1892 sensorListeners = new ArraySet<>(); 1893 mAllUserListeners.put(sensor, sensorListeners); 1894 } 1895 1896 sensorListeners.add(listener); 1897 } 1898 } 1899 } 1900 1901 private class EmergencyCallHelper { 1902 private OutgoingEmergencyStateCallback mEmergencyStateCallback; 1903 private CallStateCallback mCallStateCallback; 1904 1905 private boolean mIsInEmergencyCall; 1906 private boolean mMicUnmutedForEmergencyCall; 1907 1908 private Object mEmergencyStateLock = new Object(); 1909 EmergencyCallHelper()1910 EmergencyCallHelper() { 1911 mEmergencyStateCallback = new OutgoingEmergencyStateCallback(); 1912 mCallStateCallback = new CallStateCallback(); 1913 1914 mTelephonyManager.registerTelephonyCallback(FgThread.getExecutor(), 1915 mEmergencyStateCallback); 1916 mTelephonyManager.registerTelephonyCallback(FgThread.getExecutor(), 1917 mCallStateCallback); 1918 } 1919 isInEmergencyCall()1920 boolean isInEmergencyCall() { 1921 synchronized (mEmergencyStateLock) { 1922 return mIsInEmergencyCall; 1923 } 1924 } 1925 1926 private class OutgoingEmergencyStateCallback extends TelephonyCallback implements 1927 TelephonyCallback.OutgoingEmergencyCallListener { 1928 @Override onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, int subscriptionId)1929 public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, 1930 int subscriptionId) { 1931 onEmergencyCall(); 1932 } 1933 } 1934 1935 private class CallStateCallback extends TelephonyCallback implements 1936 TelephonyCallback.CallStateListener { 1937 @Override onCallStateChanged(int state)1938 public void onCallStateChanged(int state) { 1939 if (state == TelephonyManager.CALL_STATE_IDLE) { 1940 onCallOver(); 1941 } 1942 } 1943 } 1944 onEmergencyCall()1945 private void onEmergencyCall() { 1946 synchronized (mEmergencyStateLock) { 1947 if (!mIsInEmergencyCall) { 1948 mIsInEmergencyCall = true; 1949 if (mSensorPrivacyServiceImpl 1950 .isIndividualSensorPrivacyEnabled(mCurrentUser, MICROPHONE)) { 1951 mSensorPrivacyServiceImpl.setIndividualSensorPrivacyUnchecked( 1952 mCurrentUser, OTHER, MICROPHONE, false); 1953 mMicUnmutedForEmergencyCall = true; 1954 } else { 1955 mMicUnmutedForEmergencyCall = false; 1956 } 1957 } 1958 } 1959 } 1960 onCallOver()1961 private void onCallOver() { 1962 synchronized (mEmergencyStateLock) { 1963 if (mIsInEmergencyCall) { 1964 mIsInEmergencyCall = false; 1965 if (mMicUnmutedForEmergencyCall) { 1966 mSensorPrivacyServiceImpl.setIndividualSensorPrivacyUnchecked( 1967 mCurrentUser, OTHER, MICROPHONE, true); 1968 mMicUnmutedForEmergencyCall = false; 1969 } 1970 } 1971 } 1972 } 1973 } 1974 getCurrentTimeMillis()1975 private static long getCurrentTimeMillis() { 1976 try { 1977 return SystemClock.currentNetworkTimeMillis(); 1978 } catch (Exception e) { 1979 return System.currentTimeMillis(); 1980 } 1981 } 1982 } 1983