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 android.hardware;
18 
19 import android.Manifest;
20 import android.annotation.FlaggedApi;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.annotation.SystemService;
26 import android.annotation.TestApi;
27 import android.annotation.UserIdInt;
28 import android.content.Context;
29 import android.os.Binder;
30 import android.os.IBinder;
31 import android.os.RemoteException;
32 import android.os.ServiceManager;
33 import android.os.UserHandle;
34 import android.service.SensorPrivacyIndividualEnabledSensorProto;
35 import android.service.SensorPrivacySensorProto;
36 import android.service.SensorPrivacyToggleSourceProto;
37 import android.util.ArrayMap;
38 import android.util.Log;
39 import android.util.Pair;
40 
41 import com.android.internal.annotations.GuardedBy;
42 import com.android.internal.camera.flags.Flags;
43 
44 import java.lang.annotation.Retention;
45 import java.lang.annotation.RetentionPolicy;
46 import java.util.List;
47 import java.util.Objects;
48 import java.util.concurrent.Executor;
49 
50 /**
51  * This class provides information about the microphone and camera toggles.
52  */
53 @SystemService(Context.SENSOR_PRIVACY_SERVICE)
54 public final class SensorPrivacyManager {
55 
56     private static final String LOG_TAG = SensorPrivacyManager.class.getSimpleName();
57 
58     /**
59      * Unique Id of this manager to identify to the service
60      * @hide
61      */
62     private IBinder token = new Binder();
63 
64     /**
65      * An extra containing a sensor
66      * @hide
67      */
68     public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName()
69             + ".extra.sensor";
70 
71     /**
72      * An extra containing the notification id that triggered the intent
73      * @hide
74      */
75     public static final String EXTRA_NOTIFICATION_ID = SensorPrivacyManager.class.getName()
76             + ".extra.notification_id";
77 
78     /**
79      * An extra indicating if all sensors are affected
80      * @hide
81      */
82     public static final String EXTRA_ALL_SENSORS = SensorPrivacyManager.class.getName()
83             + ".extra.all_sensors";
84 
85     /**
86      * An extra containing the sensor type
87      * @hide
88      */
89     public static final String EXTRA_TOGGLE_TYPE = SensorPrivacyManager.class.getName()
90             + ".extra.toggle_type";
91 
92     /**
93      * Sensor constants which are used in {@link SensorPrivacyManager}
94      */
95     public static class Sensors {
96 
Sensors()97         private Sensors() {}
98 
99         /**
100          * Constant for the microphone
101          */
102         public static final int MICROPHONE = SensorPrivacySensorProto.MICROPHONE;
103 
104         /**
105          * Constant for the camera
106          */
107         public static final int CAMERA = SensorPrivacySensorProto.CAMERA;
108 
109         /**
110          * Individual sensors not listed in {@link Sensors}
111          *
112          * @hide
113          */
114         @IntDef(value = {
115                 MICROPHONE,
116                 CAMERA
117         })
118         @Retention(RetentionPolicy.SOURCE)
119         public @interface Sensor {}
120     }
121 
122     /**
123      * Source through which Privacy Sensor was toggled.
124      * @hide
125      */
126     @TestApi
127     public static class Sources {
Sources()128         private Sources() {}
129 
130         /**
131          * Constant for the Quick Setting Tile.
132          */
133         public static final int QS_TILE = SensorPrivacyToggleSourceProto.QS_TILE;
134 
135         /**
136          * Constant for the Settings.
137          */
138         public static final int SETTINGS = SensorPrivacyToggleSourceProto.SETTINGS;
139 
140         /**
141          * Constant for Dialog.
142          */
143         public static final int DIALOG = SensorPrivacyToggleSourceProto.DIALOG;
144 
145         /**
146          * Constant for SHELL.
147          */
148         public static final int SHELL = SensorPrivacyToggleSourceProto.SHELL;
149 
150         /**
151          * Constant for OTHER.
152          */
153         public static final int OTHER = SensorPrivacyToggleSourceProto.OTHER;
154 
155         /**
156          * Constant for SAFETY_CENTER.
157          */
158         public static final int SAFETY_CENTER = SensorPrivacyToggleSourceProto.SAFETY_CENTER;
159 
160         /**
161          * Source for toggling sensors
162          *
163          * @hide
164          */
165         @IntDef(value = {
166                 QS_TILE,
167                 SETTINGS,
168                 DIALOG,
169                 SHELL,
170                 OTHER,
171                 SAFETY_CENTER
172         })
173         @Retention(RetentionPolicy.SOURCE)
174         public @interface Source {}
175 
176     }
177 
178 
179     /**
180      * Constant for software toggle.
181      */
182     public static final int TOGGLE_TYPE_SOFTWARE =
183             SensorPrivacyIndividualEnabledSensorProto.SOFTWARE;
184 
185     /**
186      * Constant for hardware toggle.
187      */
188     public static final int TOGGLE_TYPE_HARDWARE =
189             SensorPrivacyIndividualEnabledSensorProto.HARDWARE;
190 
191     /**
192      * Types of toggles which can exist for sensor privacy
193      *
194      * @hide
195      */
196     @IntDef(value = {
197             TOGGLE_TYPE_SOFTWARE,
198             TOGGLE_TYPE_HARDWARE
199     })
200     @Retention(RetentionPolicy.SOURCE)
201     public @interface ToggleType {}
202 
203     /**
204      * Types of state which can exist for the sensor privacy toggle
205      * @hide
206      */
207     @SystemApi
208     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
209     public static class StateTypes {
StateTypes()210         private StateTypes() {}
211 
212         /**
213          * Constant indicating privacy is enabled.
214          */
215         public static final int ENABLED = SensorPrivacyIndividualEnabledSensorProto.ENABLED;
216 
217         /**
218          * Constant indicating privacy is disabled.
219          */
220         public static final int DISABLED = SensorPrivacyIndividualEnabledSensorProto.DISABLED;
221 
222          /**
223          * Constant indicating privacy is enabled except for the automotive driver assistance apps
224          * which are required by car manufacturer for driving.
225          */
226         public static final int ENABLED_EXCEPT_ALLOWLISTED_APPS =
227                 SensorPrivacyIndividualEnabledSensorProto.ENABLED_EXCEPT_ALLOWLISTED_APPS;
228 
229         /**
230          * Types of state which can exist for a sensor privacy toggle
231          *
232          * @hide
233          */
234         @IntDef(value = {
235                 ENABLED,
236                 DISABLED,
237                 ENABLED_EXCEPT_ALLOWLISTED_APPS
238         })
239         @Retention(RetentionPolicy.SOURCE)
240         public @interface StateType {}
241 
242     }
243 
244     /**
245      * A class implementing this interface can register with the {@link
246      * android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
247      * state changes.
248      *
249      * @hide
250      */
251     @SystemApi
252     public interface OnSensorPrivacyChangedListener {
253         /**
254          * Callback invoked when the sensor privacy state changes.
255          *
256          * @param params Parameters describing the new state
257          */
onSensorPrivacyChanged(@onNull SensorPrivacyChangedParams params)258         default void onSensorPrivacyChanged(@NonNull SensorPrivacyChangedParams params) {
259             onSensorPrivacyChanged(params.mSensor, params.mEnabled);
260         }
261 
262         /**
263          * Callback invoked when the sensor privacy state changes.
264          *
265          * @param sensor the sensor whose state is changing
266          * @param enabled true if sensor privacy is enabled, false otherwise.
267          *
268          * @deprecated Please use
269          * {@link #onSensorPrivacyChanged(SensorPrivacyChangedParams)}
270          */
271         @Deprecated
onSensorPrivacyChanged(int sensor, boolean enabled)272         void onSensorPrivacyChanged(int sensor, boolean enabled);
273 
274         /**
275          * A class containing information about what the sensor privacy state has changed to.
276          */
277         class SensorPrivacyChangedParams {
278 
279             private int mToggleType;
280             private int mSensor;
281             private boolean mEnabled;
282             private int mState;
283 
284             @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
SensorPrivacyChangedParams(int toggleType, int sensor, int state)285             private SensorPrivacyChangedParams(int toggleType, int sensor, int state) {
286                 mToggleType = toggleType;
287                 mSensor = sensor;
288                 mState = state;
289                 if (state == StateTypes.ENABLED) {
290                     mEnabled = true;
291                 } else {
292                     mEnabled = false;
293                 }
294             }
295 
SensorPrivacyChangedParams(int toggleType, int sensor, boolean enabled)296             private SensorPrivacyChangedParams(int toggleType, int sensor, boolean enabled) {
297                 mToggleType = toggleType;
298                 mSensor = sensor;
299                 mEnabled = enabled;
300             }
301 
getToggleType()302             public @ToggleType int getToggleType() {
303                 return mToggleType;
304             }
305 
getSensor()306             public @Sensors.Sensor int getSensor() {
307                 return mSensor;
308             }
309 
isEnabled()310             public boolean isEnabled() {
311                 return mEnabled;
312             }
313 
314             @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
getState()315             public @StateTypes.StateType int getState() {
316                 return mState;
317             }
318 
319         }
320     }
321 
322     private static final Object sInstanceLock = new Object();
323 
324     private final Object mLock = new Object();
325 
326     @GuardedBy("sInstanceLock")
327     private static SensorPrivacyManager sInstance;
328 
329     @NonNull
330     private final Context mContext;
331 
332     @NonNull
333     private final ISensorPrivacyManager mService;
334 
335     @GuardedBy("mLock")
336     private final ArrayMap<Pair<Integer, Integer>, Boolean> mToggleSupportCache = new ArrayMap<>();
337 
338     @NonNull
339     private final ArrayMap<OnAllSensorPrivacyChangedListener, ISensorPrivacyListener> mListeners;
340 
341     /** Registered listeners */
342     @GuardedBy("mLock")
343     @NonNull
344     private final ArrayMap<OnSensorPrivacyChangedListener, Executor> mToggleListeners =
345             new ArrayMap<>();
346 
347     /** Listeners registered using the deprecated APIs and which
348      * OnSensorPrivacyChangedListener they're using. */
349     @GuardedBy("mLock")
350     @NonNull
351     private final ArrayMap<Pair<Integer, OnSensorPrivacyChangedListener>,
352             OnSensorPrivacyChangedListener> mLegacyToggleListeners = new ArrayMap<>();
353 
354     /** The singleton ISensorPrivacyListener for IPC which will be used to dispatch to local
355      * listeners */
356     @NonNull
357     private final ISensorPrivacyListener mIToggleListener = new ISensorPrivacyListener.Stub() {
358         @Override
359         public void onSensorPrivacyChanged(int toggleType, int sensor, boolean enabled) {
360             synchronized (mLock) {
361                 for (int i = 0; i < mToggleListeners.size(); i++) {
362                     OnSensorPrivacyChangedListener listener = mToggleListeners.keyAt(i);
363                     if (Flags.cameraPrivacyAllowlist()) {
364                         int state = enabled ?  StateTypes.ENABLED : StateTypes.DISABLED;
365                         mToggleListeners.valueAt(i).execute(() -> listener
366                                 .onSensorPrivacyChanged(new OnSensorPrivacyChangedListener
367                                         .SensorPrivacyChangedParams(toggleType, sensor, state)));
368                     } else {
369                         mToggleListeners.valueAt(i).execute(() -> listener
370                                 .onSensorPrivacyChanged(new OnSensorPrivacyChangedListener
371                                         .SensorPrivacyChangedParams(toggleType, sensor, enabled)));
372                     }
373                 }
374             }
375         }
376 
377         @Override
378         @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
379         public void onSensorPrivacyStateChanged(@ToggleType int toggleType,
380                 @Sensors.Sensor int sensor, @StateTypes.StateType int state) {
381             synchronized (mLock) {
382                 for (int i = 0; i < mToggleListeners.size(); i++) {
383                     OnSensorPrivacyChangedListener listener = mToggleListeners.keyAt(i);
384                     mToggleListeners.valueAt(i).execute(() -> listener
385                             .onSensorPrivacyChanged(new OnSensorPrivacyChangedListener
386                                     .SensorPrivacyChangedParams(toggleType, sensor, state)));
387                 }
388             }
389         }
390 
391     };
392 
393     /** Whether the singleton ISensorPrivacyListener has been registered */
394     @GuardedBy("mLock")
395     @NonNull
396     private boolean mToggleListenerRegistered = false;
397 
398     private Boolean mRequiresAuthentication = null;
399 
400     /**
401      * Private constructor to ensure only a single instance is created.
402      */
SensorPrivacyManager(Context context, ISensorPrivacyManager service)403     private SensorPrivacyManager(Context context, ISensorPrivacyManager service) {
404         mContext = context;
405         mService = service;
406         mListeners = new ArrayMap<>();
407     }
408 
409     /**
410      * Returns the single instance of the SensorPrivacyManager.
411      *
412      * @hide
413      */
getInstance(Context context)414     public static SensorPrivacyManager getInstance(Context context) {
415         synchronized (sInstanceLock) {
416             if (sInstance == null) {
417                 try {
418                     IBinder b = ServiceManager.getServiceOrThrow(Context.SENSOR_PRIVACY_SERVICE);
419                     ISensorPrivacyManager service = ISensorPrivacyManager.Stub.asInterface(b);
420                     sInstance = new SensorPrivacyManager(context, service);
421                 } catch (ServiceManager.ServiceNotFoundException e) {
422                     throw new IllegalStateException(e);
423                 }
424             }
425             return sInstance;
426         }
427     }
428 
429     /**
430      * Returns the single instance of the SensorPrivacyManager.
431      *
432      * @hide
433      */
getInstance(Context context, ISensorPrivacyManager service)434     public static SensorPrivacyManager getInstance(Context context, ISensorPrivacyManager service) {
435         synchronized (sInstanceLock) {
436             sInstance = new SensorPrivacyManager(context, service);
437             return sInstance;
438         }
439     }
440 
441     /**
442      * Checks if the given toggle is supported on this device
443      * @param sensor The sensor to check
444      * @return whether the toggle for the sensor is supported on this device.
445      */
supportsSensorToggle(@ensors.Sensor int sensor)446     public boolean supportsSensorToggle(@Sensors.Sensor int sensor) {
447         return supportsSensorToggle(TOGGLE_TYPE_SOFTWARE, sensor);
448     }
449 
450     /**
451      * Checks if the given toggle is supported on this device
452      * @param sensor The sensor to check
453      * @return whether the toggle for the sensor is supported on this device.
454      *
455      */
supportsSensorToggle(@oggleType int toggleType, @Sensors.Sensor int sensor)456     public boolean supportsSensorToggle(@ToggleType int toggleType, @Sensors.Sensor int sensor) {
457         try {
458             Pair key = new Pair(toggleType, sensor);
459             synchronized (mLock) {
460                 Boolean val = mToggleSupportCache.get(key);
461                 if (val == null) {
462                     val = mService.supportsSensorToggle(toggleType, sensor);
463                     mToggleSupportCache.put(key, val);
464                 }
465                 return val;
466             }
467         } catch (RemoteException e) {
468             throw e.rethrowFromSystemServer();
469         }
470     }
471 
472     /**
473      *
474      * Registers a new listener to receive notification when the state of sensor privacy
475      * changes.
476      *
477      * @param sensor the sensor to listen to changes to
478      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
479      *                       privacy changes.
480      *
481      * @hide
482      */
483     @SystemApi
484     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
addSensorPrivacyListener(@ensors.Sensor int sensor, @NonNull OnSensorPrivacyChangedListener listener)485     public void addSensorPrivacyListener(@Sensors.Sensor int sensor,
486             @NonNull OnSensorPrivacyChangedListener listener) {
487         addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
488     }
489 
490     /**
491      *
492      * Registers a new listener to receive notification when the state of sensor privacy
493      * changes.
494      *
495      * @param sensor the sensor to listen to changes to
496      * @param userId the user's id
497      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
498      *                 privacy changes.
499      *
500      * @hide
501      */
502     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
addSensorPrivacyListener(@ensors.Sensor int sensor, int userId, @NonNull OnSensorPrivacyChangedListener listener)503     public void addSensorPrivacyListener(@Sensors.Sensor int sensor, int userId,
504             @NonNull OnSensorPrivacyChangedListener listener) {
505         addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
506     }
507 
508     /**
509      *
510      * Registers a new listener to receive notification when the state of sensor privacy
511      * changes.
512      *
513      * @param sensor the sensor to listen to changes to
514      * @param executor the executor to dispatch the callback on
515      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
516      *                       privacy changes.
517      *
518      * @hide
519      */
520     @SystemApi
521     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
addSensorPrivacyListener(@ensors.Sensor int sensor, @NonNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener)522     public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
523             @NonNull OnSensorPrivacyChangedListener listener) {
524         Pair<Integer, OnSensorPrivacyChangedListener> pair = new Pair(sensor, listener);
525         OnSensorPrivacyChangedListener toggleListener = new OnSensorPrivacyChangedListener() {
526             @Override
527             public void onSensorPrivacyChanged(SensorPrivacyChangedParams params) {
528                 if (params.getSensor() == sensor) {
529                     listener.onSensorPrivacyChanged(params);
530                 }
531             }
532             @Override
533             public void onSensorPrivacyChanged(int sensor, boolean enabled) {
534             }
535         };
536 
537         synchronized (mLock) {
538             mLegacyToggleListeners.put(pair, toggleListener);
539             addSensorPrivacyListenerLocked(executor, toggleListener);
540         }
541     }
542 
543     /**
544      *
545      * Registers a new listener to receive notification when the state of sensor privacy
546      * changes.
547      *
548      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of
549      *                 sensor privacy changes.
550      *
551      * @hide
552      */
553     @SystemApi
554     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
addSensorPrivacyListener(@onNull OnSensorPrivacyChangedListener listener)555     public void addSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) {
556         addSensorPrivacyListener(mContext.getMainExecutor(), listener);
557     }
558 
559     /**
560      *
561      * Registers a new listener to receive notification when the state of sensor privacy
562      * changes.
563      *
564      * @param executor the executor to dispatch the callback on
565      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of
566      *                 sensor privacy changes.
567      *
568      * @hide
569      */
570     @SystemApi
571     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
addSensorPrivacyListener(@onNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener)572     public void addSensorPrivacyListener(@NonNull Executor executor,
573             @NonNull OnSensorPrivacyChangedListener listener) {
574         synchronized (mLock) {
575             addSensorPrivacyListenerLocked(executor, listener);
576         }
577     }
578 
579     @GuardedBy("mLock")
addSensorPrivacyListenerLocked(@onNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener)580     private void addSensorPrivacyListenerLocked(@NonNull Executor executor,
581             @NonNull OnSensorPrivacyChangedListener listener) {
582         if (!mToggleListenerRegistered) {
583             try {
584                 mService.addToggleSensorPrivacyListener(mIToggleListener);
585                 mToggleListenerRegistered = true;
586             } catch (RemoteException e) {
587                 e.rethrowFromSystemServer();
588             }
589         }
590         if (mToggleListeners.containsKey(listener)) {
591             throw new IllegalArgumentException("listener is already registered");
592         }
593         mToggleListeners.put(listener, executor);
594     }
595 
596     /**
597      * Unregisters the specified listener from receiving notifications when the state of any sensor
598      * privacy changes.
599      *
600      * @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when
601      *                 sensor privacy changes.
602      *
603      * @hide
604      */
605     @SystemApi
606     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
removeSensorPrivacyListener(@ensors.Sensor int sensor, @NonNull OnSensorPrivacyChangedListener listener)607     public void removeSensorPrivacyListener(@Sensors.Sensor int sensor,
608             @NonNull OnSensorPrivacyChangedListener listener) {
609         Pair<Integer, OnSensorPrivacyChangedListener> pair = new Pair(sensor, listener);
610         synchronized (mLock) {
611             OnSensorPrivacyChangedListener onToggleSensorPrivacyChangedListener =
612                     mLegacyToggleListeners.remove(pair);
613             if (onToggleSensorPrivacyChangedListener != null) {
614                 removeSensorPrivacyListenerLocked(onToggleSensorPrivacyChangedListener);
615             }
616         }
617     }
618 
619     /**
620      * Unregisters the specified listener from receiving notifications when the state of any sensor
621      * privacy changes.
622      *
623      * @param listener the {@link OnSensorPrivacyChangedListener} to be unregistered from
624      *                 notifications when sensor privacy changes.
625      *
626      * @hide
627      */
628     @SystemApi
629     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
removeSensorPrivacyListener( @onNull OnSensorPrivacyChangedListener listener)630     public void removeSensorPrivacyListener(
631             @NonNull OnSensorPrivacyChangedListener listener) {
632         synchronized (mLock) {
633             removeSensorPrivacyListenerLocked(listener);
634         }
635     }
636 
637     @GuardedBy("mLock")
removeSensorPrivacyListenerLocked( @onNull OnSensorPrivacyChangedListener listener)638     private void removeSensorPrivacyListenerLocked(
639             @NonNull OnSensorPrivacyChangedListener listener) {
640         mToggleListeners.remove(listener);
641         if (mToggleListeners.size() == 0) {
642             try {
643                 mService.removeToggleSensorPrivacyListener(mIToggleListener);
644                 mToggleListenerRegistered = false;
645             } catch (RemoteException e) {
646                 e.rethrowFromSystemServer();
647             }
648         }
649     }
650 
651     /**
652      * Returns whether sensor privacy is currently enabled by software control for a specific
653      * sensor.
654      *
655      * @return true if sensor privacy is currently enabled, false otherwise.
656      *
657      * @deprecated Prefer to use {@link #isSensorPrivacyEnabled(int, int)}
658      *
659      * @hide
660      */
661     @Deprecated
662     @SystemApi
663     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
isSensorPrivacyEnabled(@ensors.Sensor int sensor)664     public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
665         return isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor);
666     }
667 
668     /**
669      * Returns whether sensor privacy is currently enabled for a specific sensor.
670      *
671      * @return true if sensor privacy is currently enabled, false otherwise.
672      *
673      * @hide
674      */
675     @SystemApi
676     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
isSensorPrivacyEnabled(@oggleType int toggleType, @Sensors.Sensor int sensor)677     public boolean isSensorPrivacyEnabled(@ToggleType int toggleType,
678             @Sensors.Sensor int sensor) {
679         try {
680             return mService.isToggleSensorPrivacyEnabled(toggleType, sensor);
681         } catch (RemoteException e) {
682             throw e.rethrowFromSystemServer();
683         }
684     }
685 
686     /**
687      * Returns whether sensor privacy is currently enabled for a specific sensor.
688      * Combines the state of the SW + HW toggles and returns true if either the
689      * SOFTWARE or the HARDWARE toggles are enabled.
690      *
691      * @return true if sensor privacy is currently enabled, false otherwise.
692      *
693      * @hide
694      */
695     @SystemApi
696     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
areAnySensorPrivacyTogglesEnabled(@ensors.Sensor int sensor)697     public boolean areAnySensorPrivacyTogglesEnabled(@Sensors.Sensor int sensor) {
698         try {
699             return mService.isCombinedToggleSensorPrivacyEnabled(sensor);
700         } catch (RemoteException e) {
701             throw e.rethrowFromSystemServer();
702         }
703     }
704 
705     /**
706      * Returns sensor privacy state for a specific sensor.
707      *
708      * @param toggleType The type of toggle to use
709      * @param sensor The sensor to check
710      * @return int sensor privacy state.
711      *
712      * @hide
713      */
714     @SystemApi
715     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
716     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
getSensorPrivacyState(@oggleType int toggleType, @Sensors.Sensor int sensor)717     public @StateTypes.StateType int getSensorPrivacyState(@ToggleType int toggleType,
718             @Sensors.Sensor int sensor) {
719         try {
720             return mService.getToggleSensorPrivacyState(toggleType, sensor);
721         } catch (RemoteException e) {
722             throw e.rethrowFromSystemServer();
723         }
724     }
725 
726    /**
727      * Returns if camera privacy is enabled for a specific package.
728      *
729      * @param packageName The package to check
730      * @return boolean camera privacy state.
731      *
732      * @hide
733      */
734     @SystemApi
735     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
736     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
isCameraPrivacyEnabled(@onNull String packageName)737     public boolean isCameraPrivacyEnabled(@NonNull String packageName) {
738         try {
739             return mService.isCameraPrivacyEnabled(packageName);
740         } catch (RemoteException e) {
741             throw e.rethrowFromSystemServer();
742         }
743     }
744 
745     /**
746      * Returns camera privacy allowlist.
747      *
748      * @return List of automotive driver assistance packages for
749      * privacy allowlisting.
750      *
751      * @hide
752      */
753     @SystemApi
754     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
755     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
getCameraPrivacyAllowlist()756     public @NonNull List<String>  getCameraPrivacyAllowlist() {
757         synchronized (mLock) {
758             try {
759                 return mService.getCameraPrivacyAllowlist();
760             } catch (RemoteException e) {
761                 throw e.rethrowFromSystemServer();
762             }
763         }
764     }
765 
766     /**
767      * Sets camera privacy allowlist.
768      *
769      * @param allowlist List of automotive driver assistance packages for
770      * privacy allowlisting.
771      *
772      * @hide
773      */
774     @TestApi
775     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
776     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
setCameraPrivacyAllowlist(@onNull List<String> allowlist)777     public void setCameraPrivacyAllowlist(@NonNull List<String> allowlist) {
778         synchronized (mLock) {
779             try {
780                 mService.setCameraPrivacyAllowlist(allowlist);
781             } catch (RemoteException e) {
782                 throw e.rethrowFromSystemServer();
783             }
784         }
785     }
786 
787     /**
788      * Sets sensor privacy to the specified state for an individual sensor.
789      *
790      * @param sensor the sensor which to change the state for
791      * @param enable the state to which sensor privacy should be set.
792      *
793      * @hide
794      */
795     @SystemApi
796     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
setSensorPrivacy(@ensors.Sensor int sensor, boolean enable)797     public void setSensorPrivacy(@Sensors.Sensor int sensor,
798             boolean enable) {
799         setSensorPrivacy(resolveSourceFromCurrentContext(), sensor, enable,
800                 UserHandle.USER_CURRENT);
801     }
802 
resolveSourceFromCurrentContext()803     private @Sources.Source int resolveSourceFromCurrentContext() {
804         String packageName = mContext.getOpPackageName();
805         if (Objects.equals(packageName,
806                 mContext.getPackageManager().getPermissionControllerPackageName())) {
807             return Sources.SAFETY_CENTER;
808         }
809         return Sources.OTHER;
810     }
811 
812     /**
813      * Sets sensor privacy to the specified state for an individual sensor.
814      *
815      * @param sensor the sensor which to change the state for
816      * @param state the state to which sensor privacy should be set.
817      *
818      * @hide
819      */
820     @SystemApi
821     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
822     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
setSensorPrivacyState(@ensors.Sensor int sensor, @StateTypes.StateType int state)823     public void setSensorPrivacyState(@Sensors.Sensor int sensor,
824             @StateTypes.StateType int state) {
825         setSensorPrivacyState(resolveSourceFromCurrentContext(), sensor, state);
826     }
827 
828     /**
829      * Sets sensor privacy to the specified state for an individual sensor.
830      *
831      * @param sensor the sensor which to change the state for
832      * @param enable the state to which sensor privacy should be set.
833      *
834      * @hide
835      */
836     @TestApi
837     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
setSensorPrivacy(@ources.Source int source, @Sensors.Sensor int sensor, boolean enable)838     public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
839             boolean enable) {
840         setSensorPrivacy(source, sensor, enable, UserHandle.USER_CURRENT);
841     }
842 
843     /**
844      * Sets sensor privacy to the specified state for an individual sensor.
845      *
846      * @param sensor the sensor which to change the state for
847      * @param enable the state to which sensor privacy should be set.
848      * @param userId the user's id
849      *
850      * @hide
851      */
852     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
setSensorPrivacy(@ources.Source int source, @Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId)853     public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
854             boolean enable, @UserIdInt int userId) {
855         try {
856             mService.setToggleSensorPrivacy(userId, source, sensor, enable);
857         } catch (RemoteException e) {
858             throw e.rethrowFromSystemServer();
859         }
860     }
861 
862     /**
863      * Sets sensor privacy to the specified state for an individual sensor.
864      *
865      * @param source the source using which the sensor is toggled
866      * @param sensor the sensor which to change the state for
867      * @param state the state to which sensor privacy should be set.
868      *
869      * @hide
870      */
871     @TestApi
872     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
873     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
setSensorPrivacyState(@ources.Source int source, @Sensors.Sensor int sensor, @StateTypes.StateType int state)874     public void setSensorPrivacyState(@Sources.Source int source, @Sensors.Sensor int sensor,
875             @StateTypes.StateType int state) {
876         try {
877             mService.setToggleSensorPrivacyState(mContext.getUserId(), source, sensor, state);
878         } catch (RemoteException e) {
879             throw e.rethrowFromSystemServer();
880         }
881 
882     }
883 
884     /**
885      * Sets sensor privacy to the specified state for an individual sensor for the profile group of
886      * context's user.
887      *
888      * @param source the source using which the sensor is toggled.
889      * @param sensor the sensor which to change the state for
890      * @param enable the state to which sensor privacy should be set.
891      *
892      * @hide
893      */
894     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
setSensorPrivacyForProfileGroup(@ources.Source int source, @Sensors.Sensor int sensor, boolean enable)895     public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
896             @Sensors.Sensor int sensor, boolean enable) {
897         setSensorPrivacyForProfileGroup(source , sensor, enable, UserHandle.USER_CURRENT);
898     }
899 
900     /**
901      * Sets sensor privacy to the specified state for an individual sensor for the profile group of
902      * context's user.
903      *
904      * @param source the source using which the sensor is toggled.
905      * @param sensor the sensor which to change the state for
906      * @param enable the state to which sensor privacy should be set.
907      * @param userId the user's id
908      *
909      * @hide
910      */
911     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
setSensorPrivacyForProfileGroup(@ources.Source int source, @Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId)912     public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
913             @Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId) {
914         try {
915             mService.setToggleSensorPrivacyForProfileGroup(userId, source, sensor, enable);
916         } catch (RemoteException e) {
917             throw e.rethrowFromSystemServer();
918         }
919     }
920 
921     /**
922      * Sets sensor privacy to the specified state for an individual sensor for the profile group of
923      * context's user.
924      *
925      * @param source the source using which the sensor is toggled.
926      * @param sensor the sensor which to change the state for
927      * @param state the state to which sensor privacy should be set.
928      *
929      * @hide
930      */
931     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
932     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
setSensorPrivacyStateForProfileGroup(@ources.Source int source, @Sensors.Sensor int sensor, @StateTypes.StateType int state)933     public void setSensorPrivacyStateForProfileGroup(@Sources.Source int source,
934             @Sensors.Sensor int sensor, @StateTypes.StateType int state) {
935         try {
936             mService.setToggleSensorPrivacyStateForProfileGroup(mContext.getUserId(), source,
937                     sensor, state);
938         } catch (RemoteException e) {
939             throw e.rethrowFromSystemServer();
940         }
941     }
942 
943     /**
944      * Don't show dialogs to turn off sensor privacy for this package.
945      *
946      * @param suppress Whether to suppress or re-enable.
947      *
948      * @hide
949      */
950     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
suppressSensorPrivacyReminders(int sensor, boolean suppress)951     public void suppressSensorPrivacyReminders(int sensor,
952             boolean suppress) {
953         suppressSensorPrivacyReminders(sensor, suppress, UserHandle.USER_CURRENT);
954     }
955 
956     /**
957      * Don't show dialogs to turn off sensor privacy for this package.
958      *
959      * @param suppress Whether to suppress or re-enable.
960      * @param userId the user's id
961      *
962      * @hide
963      */
964     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
suppressSensorPrivacyReminders(int sensor, boolean suppress, @UserIdInt int userId)965     public void suppressSensorPrivacyReminders(int sensor,
966             boolean suppress, @UserIdInt int userId) {
967         try {
968             mService.suppressToggleSensorPrivacyReminders(userId, sensor,
969                     token, suppress);
970         } catch (RemoteException e) {
971             throw e.rethrowFromSystemServer();
972         }
973     }
974 
975     /**
976      * @return whether the device is required to be unlocked to change software state.
977      *
978      * @hide
979      */
980     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
requiresAuthentication()981     public boolean requiresAuthentication() {
982         if (mRequiresAuthentication == null) {
983             try {
984                 mRequiresAuthentication = mService.requiresAuthentication();
985             } catch (RemoteException e) {
986                 throw e.rethrowFromSystemServer();
987             }
988         }
989         return mRequiresAuthentication;
990     }
991 
992     /**
993      * If sensor privacy for the provided sensor is enabled then this call will show the user the
994      * dialog which is shown when an application attempts to use that sensor. If privacy isn't
995      * enabled then this does nothing.
996      *
997      * This call can only be made by the system uid.
998      *
999      * @throws SecurityException when called by someone other than system uid.
1000      *
1001      * @hide
1002      */
showSensorUseDialog(int sensor)1003     public void showSensorUseDialog(int sensor) {
1004         try {
1005             mService.showSensorUseDialog(sensor);
1006         } catch (RemoteException e) {
1007             Log.e(LOG_TAG, "Received exception while trying to show sensor use dialog", e);
1008         }
1009     }
1010 
1011     /**
1012      * A class implementing this interface can register with the {@link
1013      * android.hardware.SensorPrivacyManager} to receive notification when the all-sensor privacy
1014      * state changes.
1015      *
1016      * @hide
1017      */
1018     public interface OnAllSensorPrivacyChangedListener {
1019         /**
1020          * Callback invoked when the sensor privacy state changes.
1021          *
1022          * @param enabled true if sensor privacy is enabled, false otherwise.
1023          */
onAllSensorPrivacyChanged(boolean enabled)1024         void onAllSensorPrivacyChanged(boolean enabled);
1025     }
1026 
1027     /**
1028      * Sets all-sensor privacy to the specified state.
1029      *
1030      * @param enable the state to which sensor privacy should be set.
1031      *
1032      * @hide
1033      */
1034     @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
setAllSensorPrivacy(boolean enable)1035     public void setAllSensorPrivacy(boolean enable) {
1036         try {
1037             mService.setSensorPrivacy(enable);
1038         } catch (RemoteException e) {
1039             throw e.rethrowFromSystemServer();
1040         }
1041     }
1042 
1043     /**
1044      * Registers a new listener to receive notification when the state of all-sensor privacy
1045      * changes.
1046      *
1047      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of
1048      *                 all-sensor privacy changes.
1049      *
1050      * @hide
1051      */
1052     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
addAllSensorPrivacyListener( @onNull final OnAllSensorPrivacyChangedListener listener)1053     public void addAllSensorPrivacyListener(
1054             @NonNull final OnAllSensorPrivacyChangedListener listener) {
1055         synchronized (mListeners) {
1056             ISensorPrivacyListener iListener = mListeners.get(listener);
1057             if (iListener == null) {
1058                 iListener = new ISensorPrivacyListener.Stub() {
1059                     @Override
1060                     public void onSensorPrivacyChanged(int toggleType, int sensor,
1061                             boolean enabled) {
1062                         listener.onAllSensorPrivacyChanged(enabled);
1063                     }
1064 
1065                     @Override
1066                     @FlaggedApi(Flags.FLAG_CAMERA_PRIVACY_ALLOWLIST)
1067                     public void onSensorPrivacyStateChanged(int toggleType, int sensor,
1068                             int state) {
1069                     }
1070                 };
1071                 mListeners.put(listener, iListener);
1072             }
1073 
1074             try {
1075                 mService.addSensorPrivacyListener(iListener);
1076             } catch (RemoteException e) {
1077                 throw e.rethrowFromSystemServer();
1078             }
1079         }
1080     }
1081 
1082     /**
1083      * Unregisters the specified listener from receiving notifications when the state of all-sensor
1084      * privacy changes.
1085      *
1086      * @param listener the OnAllSensorPrivacyChangedListener to be unregistered from notifications
1087      *                 when all-sensor privacy changes.
1088      *
1089      * @hide
1090      */
1091     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
removeAllSensorPrivacyListener( @onNull OnAllSensorPrivacyChangedListener listener)1092     public void removeAllSensorPrivacyListener(
1093             @NonNull OnAllSensorPrivacyChangedListener listener) {
1094         synchronized (mListeners) {
1095             ISensorPrivacyListener iListener = mListeners.get(listener);
1096             if (iListener != null) {
1097                 mListeners.remove(iListener);
1098                 try {
1099                     mService.removeSensorPrivacyListener(iListener);
1100                 } catch (RemoteException e) {
1101                     throw e.rethrowFromSystemServer();
1102                 }
1103             }
1104         }
1105     }
1106 
1107     /**
1108      * Returns whether all-sensor privacy is currently enabled.
1109      *
1110      * @return true if all-sensor privacy is currently enabled, false otherwise.
1111      *
1112      * @hide
1113      */
1114     @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
isAllSensorPrivacyEnabled()1115     public boolean isAllSensorPrivacyEnabled() {
1116         try {
1117             return mService.isSensorPrivacyEnabled();
1118         } catch (RemoteException e) {
1119             throw e.rethrowFromSystemServer();
1120         }
1121     }
1122 
1123 }
1124