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