Merge changes If8da2ae5,I38445a13 into sc-dev

* changes:
  Log duration privacy toggle was in previous state
  Persist the last time a sensor's privacy state changed
This commit is contained in:
Evan Severson
2021-07-08 22:03:53 +00:00
committed by Android (Google) Code Review

View File

@@ -94,6 +94,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -147,6 +148,8 @@ import java.util.Objects;
public final class SensorPrivacyService extends SystemService {
private static final String TAG = SensorPrivacyService.class.getSimpleName();
private static final boolean DEBUG = false;
private static final boolean DEBUG_LOGGING = false;
/** Version number indicating compatibility parsing the persisted file */
private static final int CURRENT_PERSISTENCE_VERSION = 1;
@@ -162,6 +165,7 @@ public final class SensorPrivacyService extends SystemService {
private static final String XML_ATTRIBUTE_PERSISTENCE_VERSION = "persistence-version";
private static final String XML_ATTRIBUTE_VERSION = "version";
private static final String XML_ATTRIBUTE_ENABLED = "enabled";
private static final String XML_ATTRIBUTE_LAST_CHANGE = "last-change";
private static final String XML_ATTRIBUTE_SENSOR = "sensor";
private static final String SENSOR_PRIVACY_CHANNEL_ID = Context.SENSOR_PRIVACY_SERVICE;
@@ -248,7 +252,7 @@ public final class SensorPrivacyService extends SystemService {
@GuardedBy("mLock")
private SparseBooleanArray mEnabled = new SparseBooleanArray();
@GuardedBy("mLock")
private SparseArray<SparseBooleanArray> mIndividualEnabled = new SparseArray<>();
private SparseArray<SparseArray<SensorState>> mIndividualEnabled = new SparseArray<>();
/**
* Packages for which not to show sensor use reminders.
@@ -262,6 +266,34 @@ public final class SensorPrivacyService extends SystemService {
private final ArrayMap<SensorUseReminderDialogInfo, ArraySet<Integer>>
mQueuedSensorUseReminderDialogs = new ArrayMap<>();
private class SensorState {
private boolean mEnabled;
private long mLastChange;
SensorState(boolean enabled) {
mEnabled = enabled;
mLastChange = getCurrentTimeMillis();
}
SensorState(boolean enabled, long lastChange) {
mEnabled = enabled;
if (lastChange < 0) {
mLastChange = getCurrentTimeMillis();
} else {
mLastChange = lastChange;
}
}
boolean setEnabled(boolean enabled) {
if (mEnabled != enabled) {
mEnabled = enabled;
mLastChange = getCurrentTimeMillis();
return true;
}
return false;
}
}
private class SensorUseReminderDialogInfo {
private int mTaskId;
private UserHandle mUser;
@@ -326,11 +358,11 @@ 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)) {
setIndividualSensorPrivacyUnchecked(userId, CAMERA, false);
setIndividualSensorPrivacyUnchecked(userId, OTHER, CAMERA, false);
}
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
setIndividualSensorPrivacyUnchecked(userId, MICROPHONE, false);
setIndividualSensorPrivacyUnchecked(userId, OTHER, MICROPHONE, false);
}
}
@@ -671,20 +703,33 @@ public final class SensorPrivacyService extends SystemService {
return;
}
if (userId == mUserManagerInternal.getProfileParentId(userId)) {
logSensorPrivacyToggle(source, sensor, enable);
}
setIndividualSensorPrivacyUnchecked(userId, sensor, enable);
setIndividualSensorPrivacyUnchecked(userId, source, sensor, enable);
}
private void setIndividualSensorPrivacyUnchecked(int userId, int sensor, boolean enable) {
private void setIndividualSensorPrivacyUnchecked(int userId, int source, int sensor,
boolean enable) {
synchronized (mLock) {
SparseBooleanArray userIndividualEnabled = mIndividualEnabled.get(userId,
new SparseBooleanArray());
userIndividualEnabled.put(sensor, enable);
SparseArray<SensorState> userIndividualEnabled = mIndividualEnabled.get(userId,
new SparseArray<>());
SensorState sensorState = userIndividualEnabled.get(sensor);
long lastChange;
if (sensorState != null) {
lastChange = sensorState.mLastChange;
if (!sensorState.setEnabled(enable)) {
// State not changing
return;
}
} else {
sensorState = new SensorState(enable);
lastChange = sensorState.mLastChange;
userIndividualEnabled.put(sensor, sensorState);
}
mIndividualEnabled.put(userId, userIndividualEnabled);
if (userId == mUserManagerInternal.getProfileParentId(userId)) {
logSensorPrivacyToggle(source, sensor, sensorState.mEnabled, lastChange);
}
if (!enable) {
long token = Binder.clearCallingIdentity();
try {
@@ -728,12 +773,12 @@ public final class SensorPrivacyService extends SystemService {
return true;
}
private void logSensorPrivacyToggle(int source, int sensor, boolean enable) {
long logMins = 0L;
//(TODO:pyuli) : Add timestamp after persistent storage for timestamp is done.
private void logSensorPrivacyToggle(int source, int sensor, boolean enabled,
long lastChange) {
long logMins = Math.max(0, (getCurrentTimeMillis() - lastChange) / (1000 * 60));
int logAction = -1;
if (enable) {
if (enabled) {
logAction = PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_OFF;
} else {
logAction = PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_ON;
@@ -766,6 +811,11 @@ public final class SensorPrivacyService extends SystemService {
logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SOURCE_UNKNOWN;
}
if (DEBUG || DEBUG_LOGGING) {
Log.d(TAG, "Logging sensor toggle interaction:" + " logSensor=" + logSensor
+ " logAction=" + logAction + " logSource=" + logSource + " logMins="
+ logMins);
}
write(PRIVACY_SENSOR_TOGGLE_INTERACTION, logSensor, logAction, logSource, logMins);
}
@@ -828,11 +878,15 @@ public final class SensorPrivacyService extends SystemService {
public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
enforceObserveSensorPrivacyPermission();
synchronized (mLock) {
SparseBooleanArray states = mIndividualEnabled.get(userId);
SparseArray<SensorState> states = mIndividualEnabled.get(userId);
if (states == null) {
return false;
}
return states.get(sensor, false);
SensorState state = states.get(sensor);
if (state == null) {
return false;
}
return state.mEnabled;
}
}
@@ -857,7 +911,7 @@ public final class SensorPrivacyService extends SystemService {
// these should never be changed even with refactorings.
if (persistenceVersion == 0) {
boolean enabled = parser.getAttributeBoolean(null, "enabled", false);
SparseBooleanArray individualEnabled = new SparseBooleanArray();
SparseArray<SensorState> individualEnabled = new SparseArray<>();
version = 0;
XmlUtils.nextElement(parser);
@@ -867,7 +921,7 @@ public final class SensorPrivacyService extends SystemService {
int sensor = XmlUtils.readIntAttribute(parser, "sensor");
boolean indEnabled = XmlUtils.readBooleanAttribute(parser,
"enabled");
individualEnabled.put(sensor, indEnabled);
individualEnabled.put(sensor, new SensorState(indEnabled));
XmlUtils.skipCurrentTag(parser);
} else {
XmlUtils.nextElement(parser);
@@ -877,7 +931,8 @@ public final class SensorPrivacyService extends SystemService {
map.put(VER0_INDIVIDUAL_ENABLED, individualEnabled);
} else if (persistenceVersion == CURRENT_PERSISTENCE_VERSION) {
SparseBooleanArray enabled = new SparseBooleanArray();
SparseArray<SparseBooleanArray> individualEnabled = new SparseArray<>();
SparseArray<SparseArray<SensorState>> individualEnabled =
new SparseArray<>();
version = parser.getAttributeInt(null,
XML_ATTRIBUTE_VERSION, 1);
@@ -913,10 +968,13 @@ public final class SensorPrivacyService extends SystemService {
int sensor = parser.getAttributeInt(null, XML_ATTRIBUTE_SENSOR);
boolean isEnabled = parser.getAttributeBoolean(null,
XML_ATTRIBUTE_ENABLED);
SparseBooleanArray userIndividualEnabled = individualEnabled.get(
currentUserId, new SparseBooleanArray());
long lastChange = parser
.getAttributeLong(null, XML_ATTRIBUTE_LAST_CHANGE, -1);
SparseArray<SensorState> userIndividualEnabled =
individualEnabled.get(currentUserId, new SparseArray<>());
userIndividualEnabled.put(sensor, isEnabled);
userIndividualEnabled
.put(sensor, new SensorState(isEnabled, lastChange));
individualEnabled.put(currentUserId, userIndividualEnabled);
}
}
@@ -949,7 +1007,7 @@ public final class SensorPrivacyService extends SystemService {
mEnabled = new SparseBooleanArray();
mIndividualEnabled = new SparseArray<>();
forAllUsers(userId -> mEnabled.put(userId, false));
forAllUsers(userId -> mIndividualEnabled.put(userId, new SparseBooleanArray()));
forAllUsers(userId -> mIndividualEnabled.put(userId, new SparseArray<>()));
return true;
}
boolean upgraded = false;
@@ -986,7 +1044,7 @@ public final class SensorPrivacyService extends SystemService {
if (version == CURRENT_VERSION) {
mEnabled = (SparseBooleanArray) map.get(VER1_ENABLED);
mIndividualEnabled =
(SparseArray<SparseBooleanArray>) map.get(VER1_INDIVIDUAL_ENABLED);
(SparseArray<SparseArray<SensorState>>) map.get(VER1_INDIVIDUAL_ENABLED);
}
return upgraded;
}
@@ -1016,15 +1074,18 @@ public final class SensorPrivacyService extends SystemService {
serializer.attributeBoolean(
null, XML_ATTRIBUTE_ENABLED, isSensorPrivacyEnabled(userId));
SparseBooleanArray individualEnabled =
mIndividualEnabled.get(userId, new SparseBooleanArray());
SparseArray<SensorState> individualEnabled =
mIndividualEnabled.get(userId, new SparseArray<>());
int numIndividual = individualEnabled.size();
for (int i = 0; i < numIndividual; i++) {
serializer.startTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY);
int sensor = individualEnabled.keyAt(i);
boolean enabled = individualEnabled.valueAt(i);
SensorState sensorState = individualEnabled.valueAt(i);
boolean enabled = sensorState.mEnabled;
long lastChange = sensorState.mLastChange;
serializer.attributeInt(null, XML_ATTRIBUTE_SENSOR, sensor);
serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enabled);
serializer.attributeLong(null, XML_ATTRIBUTE_LAST_CHANGE, lastChange);
serializer.endTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY);
}
serializer.endTag(null, XML_TAG_USER);
@@ -1229,7 +1290,7 @@ public final class SensorPrivacyService extends SystemService {
dumpStream.write("is_enabled", SensorPrivacyUserProto.IS_ENABLED,
mEnabled.get(userId, false));
SparseBooleanArray individualEnabled = mIndividualEnabled.get(userId);
SparseArray<SensorState> individualEnabled = mIndividualEnabled.get(userId);
if (individualEnabled != null) {
int numIndividualEnabled = individualEnabled.size();
for (int i = 0; i < numIndividualEnabled; i++) {
@@ -1241,7 +1302,8 @@ public final class SensorPrivacyService extends SystemService {
individualEnabled.keyAt(i));
dumpStream.write("is_enabled",
SensorPrivacyIndividualEnabledSensorProto.IS_ENABLED,
individualEnabled.valueAt(i));
individualEnabled.valueAt(i).mEnabled);
// TODO dump last change
dumpStream.end(individualToken);
}
@@ -1321,7 +1383,7 @@ public final class SensorPrivacyService extends SystemService {
enforceManageSensorPrivacyPermission();
synchronized (mLock) {
SparseBooleanArray individualEnabled =
SparseArray<SensorState> individualEnabled =
mIndividualEnabled.get(userId);
if (individualEnabled != null) {
individualEnabled.delete(sensor);
@@ -1682,7 +1744,7 @@ public final class SensorPrivacyService extends SystemService {
if (mSensorPrivacyServiceImpl
.isIndividualSensorPrivacyEnabled(getCurrentUser(), MICROPHONE)) {
mSensorPrivacyServiceImpl.setIndividualSensorPrivacyUnchecked(
getCurrentUser(), MICROPHONE, false);
getCurrentUser(), OTHER, MICROPHONE, false);
mMicUnmutedForEmergencyCall = true;
} else {
mMicUnmutedForEmergencyCall = false;
@@ -1697,11 +1759,19 @@ public final class SensorPrivacyService extends SystemService {
mIsInEmergencyCall = false;
if (mMicUnmutedForEmergencyCall) {
mSensorPrivacyServiceImpl.setIndividualSensorPrivacyUnchecked(
getCurrentUser(), MICROPHONE, true);
getCurrentUser(), OTHER, MICROPHONE, true);
mMicUnmutedForEmergencyCall = false;
}
}
}
}
}
private static long getCurrentTimeMillis() {
try {
return SystemClock.currentNetworkTimeMillis();
} catch (Exception e) {
return System.currentTimeMillis();
}
}
}