Add system APIs to allow checking of hardware mic/cam toggles

Allow priv apps to query the state of the software and hardware privacy toggles.

Test: atest CtsSensorPrivacyTestCases
Bug: 191745272
Change-Id: I87c31bcdd25daafe589dff8f21f227f2c2356ab1
This commit is contained in:
Valentin Iftime
2022-02-14 21:46:01 +01:00
parent 28dac743f0
commit bea2fd3ae0
6 changed files with 233 additions and 203 deletions

View File

@@ -17117,6 +17117,9 @@ package android.hardware {
public final class SensorPrivacyManager {
method public boolean supportsSensorToggle(int);
method public boolean supportsSensorToggle(int, int);
field public static final int TOGGLE_TYPE_HARDWARE = 2; // 0x2
field public static final int TOGGLE_TYPE_SOFTWARE = 1; // 0x1
}
public static class SensorPrivacyManager.Sensors {

View File

@@ -3726,13 +3726,25 @@ package android.hardware {
public final class SensorPrivacyManager {
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean areAnySensorPrivacyTogglesEnabled(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int, int);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, boolean);
}
public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
method public void onSensorPrivacyChanged(int, boolean);
method public default void onSensorPrivacyChanged(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener.SensorPrivacyChangedParams);
method @Deprecated public void onSensorPrivacyChanged(int, boolean);
}
public static class SensorPrivacyManager.OnSensorPrivacyChangedListener.SensorPrivacyChangedParams {
method public int getSensor();
method public int getToggleType();
method public boolean isEnabled();
}
}

View File

@@ -158,36 +158,30 @@ public final class SensorPrivacyManager {
}
/**
* Constant for software toggle.
*/
public static final int TOGGLE_TYPE_SOFTWARE =
SensorPrivacyIndividualEnabledSensorProto.SOFTWARE;
/**
* Constant for hardware toggle.
*/
public static final int TOGGLE_TYPE_HARDWARE =
SensorPrivacyIndividualEnabledSensorProto.HARDWARE;
/**
* Types of toggles which can exist for sensor privacy
*
* @hide
*/
public static class ToggleTypes {
private ToggleTypes() {}
/**
* Constant for software toggle.
*/
public static final int SOFTWARE = SensorPrivacyIndividualEnabledSensorProto.SOFTWARE;
/**
* Constant for hardware toggle.
*/
public static final int HARDWARE = SensorPrivacyIndividualEnabledSensorProto.HARDWARE;
/**
* Types of toggles which can exist for sensor privacy
*
* @hide
*/
@IntDef(value = {
SOFTWARE,
HARDWARE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ToggleType {}
}
@IntDef(value = {
TOGGLE_TYPE_SOFTWARE,
TOGGLE_TYPE_HARDWARE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ToggleType {}
/**
* Types of state which can exist for the sensor privacy toggle
@@ -229,23 +223,26 @@ public final class SensorPrivacyManager {
*/
@SystemApi
public interface OnSensorPrivacyChangedListener {
/**
* Callback invoked when the sensor privacy state changes.
*
* @param params Parameters describing the new state
*/
default void onSensorPrivacyChanged(@NonNull SensorPrivacyChangedParams params) {
onSensorPrivacyChanged(params.mSensor, params.mEnabled);
}
/**
* Callback invoked when the sensor privacy state changes.
*
* @param sensor the sensor whose state is changing
* @param enabled true if sensor privacy is enabled, false otherwise.
*
* @deprecated Please use
* {@link #onSensorPrivacyChanged(SensorPrivacyChangedParams)}
*/
@Deprecated
void onSensorPrivacyChanged(int sensor, boolean enabled);
}
/**
* A class implementing this interface can register with the {@link
* android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
* state changes.
*
* @hide
*/
public interface OnToggleSensorPrivacyChangedListener {
/**
* A class containing information about what the sensor privacy state has changed to.
@@ -262,7 +259,7 @@ public final class SensorPrivacyManager {
mEnabled = enabled;
}
public @ToggleTypes.ToggleType int getToggleType() {
public @ToggleType int getToggleType() {
return mToggleType;
}
@@ -274,13 +271,6 @@ public final class SensorPrivacyManager {
return mEnabled;
}
}
/**
* Callback invoked when the sensor privacy state changes.
*
* @param params Parameters describing the new state
*/
void onSensorPrivacyChanged(@NonNull SensorPrivacyChangedParams params);
}
private static final Object sInstanceLock = new Object();
@@ -305,15 +295,15 @@ public final class SensorPrivacyManager {
/** Registered listeners */
@GuardedBy("mLock")
@NonNull
private final ArrayMap<OnToggleSensorPrivacyChangedListener, Executor> mToggleListeners =
private final ArrayMap<OnSensorPrivacyChangedListener, Executor> mToggleListeners =
new ArrayMap<>();
/** Listeners registered using the deprecated APIs and which
* OnToggleSensorPrivacyChangedListener they're using. */
* OnSensorPrivacyChangedListener they're using. */
@GuardedBy("mLock")
@NonNull
private final ArrayMap<Pair<Integer, OnSensorPrivacyChangedListener>,
OnToggleSensorPrivacyChangedListener> mLegacyToggleListeners = new ArrayMap<>();
OnSensorPrivacyChangedListener> mLegacyToggleListeners = new ArrayMap<>();
/** The singleton ISensorPrivacyListener for IPC which will be used to dispatch to local
* listeners */
@@ -323,9 +313,9 @@ public final class SensorPrivacyManager {
public void onSensorPrivacyChanged(int toggleType, int sensor, boolean enabled) {
synchronized (mLock) {
for (int i = 0; i < mToggleListeners.size(); i++) {
OnToggleSensorPrivacyChangedListener listener = mToggleListeners.keyAt(i);
OnSensorPrivacyChangedListener listener = mToggleListeners.keyAt(i);
mToggleListeners.valueAt(i).execute(() -> listener
.onSensorPrivacyChanged(new OnToggleSensorPrivacyChangedListener
.onSensorPrivacyChanged(new OnSensorPrivacyChangedListener
.SensorPrivacyChangedParams(toggleType, sensor, enabled)));
}
}
@@ -366,13 +356,25 @@ public final class SensorPrivacyManager {
}
}
/**
* Returns the single instance of the SensorPrivacyManager.
*
* @hide
*/
public static SensorPrivacyManager getInstance(Context context, ISensorPrivacyManager service) {
synchronized (sInstanceLock) {
sInstance = new SensorPrivacyManager(context, service);
return sInstance;
}
}
/**
* Checks if the given toggle is supported on this device
* @param sensor The sensor to check
* @return whether the toggle for the sensor is supported on this device.
*/
public boolean supportsSensorToggle(@Sensors.Sensor int sensor) {
return supportsSensorToggle(ToggleTypes.SOFTWARE, sensor);
return supportsSensorToggle(TOGGLE_TYPE_SOFTWARE, sensor);
}
/**
@@ -380,10 +382,8 @@ public final class SensorPrivacyManager {
* @param sensor The sensor to check
* @return whether the toggle for the sensor is supported on this device.
*
* @hide
*/
public boolean supportsSensorToggle(@ToggleTypes.ToggleType int toggleType,
@Sensors.Sensor int sensor) {
public boolean supportsSensorToggle(@ToggleType int toggleType, @Sensors.Sensor int sensor) {
try {
Pair key = new Pair(toggleType, sensor);
synchronized (mLock) {
@@ -408,8 +408,6 @@ public final class SensorPrivacyManager {
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
*
* {@link #addSensorPrivacyListener(OnToggleSensorPrivacyChangedListener)}
*
* @hide
*/
@SystemApi
@@ -429,8 +427,6 @@ public final class SensorPrivacyManager {
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
*
* {@link #addSensorPrivacyListener(OnToggleSensorPrivacyChangedListener)}
*
* @hide
*/
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
@@ -449,19 +445,22 @@ public final class SensorPrivacyManager {
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
*
* {@link #addSensorPrivacyListener(Executor, OnToggleSensorPrivacyChangedListener)}
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
@NonNull OnSensorPrivacyChangedListener listener) {
Pair<Integer, OnSensorPrivacyChangedListener> pair = new Pair(sensor, listener);
OnToggleSensorPrivacyChangedListener toggleListener = params -> {
if (params.getSensor() == sensor) {
listener.onSensorPrivacyChanged(params.getSensor(), params.isEnabled());
OnSensorPrivacyChangedListener toggleListener = new OnSensorPrivacyChangedListener() {
@Override
public void onSensorPrivacyChanged(SensorPrivacyChangedParams params) {
if (params.getSensor() == sensor) {
listener.onSensorPrivacyChanged(params.getSensor(), params.isEnabled());
}
}
@Override
public void onSensorPrivacyChanged(int sensor, boolean enabled) {
}
};
@@ -476,13 +475,14 @@ public final class SensorPrivacyManager {
* Registers a new listener to receive notification when the state of sensor privacy
* changes.
*
* @param listener the OnToggleSensorPrivacyChangedListener to be notified when the state of
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of
* sensor privacy changes.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@NonNull OnToggleSensorPrivacyChangedListener listener) {
public void addSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) {
addSensorPrivacyListener(mContext.getMainExecutor(), listener);
}
@@ -492,14 +492,15 @@ public final class SensorPrivacyManager {
* changes.
*
* @param executor the executor to dispatch the callback on
* @param listener the OnToggleSensorPrivacyChangedListener to be notified when the state of
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of
* sensor privacy changes.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void addSensorPrivacyListener(@NonNull Executor executor,
@NonNull OnToggleSensorPrivacyChangedListener listener) {
@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mLock) {
addSensorPrivacyListenerLocked(executor, listener);
}
@@ -507,7 +508,7 @@ public final class SensorPrivacyManager {
@GuardedBy("mLock")
private void addSensorPrivacyListenerLocked(@NonNull Executor executor,
@NonNull OnToggleSensorPrivacyChangedListener listener) {
@NonNull OnSensorPrivacyChangedListener listener) {
if (!mToggleListenerRegistered) {
try {
mService.addToggleSensorPrivacyListener(mIToggleListener);
@@ -529,10 +530,6 @@ public final class SensorPrivacyManager {
* @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when
* sensor privacy changes.
*
* {@link #removeSensorPrivacyListener(OnToggleSensorPrivacyChangedListener)} with
* {@link #addSensorPrivacyListener(OnToggleSensorPrivacyChangedListener)} or
* {@link #addSensorPrivacyListener(Executor, OnToggleSensorPrivacyChangedListener)}
*
* @hide
*/
@SystemApi
@@ -541,7 +538,7 @@ public final class SensorPrivacyManager {
@NonNull OnSensorPrivacyChangedListener listener) {
Pair<Integer, OnSensorPrivacyChangedListener> pair = new Pair(sensor, listener);
synchronized (mLock) {
OnToggleSensorPrivacyChangedListener onToggleSensorPrivacyChangedListener =
OnSensorPrivacyChangedListener onToggleSensorPrivacyChangedListener =
mLegacyToggleListeners.remove(pair);
if (onToggleSensorPrivacyChangedListener != null) {
removeSensorPrivacyListenerLocked(onToggleSensorPrivacyChangedListener);
@@ -553,14 +550,15 @@ public final class SensorPrivacyManager {
* Unregisters the specified listener from receiving notifications when the state of any sensor
* privacy changes.
*
* @param listener the {@link OnToggleSensorPrivacyChangedListener} to be unregistered from
* @param listener the {@link OnSensorPrivacyChangedListener} to be unregistered from
* notifications when sensor privacy changes.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public void removeSensorPrivacyListener(
@NonNull OnToggleSensorPrivacyChangedListener listener) {
@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mLock) {
removeSensorPrivacyListenerLocked(listener);
}
@@ -568,7 +566,7 @@ public final class SensorPrivacyManager {
@GuardedBy("mLock")
private void removeSensorPrivacyListenerLocked(
@NonNull OnToggleSensorPrivacyChangedListener listener) {
@NonNull OnSensorPrivacyChangedListener listener) {
mToggleListeners.remove(listener);
if (mToggleListeners.size() == 0) {
try {
@@ -586,12 +584,15 @@ public final class SensorPrivacyManager {
*
* @return true if sensor privacy is currently enabled, false otherwise.
*
* @deprecated Prefer to use {@link #isSensorPrivacyEnabled(int, int)}
*
* @hide
*/
@Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
return isSensorPrivacyEnabled(ToggleTypes.SOFTWARE, sensor);
return isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor);
}
/**
@@ -601,8 +602,9 @@ public final class SensorPrivacyManager {
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isSensorPrivacyEnabled(@ToggleTypes.ToggleType int toggleType,
public boolean isSensorPrivacyEnabled(@ToggleType int toggleType,
@Sensors.Sensor int sensor) {
try {
return mService.isToggleSensorPrivacyEnabled(toggleType, sensor);
@@ -613,14 +615,16 @@ public final class SensorPrivacyManager {
/**
* Returns whether sensor privacy is currently enabled for a specific sensor.
* Combines the state of the SW + HW toggles and returns the actual privacy state.
* Combines the state of the SW + HW toggles and returns true if either the
* SOFTWARE or the HARDWARE toggles are enabled.
*
* @return true if sensor privacy is currently enabled, false otherwise.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isToggleSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
public boolean areAnySensorPrivacyTogglesEnabled(@Sensors.Sensor int sensor) {
try {
return mService.isCombinedToggleSensorPrivacyEnabled(sensor);
} catch (RemoteException e) {

View File

@@ -296,7 +296,7 @@ class PersistedState {
SensorState sensorState = states.valueAt(i);
// Do not persist hardware toggle states. Will be restored on reboot
if (userSensor.mType != SensorPrivacyManager.ToggleTypes.SOFTWARE) {
if (userSensor.mType != SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE) {
continue;
}
@@ -478,7 +478,7 @@ class PersistedState {
for (int j = 0; j < numSensors; j++) {
int sensor = userIndividualEnabled.keyAt(j);
SensorState sensorState = userIndividualEnabled.valueAt(j);
result.addState(SensorPrivacyManager.ToggleTypes.SOFTWARE,
result.addState(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
userId, sensor, sensorState.getState(), sensorState.getLastChange());
}
}

View File

@@ -39,8 +39,8 @@ import static android.hardware.SensorPrivacyManager.Sources.OTHER;
import static android.hardware.SensorPrivacyManager.Sources.QS_TILE;
import static android.hardware.SensorPrivacyManager.Sources.SETTINGS;
import static android.hardware.SensorPrivacyManager.Sources.SHELL;
import static android.hardware.SensorPrivacyManager.ToggleTypes.HARDWARE;
import static android.hardware.SensorPrivacyManager.ToggleTypes.SOFTWARE;
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_HARDWARE;
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE;
import static android.os.UserHandle.USER_NULL;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
@@ -310,11 +310,12 @@ public final class SensorPrivacyService extends SystemService {
// Reset sensor privacy when restriction is added
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)) {
setToggleSensorPrivacyUnchecked(SOFTWARE, userId, OTHER, CAMERA, false);
setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, CAMERA, false);
}
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
setToggleSensorPrivacyUnchecked(SOFTWARE, userId, OTHER, MICROPHONE, false);
setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, MICROPHONE,
false);
}
}
@@ -565,7 +566,7 @@ public final class SensorPrivacyService extends SystemService {
*/
private String getSensorUseActivityName(ArraySet<Integer> sensors) {
for (Integer sensor : sensors) {
if (isToggleSensorPrivacyEnabled(HARDWARE, sensor)) {
if (isToggleSensorPrivacyEnabled(TOGGLE_TYPE_HARDWARE, sensor)) {
return mContext.getResources().getString(
R.string.config_sensorUseStartedActivity_hwToggle);
}
@@ -691,7 +692,7 @@ public final class SensorPrivacyService extends SystemService {
return;
}
setToggleSensorPrivacyUnchecked(SOFTWARE, userId, source, sensor, enable);
setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, source, sensor, enable);
}
private void setToggleSensorPrivacyUnchecked(int toggleType, int userId, int source,
@@ -866,8 +867,8 @@ public final class SensorPrivacyService extends SystemService {
@Override
public boolean isCombinedToggleSensorPrivacyEnabled(int sensor) {
return isToggleSensorPrivacyEnabled(SOFTWARE, sensor) || isToggleSensorPrivacyEnabled(
HARDWARE, sensor);
return isToggleSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor)
|| isToggleSensorPrivacyEnabled(TOGGLE_TYPE_HARDWARE, sensor);
}
private boolean isToggleSensorPrivacyEnabledInternal(int userId, int toggleType,
@@ -879,7 +880,7 @@ public final class SensorPrivacyService extends SystemService {
@Override
public boolean supportsSensorToggle(int toggleType, int sensor) {
if (toggleType == SOFTWARE) {
if (toggleType == TOGGLE_TYPE_SOFTWARE) {
if (sensor == MICROPHONE) {
return mContext.getResources()
.getBoolean(R.bool.config_supportsMicToggle);
@@ -887,7 +888,7 @@ public final class SensorPrivacyService extends SystemService {
return mContext.getResources()
.getBoolean(R.bool.config_supportsCamToggle);
}
} else if (toggleType == SensorPrivacyManager.ToggleTypes.HARDWARE) {
} else if (toggleType == TOGGLE_TYPE_HARDWARE) {
if (sensor == MICROPHONE) {
return mContext.getResources()
.getBoolean(R.bool.config_supportsHardwareMicToggle);
@@ -1003,37 +1004,41 @@ public final class SensorPrivacyService extends SystemService {
final int hwToggleIdx = 1;
// Get SW toggles state
mSensorPrivacyStateController.atomic(() -> {
prevMicState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(from, SOFTWARE,
MICROPHONE);
prevCamState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(from, SOFTWARE,
CAMERA);
micState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(to, SOFTWARE,
MICROPHONE);
camState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(to, SOFTWARE, CAMERA);
prevMicState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(from,
TOGGLE_TYPE_SOFTWARE, MICROPHONE);
prevCamState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(from,
TOGGLE_TYPE_SOFTWARE, CAMERA);
micState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(to,
TOGGLE_TYPE_SOFTWARE, MICROPHONE);
camState[swToggleIdx] = isToggleSensorPrivacyEnabledInternal(to,
TOGGLE_TYPE_SOFTWARE, CAMERA);
});
// Get HW toggles state
mSensorPrivacyStateController.atomic(() -> {
prevMicState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(from, HARDWARE,
MICROPHONE);
prevCamState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(from, HARDWARE,
CAMERA);
micState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(to, HARDWARE,
MICROPHONE);
camState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(to, HARDWARE, CAMERA);
prevMicState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(from,
TOGGLE_TYPE_HARDWARE, MICROPHONE);
prevCamState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(from,
TOGGLE_TYPE_HARDWARE, CAMERA);
micState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(to,
TOGGLE_TYPE_HARDWARE, MICROPHONE);
camState[hwToggleIdx] = isToggleSensorPrivacyEnabledInternal(to,
TOGGLE_TYPE_HARDWARE, CAMERA);
});
if (from == USER_NULL || prevMicState[swToggleIdx] != micState[swToggleIdx]
|| prevMicState[hwToggleIdx] != micState[hwToggleIdx]) {
mHandler.handleSensorPrivacyChanged(to, SOFTWARE, MICROPHONE,
mHandler.handleSensorPrivacyChanged(to, TOGGLE_TYPE_SOFTWARE, MICROPHONE,
micState[swToggleIdx]);
mHandler.handleSensorPrivacyChanged(to, HARDWARE, MICROPHONE,
mHandler.handleSensorPrivacyChanged(to, TOGGLE_TYPE_HARDWARE, MICROPHONE,
micState[hwToggleIdx]);
setGlobalRestriction(MICROPHONE, micState[swToggleIdx] || micState[hwToggleIdx]);
}
if (from == USER_NULL || prevCamState[swToggleIdx] != camState[swToggleIdx]
|| prevCamState[hwToggleIdx] != camState[hwToggleIdx]) {
mHandler.handleSensorPrivacyChanged(to, SOFTWARE, CAMERA, camState[swToggleIdx]);
mHandler.handleSensorPrivacyChanged(to, HARDWARE, CAMERA, camState[hwToggleIdx]);
mHandler.handleSensorPrivacyChanged(to, TOGGLE_TYPE_SOFTWARE, CAMERA,
camState[swToggleIdx]);
mHandler.handleSensorPrivacyChanged(to, TOGGLE_TYPE_HARDWARE, CAMERA,
camState[hwToggleIdx]);
setGlobalRestriction(CAMERA, camState[swToggleIdx] || camState[hwToggleIdx]);
}
}
@@ -1437,7 +1442,7 @@ public final class SensorPrivacyService extends SystemService {
public boolean isSensorPrivacyEnabled(int userId, int sensor) {
return SensorPrivacyService.this
.mSensorPrivacyServiceImpl.isToggleSensorPrivacyEnabledInternal(userId,
SOFTWARE, sensor);
TOGGLE_TYPE_SOFTWARE, sensor);
}
@Override
@@ -1487,10 +1492,12 @@ public final class SensorPrivacyService extends SystemService {
userId = (userId == UserHandle.USER_CURRENT ? mCurrentUser : userId);
final int realUserId = (userId == UserHandle.USER_NULL ? mContext.getUserId() : userId);
sps.setToggleSensorPrivacyUnchecked(HARDWARE, realUserId, OTHER, sensor, enable);
sps.setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_HARDWARE, realUserId, OTHER, sensor,
enable);
// Also disable the SW toggle when disabling the HW toggle
if (!enable) {
sps.setToggleSensorPrivacyUnchecked(SOFTWARE, realUserId, OTHER, sensor, enable);
sps.setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, realUserId, OTHER, sensor,
enable);
}
}
}
@@ -1546,9 +1553,9 @@ public final class SensorPrivacyService extends SystemService {
if (!mIsInEmergencyCall) {
mIsInEmergencyCall = true;
if (mSensorPrivacyServiceImpl
.isToggleSensorPrivacyEnabled(SOFTWARE, MICROPHONE)) {
.isToggleSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, MICROPHONE)) {
mSensorPrivacyServiceImpl.setToggleSensorPrivacyUnchecked(
SOFTWARE, mCurrentUser, OTHER, MICROPHONE, false);
TOGGLE_TYPE_SOFTWARE, mCurrentUser, OTHER, MICROPHONE, false);
mMicUnmutedForEmergencyCall = true;
} else {
mMicUnmutedForEmergencyCall = false;
@@ -1574,7 +1581,7 @@ public final class SensorPrivacyService extends SystemService {
mIsInEmergencyCall = false;
if (mMicUnmutedForEmergencyCall) {
mSensorPrivacyServiceImpl.setToggleSensorPrivacyUnchecked(
SOFTWARE, mCurrentUser, OTHER, MICROPHONE, true);
TOGGLE_TYPE_SOFTWARE, mCurrentUser, OTHER, MICROPHONE, true);
mMicUnmutedForEmergencyCall = false;
}
}

View File

@@ -18,8 +18,8 @@ package com.android.server.sensorprivacy;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.hardware.SensorPrivacyManager.ToggleTypes.HARDWARE;
import static android.hardware.SensorPrivacyManager.ToggleTypes.SOFTWARE;
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_HARDWARE;
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -102,106 +102,106 @@ public class SensorPrivacyServiceMockingTest {
public void testMigration1() throws IOException {
PersistedState ps = migrateFromFile(PERSISTENCE_FILE1);
assertTrue(ps.getState(SOFTWARE, 0, MICROPHONE).isEnabled());
assertTrue(ps.getState(SOFTWARE, 0, CAMERA).isEnabled());
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE).isEnabled());
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).isEnabled());
assertNull(ps.getState(SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA));
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
}
@Test
public void testMigration2() throws IOException {
PersistedState ps = migrateFromFile(PERSISTENCE_FILE2);
assertTrue(ps.getState(SOFTWARE, 0, MICROPHONE).isEnabled());
assertTrue(ps.getState(SOFTWARE, 0, CAMERA).isEnabled());
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE).isEnabled());
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).isEnabled());
assertTrue(ps.getState(SOFTWARE, 10, MICROPHONE).isEnabled());
assertFalse(ps.getState(SOFTWARE, 10, CAMERA).isEnabled());
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE).isEnabled());
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA).isEnabled());
assertNull(ps.getState(SOFTWARE, 11, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 11, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 11, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 11, CAMERA));
assertTrue(ps.getState(SOFTWARE, 12, MICROPHONE).isEnabled());
assertNull(ps.getState(SOFTWARE, 12, CAMERA));
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 12, MICROPHONE).isEnabled());
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 12, CAMERA));
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(HARDWARE, 11, MICROPHONE));
assertNull(ps.getState(HARDWARE, 11, CAMERA));
assertNull(ps.getState(HARDWARE, 12, MICROPHONE));
assertNull(ps.getState(HARDWARE, 12, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 11, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 11, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 12, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 12, CAMERA));
}
@Test
public void testMigration3() throws IOException {
PersistedState ps = migrateFromFile(PERSISTENCE_FILE3);
assertFalse(ps.getState(SOFTWARE, 0, MICROPHONE).isEnabled());
assertFalse(ps.getState(SOFTWARE, 0, CAMERA).isEnabled());
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE).isEnabled());
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).isEnabled());
assertNull(ps.getState(SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA));
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
}
@Test
public void testMigration4() throws IOException {
PersistedState ps = migrateFromFile(PERSISTENCE_FILE4);
assertTrue(ps.getState(SOFTWARE, 0, MICROPHONE).isEnabled());
assertFalse(ps.getState(SOFTWARE, 0, CAMERA).isEnabled());
assertTrue(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE).isEnabled());
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).isEnabled());
assertFalse(ps.getState(SOFTWARE, 10, MICROPHONE).isEnabled());
assertNull(ps.getState(SOFTWARE, 10, CAMERA));
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE).isEnabled());
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA));
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
}
@Test
public void testMigration5() throws IOException {
PersistedState ps = migrateFromFile(PERSISTENCE_FILE5);
assertNull(ps.getState(SOFTWARE, 0, MICROPHONE));
assertFalse(ps.getState(SOFTWARE, 0, CAMERA).isEnabled());
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE));
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).isEnabled());
assertNull(ps.getState(SOFTWARE, 10, MICROPHONE));
assertFalse(ps.getState(SOFTWARE, 10, CAMERA).isEnabled());
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE));
assertFalse(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA).isEnabled());
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
}
@Test
public void testMigration6() throws IOException {
PersistedState ps = migrateFromFile(PERSISTENCE_FILE6);
assertNull(ps.getState(SOFTWARE, 0, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA));
assertNull(ps.getState(SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA));
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
}
private PersistedState migrateFromFile(String fileName) throws IOException {
@@ -233,32 +233,32 @@ public class SensorPrivacyServiceMockingTest {
public void testPersistence1Version2() throws IOException {
PersistedState ps = getPersistedStateV2(PERSISTENCE_FILE7);
assertEquals(1, ps.getState(SOFTWARE, 0, MICROPHONE).getState());
assertEquals(123L, ps.getState(SOFTWARE, 0, MICROPHONE).getLastChange());
assertEquals(2, ps.getState(SOFTWARE, 0, CAMERA).getState());
assertEquals(123L, ps.getState(SOFTWARE, 0, CAMERA).getLastChange());
assertEquals(1, ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE).getState());
assertEquals(123L, ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE).getLastChange());
assertEquals(2, ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).getState());
assertEquals(123L, ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA).getLastChange());
assertNull(ps.getState(HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(HARDWARE, 0, CAMERA));
assertNull(ps.getState(SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA));
}
@Test
public void testPersistence2Version2() throws IOException {
PersistedState ps = getPersistedStateV2(PERSISTENCE_FILE8);
assertEquals(1, ps.getState(HARDWARE, 0, MICROPHONE).getState());
assertEquals(1234L, ps.getState(HARDWARE, 0, MICROPHONE).getLastChange());
assertEquals(2, ps.getState(HARDWARE, 0, CAMERA).getState());
assertEquals(1234L, ps.getState(HARDWARE, 0, CAMERA).getLastChange());
assertEquals(1, ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE).getState());
assertEquals(1234L, ps.getState(TOGGLE_TYPE_HARDWARE, 0, MICROPHONE).getLastChange());
assertEquals(2, ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA).getState());
assertEquals(1234L, ps.getState(TOGGLE_TYPE_HARDWARE, 0, CAMERA).getLastChange());
assertNull(ps.getState(SOFTWARE, 0, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 0, CAMERA));
assertNull(ps.getState(SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(SOFTWARE, 10, CAMERA));
assertNull(ps.getState(HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(HARDWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_SOFTWARE, 10, CAMERA));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, MICROPHONE));
assertNull(ps.getState(TOGGLE_TYPE_HARDWARE, 10, CAMERA));
}
private PersistedState getPersistedStateV2(String version2FilePath) throws IOException {
@@ -296,13 +296,15 @@ public class SensorPrivacyServiceMockingTest {
SensorPrivacyStateController sensorPrivacyStateController =
getSensorPrivacyStateControllerImpl();
SensorState micState = sensorPrivacyStateController.getState(SOFTWARE, 0, MICROPHONE);
SensorState camState = sensorPrivacyStateController.getState(SOFTWARE, 0, CAMERA);
SensorState micState = sensorPrivacyStateController.getState(TOGGLE_TYPE_SOFTWARE, 0,
MICROPHONE);
SensorState camState = sensorPrivacyStateController.getState(TOGGLE_TYPE_SOFTWARE, 0,
CAMERA);
assertEquals(SensorPrivacyManager.StateTypes.DISABLED, micState.getState());
assertEquals(SensorPrivacyManager.StateTypes.DISABLED, camState.getState());
verify(persistedState, times(1)).getState(SOFTWARE, 0, MICROPHONE);
verify(persistedState, times(1)).getState(SOFTWARE, 0, CAMERA);
verify(persistedState, times(1)).getState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE);
verify(persistedState, times(1)).getState(TOGGLE_TYPE_SOFTWARE, 0, CAMERA);
} finally {
mockitoSession.finishMocking();
}
@@ -319,14 +321,16 @@ public class SensorPrivacyServiceMockingTest {
PersistedState persistedState = mock(PersistedState.class);
SensorState sensorState = mock(SensorState.class);
doReturn(persistedState).when(() -> PersistedState.fromFile(any()));
doReturn(sensorState).when(persistedState).getState(SOFTWARE, 0, MICROPHONE);
doReturn(sensorState).when(persistedState).getState(TOGGLE_TYPE_SOFTWARE, 0,
MICROPHONE);
doReturn(SensorPrivacyManager.StateTypes.ENABLED).when(sensorState).getState();
doReturn(0L).when(sensorState).getLastChange();
SensorPrivacyStateController sensorPrivacyStateController =
getSensorPrivacyStateControllerImpl();
SensorState micState = sensorPrivacyStateController.getState(SOFTWARE, 0, MICROPHONE);
SensorState micState = sensorPrivacyStateController.getState(TOGGLE_TYPE_SOFTWARE, 0,
MICROPHONE);
assertEquals(SensorPrivacyManager.StateTypes.ENABLED, micState.getState());
assertEquals(0L, micState.getLastChange());
@@ -349,13 +353,13 @@ public class SensorPrivacyServiceMockingTest {
SensorPrivacyStateController sensorPrivacyStateController =
getSensorPrivacyStateControllerImpl();
sensorPrivacyStateController.setState(SOFTWARE, 0, MICROPHONE, true,
sensorPrivacyStateController.setState(TOGGLE_TYPE_SOFTWARE, 0, MICROPHONE, true,
mock(Handler.class), changed -> {});
ArgumentCaptor<SensorState> captor = ArgumentCaptor.forClass(SensorState.class);
verify(persistedState, times(1)).setState(eq(SOFTWARE), eq(0), eq(MICROPHONE),
captor.capture());
verify(persistedState, times(1)).setState(eq(TOGGLE_TYPE_SOFTWARE), eq(0),
eq(MICROPHONE), captor.capture());
assertEquals(SensorPrivacyManager.StateTypes.ENABLED, captor.getValue().getState());
} finally {
mockitoSession.finishMocking();