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