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