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.annotation.NonNull;
20 import android.annotation.RequiresPermission;
21 import android.annotation.SystemService;
22 import android.content.Context;
23 import android.os.IBinder;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.util.ArrayMap;
27 
28 import com.android.internal.annotations.GuardedBy;
29 
30 /**
31  * This class provides access to the sensor privacy services; sensor privacy allows the
32  * user to disable access to all sensors on the device. This class provides methods to query the
33  * current state of sensor privacy as well as to register / unregister for notification when
34  * the sensor privacy state changes.
35  *
36  * @hide
37  */
38 @SystemService(Context.SENSOR_PRIVACY_SERVICE)
39 public final class SensorPrivacyManager {
40 
41     /**
42      * A class implementing this interface can register with the {@link
43      * android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
44      * state changes.
45      */
46     public interface OnSensorPrivacyChangedListener {
47         /**
48          * Callback invoked when the sensor privacy state changes.
49          *
50          * @param enabled true if sensor privacy is enabled, false otherwise.
51          */
onSensorPrivacyChanged(boolean enabled)52         void onSensorPrivacyChanged(boolean enabled);
53     }
54 
55     private static final Object sInstanceLock = new Object();
56 
57     @GuardedBy("sInstanceLock")
58     private static SensorPrivacyManager sInstance;
59 
60     @NonNull
61     private final Context mContext;
62 
63     @NonNull
64     private final ISensorPrivacyManager mService;
65 
66     @NonNull
67     private final ArrayMap<OnSensorPrivacyChangedListener, ISensorPrivacyListener> mListeners;
68 
69     /**
70      * Private constructor to ensure only a single instance is created.
71      */
SensorPrivacyManager(Context context, ISensorPrivacyManager service)72     private SensorPrivacyManager(Context context, ISensorPrivacyManager service) {
73         mContext = context;
74         mService = service;
75         mListeners = new ArrayMap<>();
76     }
77 
78     /**
79      * Returns the single instance of the SensorPrivacyManager.
80      */
getInstance(Context context)81     public static SensorPrivacyManager getInstance(Context context) {
82         synchronized (sInstanceLock) {
83             if (sInstance == null) {
84                 try {
85                     IBinder b = ServiceManager.getServiceOrThrow(Context.SENSOR_PRIVACY_SERVICE);
86                     ISensorPrivacyManager service = ISensorPrivacyManager.Stub.asInterface(b);
87                     sInstance = new SensorPrivacyManager(context, service);
88                 } catch (ServiceManager.ServiceNotFoundException e) {
89                     throw new IllegalStateException(e);
90                 }
91             }
92             return sInstance;
93         }
94     }
95 
96     /**
97      * Sets sensor privacy to the specified state.
98      *
99      * @param enable the state to which sensor privacy should be set.
100      */
101     @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
setSensorPrivacy(boolean enable)102     public void setSensorPrivacy(boolean enable) {
103         try {
104             mService.setSensorPrivacy(enable);
105         } catch (RemoteException e) {
106             throw e.rethrowFromSystemServer();
107         }
108     }
109 
110     /**
111      * Registers a new listener to receive notification when the state of sensor privacy
112      * changes.
113      *
114      * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
115      *                 privacy changes.
116      */
addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener)117     public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) {
118         synchronized (mListeners) {
119             ISensorPrivacyListener iListener = mListeners.get(listener);
120             if (iListener == null) {
121                 iListener = new ISensorPrivacyListener.Stub() {
122                     @Override
123                     public void onSensorPrivacyChanged(boolean enabled) {
124                         listener.onSensorPrivacyChanged(enabled);
125                     }
126                 };
127                 mListeners.put(listener, iListener);
128             }
129 
130             try {
131                 mService.addSensorPrivacyListener(iListener);
132             } catch (RemoteException e) {
133                 throw e.rethrowFromSystemServer();
134             }
135         }
136     }
137 
138     /**
139      * Unregisters the specified listener from receiving notifications when the state of sensor
140      * privacy changes.
141      *
142      * @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when
143      *                 sensor privacy changes.
144      */
removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener)145     public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) {
146         synchronized (mListeners) {
147             ISensorPrivacyListener iListener = mListeners.get(listener);
148             if (iListener != null) {
149                 mListeners.remove(iListener);
150                 try {
151                     mService.removeSensorPrivacyListener(iListener);
152                 } catch (RemoteException e) {
153                     throw e.rethrowFromSystemServer();
154                 }
155             }
156         }
157     }
158 
159     /**
160      * Returns whether sensor privacy is currently enabled.
161      *
162      * @return true if sensor privacy is currently enabled, false otherwise.
163      */
isSensorPrivacyEnabled()164     public boolean isSensorPrivacyEnabled() {
165         try {
166             return mService.isSensorPrivacyEnabled();
167         } catch (RemoteException e) {
168             throw e.rethrowFromSystemServer();
169         }
170     }
171 }
172