Make SensorToggleControllers lifecycle aware
We need to watch the lifecycle so that we can unregister callbacks and not cause leaks. This change also rewrites the SensorPrivacyManagerHelper. The previous implmementation was using deprecated apis. It also had an issue where if a callback was added it would not necessarily register alistener with the callback with the service since that was only done when the value is checked. Now we register a listener when the class is instantiated and with the new API there will only be the 1. Finally we impove the tests to have more coverage and test both SensorToggleControllers and the SensorPRivacyManagerHelper class. Test: Use profiler to verify no more leaks SensorToggleControllerTest, SensorPrivacyManagerHelperTest Bug: 244280065 Change-Id: Ibf0bcee455444a104ca6800302907c3dc0de8f1f
This commit is contained in:
@@ -18,29 +18,37 @@ package com.android.settings.privacy;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CAMERA_TOGGLE;
|
||||
|
||||
import static com.android.settings.utils.SensorPrivacyManagerHelper.CAMERA;
|
||||
import static com.android.settings.utils.SensorPrivacyManagerHelper.SENSOR_CAMERA;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.utils.SensorPrivacyManagerHelper;
|
||||
|
||||
/**
|
||||
* Controller for microphone toggle
|
||||
*/
|
||||
public class CameraToggleController extends SensorToggleController {
|
||||
|
||||
public CameraToggleController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSensor() {
|
||||
return CAMERA;
|
||||
@VisibleForTesting
|
||||
public CameraToggleController(Context context, String preferenceKey,
|
||||
SensorPrivacyManagerHelper sensorPrivacyManagerHelper) {
|
||||
super(context, preferenceKey, sensorPrivacyManagerHelper, /* ignoreDeviceConfig */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mSensorPrivacyManagerHelper.supportsSensorToggle(getSensor())
|
||||
&& DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "camera_toggle_enabled",
|
||||
true) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
public int getSensor() {
|
||||
return SENSOR_CAMERA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceConfigKey() {
|
||||
return "camera_toggle_enabled";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -18,10 +18,11 @@ package com.android.settings.privacy;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_MICROPHONE_TOGGLE;
|
||||
|
||||
import static com.android.settings.utils.SensorPrivacyManagerHelper.MICROPHONE;
|
||||
import static com.android.settings.utils.SensorPrivacyManagerHelper.SENSOR_MICROPHONE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import com.android.settings.utils.SensorPrivacyManagerHelper;
|
||||
|
||||
/**
|
||||
* Controller for camera toggle
|
||||
@@ -31,16 +32,19 @@ public class MicToggleController extends SensorToggleController {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSensor() {
|
||||
return MICROPHONE;
|
||||
public MicToggleController(Context context, String preferenceKey,
|
||||
SensorPrivacyManagerHelper sensorPrivacyManagerHelper) {
|
||||
super(context, preferenceKey, sensorPrivacyManagerHelper, /* ignoreDeviceConfig */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mSensorPrivacyManagerHelper.supportsSensorToggle(getSensor())
|
||||
&& DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "mic_toggle_enabled",
|
||||
true) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
public int getSensor() {
|
||||
return SENSOR_MICROPHONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceConfigKey() {
|
||||
return "mic_toggle_enabled";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.android.settings.privacy;
|
||||
|
||||
import static android.hardware.SensorPrivacyManager.Sources.SETTINGS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -27,20 +29,35 @@ import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settings.utils.SensorPrivacyManagerHelper;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Base class for sensor toggle controllers
|
||||
*/
|
||||
public abstract class SensorToggleController extends TogglePreferenceController {
|
||||
public abstract class SensorToggleController extends TogglePreferenceController implements
|
||||
SensorPrivacyManagerHelper.Callback, LifecycleObserver {
|
||||
|
||||
protected final SensorPrivacyManagerHelper mSensorPrivacyManagerHelper;
|
||||
private final Executor mCallbackExecutor;
|
||||
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
/** For testing since DeviceConfig uses static method calls */
|
||||
private boolean mIgnoreDeviceConfig;
|
||||
|
||||
public SensorToggleController(Context context, String preferenceKey) {
|
||||
this(context, preferenceKey, SensorPrivacyManagerHelper.getInstance(context), false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
SensorToggleController(Context context, String preferenceKey,
|
||||
SensorPrivacyManagerHelper sensorPrivacyManagerHelper, boolean ignoreDeviceConfig) {
|
||||
super(context, preferenceKey);
|
||||
mSensorPrivacyManagerHelper = SensorPrivacyManagerHelper.getInstance(context);
|
||||
|
||||
mIgnoreDeviceConfig = ignoreDeviceConfig;
|
||||
mSensorPrivacyManagerHelper = sensorPrivacyManagerHelper;
|
||||
mCallbackExecutor = context.getMainExecutor();
|
||||
}
|
||||
|
||||
@@ -49,10 +66,22 @@ public abstract class SensorToggleController extends TogglePreferenceController
|
||||
*/
|
||||
public abstract int getSensor();
|
||||
|
||||
/**
|
||||
* The key for the device config setting for whether the feature is enabled.
|
||||
*/
|
||||
public abstract String getDeviceConfigKey();
|
||||
|
||||
protected String getRestriction() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mSensorPrivacyManagerHelper.supportsSensorToggle(getSensor())
|
||||
&& (mIgnoreDeviceConfig || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
|
||||
getDeviceConfigKey(), true)) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return !mSensorPrivacyManagerHelper.isSensorBlocked(getSensor());
|
||||
@@ -60,8 +89,7 @@ public abstract class SensorToggleController extends TogglePreferenceController
|
||||
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
mSensorPrivacyManagerHelper.setSensorBlockedForProfileGroup(SETTINGS, getSensor(),
|
||||
!isChecked);
|
||||
mSensorPrivacyManagerHelper.setSensorBlocked(getSensor(), !isChecked);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -69,21 +97,38 @@ public abstract class SensorToggleController extends TogglePreferenceController
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
|
||||
RestrictedSwitchPreference preference =
|
||||
(RestrictedSwitchPreference) screen.findPreference(getPreferenceKey());
|
||||
mScreen = screen;
|
||||
|
||||
RestrictedSwitchPreference preference = mScreen.findPreference(getPreferenceKey());
|
||||
if (preference != null) {
|
||||
preference.setDisabledByAdmin(RestrictedLockUtilsInternal
|
||||
.checkIfRestrictionEnforced(mContext, getRestriction(), mContext.getUserId()));
|
||||
}
|
||||
|
||||
mSensorPrivacyManagerHelper.addSensorBlockedListener(
|
||||
getSensor(),
|
||||
(sensor, blocked) -> updateState(screen.findPreference(mPreferenceKey)),
|
||||
mCallbackExecutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSliceHighlightMenuRes() {
|
||||
return R.string.menu_key_privacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorPrivacyChanged(int toggleType, int sensor, boolean blocked) {
|
||||
updateState(mScreen.findPreference(mPreferenceKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* onStart lifecycle event
|
||||
*/
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_START)
|
||||
public void onStart() {
|
||||
mSensorPrivacyManagerHelper.addSensorBlockedListener(getSensor(), mCallbackExecutor, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* onStop lifecycle event
|
||||
*/
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||
public void onStop() {
|
||||
mSensorPrivacyManagerHelper.removeSensorBlockedListener(this);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user