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