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