Merge "Add support for device state based auto-rotation preferences in Settings."

This commit is contained in:
TreeHugger Robot
2022-02-15 02:55:55 +00:00
committed by Android (Google) Code Review
24 changed files with 1106 additions and 14 deletions

View File

@@ -74,6 +74,7 @@ public class AutoRotatePreferenceController extends TogglePreferenceController i
@Override
public int getAvailabilityStatus() {
return RotationPolicy.isRotationLockToggleVisible(mContext)
&& !DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
import java.util.List;
/** Fragment that shows all the available device state based auto-rotation preferences. */
@SearchIndexable
public class DeviceStateAutoRotateDetailsFragment extends DashboardFragment {
private static final String TAG = "DeviceStateAutoRotateDetailsFragment";
@Override
public int getMetricsCategory() {
return SettingsEnums.DISPLAY_AUTO_ROTATE_SETTINGS;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.device_state_auto_rotate_settings;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
DeviceStateAutoRotationHelper.initControllers(
getLifecycle(),
useAll(DeviceStateAutoRotateSettingController.class)
);
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return DeviceStateAutoRotationHelper.createPreferenceControllers(context);
}
@Override
protected String getLogTag() {
return TAG;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.device_state_auto_rotate_settings) {
@Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context,
boolean enabled) {
return DeviceStateAutoRotationHelper.getRawDataToIndex(context, enabled);
}
};
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import android.content.Context;
import android.text.TextUtils;
import com.android.settings.core.BasePreferenceController;
/**
* The top-level preference controller for device state based auto-rotation settings.
*
* It doesn't do anything on its own besides showing/hiding. The toggling of the settings will
* always be done in the details screen when device state based auto-rotation is enabled.
*/
public class DeviceStateAutoRotateOverviewController extends BasePreferenceController {
/** Preference key for when it is used in "accessibility_system_controls.xml". */
private static final String ACCESSIBILITY_PREF_KEY = "device_state_auto_rotate_accessibility";
public DeviceStateAutoRotateOverviewController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
return isAvailableInternal() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
private boolean isAvailableInternal() {
return isA11yPage()
? DeviceStateAutoRotationHelper.isDeviceStateRotationEnabledForA11y(mContext)
: DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext);
}
private boolean isA11yPage() {
return TextUtils.equals(getPreferenceKey(), ACCESSIBILITY_PREF_KEY);
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import android.app.settings.SettingsEnums;
import android.content.Context;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.settingslib.search.SearchIndexableRaw;
import java.util.List;
/** Controller for device state based auto rotation preferences. */
public class DeviceStateAutoRotateSettingController extends TogglePreferenceController implements
LifecycleObserver {
private SwitchPreference mPreference;
private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager;
private final int mOrder;
private final DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
mDeviceStateRotationLockSettingsListener = () -> updateState(mPreference);
private final int mDeviceState;
private final String mDeviceStateDescription;
private final MetricsFeatureProvider mMetricsFeatureProvider;
public DeviceStateAutoRotateSettingController(Context context, int deviceState,
String deviceStateDescription, int order) {
super(context, getPreferenceKeyForDeviceState(deviceState));
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mDeviceState = deviceState;
mDeviceStateDescription = deviceStateDescription;
mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(context);
mOrder = order;
}
void init(Lifecycle lifecycle) {
lifecycle.addObserver(this);
}
@OnLifecycleEvent(ON_START)
void onStart() {
mAutoRotateSettingsManager.registerListener(mDeviceStateRotationLockSettingsListener);
}
@OnLifecycleEvent(ON_STOP)
void onStop() {
mAutoRotateSettingsManager.unregisterListener(mDeviceStateRotationLockSettingsListener);
}
@Override
public void displayPreference(PreferenceScreen screen) {
mPreference = new SwitchPreference(mContext);
mPreference.setTitle(mDeviceStateDescription);
mPreference.setKey(getPreferenceKey());
mPreference.setOrder(mOrder);
screen.addPreference(mPreference);
super.displayPreference(screen);
}
@Override
public int getAvailabilityStatus() {
return DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public String getPreferenceKey() {
return getPreferenceKeyForDeviceState(mDeviceState);
}
private static String getPreferenceKeyForDeviceState(int deviceState) {
return "auto_rotate_device_state_" + deviceState;
}
@Override
public boolean isChecked() {
return !mAutoRotateSettingsManager.isRotationLocked(mDeviceState);
}
@Override
public boolean setChecked(boolean isChecked) {
boolean isRotationLocked = !isChecked;
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK,
isRotationLocked);
mAutoRotateSettingsManager.updateSetting(mDeviceState, isRotationLocked);
return true;
}
@Override
public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
SearchIndexableRaw indexable = new SearchIndexableRaw(mContext);
indexable.key = getPreferenceKey();
indexable.title = mDeviceStateDescription;
// Maybe pass screen title as param?
indexable.screenTitle = mContext.getString(R.string.accelerometer_title);
rawData.add(indexable);
}
@Override
public int getSliceHighlightMenuRes() {
return R.string.menu_key_display;
}
@Override
public boolean isSliceable() {
return true; // Maybe set to false if in accessibility settings screen
}
@Override
public boolean isPublicSlice() {
return true;
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import android.content.Context;
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import com.android.internal.view.RotationPolicy;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager.SettableDeviceState;
import com.android.settingslib.search.SearchIndexableRaw;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
/**
* Helper class with utility methods related to device state auto-rotation that can be used in
* auto-rotation settings fragments and controllers.
*/
public class DeviceStateAutoRotationHelper {
private static final String TAG = "DeviceStateAutoRotHelpr";
static void initControllers(Lifecycle lifecycle,
List<DeviceStateAutoRotateSettingController> controllers) {
for (DeviceStateAutoRotateSettingController controller : controllers) {
controller.init(lifecycle);
}
}
static ImmutableList<AbstractPreferenceController> createPreferenceControllers(
Context context) {
List<SettableDeviceState> settableDeviceStates = DeviceStateRotationLockSettingsManager
.getInstance(context).getSettableDeviceStates();
int numDeviceStates = settableDeviceStates.size();
if (numDeviceStates == 0) {
return ImmutableList.of();
}
String[] deviceStateSettingDescriptions = context.getResources().getStringArray(
R.array.config_settableAutoRotationDeviceStatesDescriptions);
if (numDeviceStates != deviceStateSettingDescriptions.length) {
Log.wtf(TAG,
"Mismatch between number of device states and device states descriptions.");
return ImmutableList.of();
}
ImmutableList.Builder<AbstractPreferenceController> controllers =
ImmutableList.builderWithExpectedSize(numDeviceStates);
for (int i = 0; i < numDeviceStates; i++) {
SettableDeviceState settableDeviceState = settableDeviceStates.get(i);
if (!settableDeviceState.isSettable()) {
continue;
}
// Preferences with a lower order will be showed first. Here we go below 0 to make sure
// we are shown before statically declared preferences in XML.
int order = -numDeviceStates + i;
controllers.add(new DeviceStateAutoRotateSettingController(
context,
settableDeviceState.getDeviceState(),
deviceStateSettingDescriptions[i],
order
));
}
return controllers.build();
}
static List<SearchIndexableRaw> getRawDataToIndex(
Context context, boolean enabled) {
// Check what the "enabled" param is for
List<AbstractPreferenceController> controllers = createPreferenceControllers(context);
List<SearchIndexableRaw> rawData = new ArrayList<>();
for (AbstractPreferenceController controller : controllers) {
((BasePreferenceController) controller).updateRawDataToIndex(rawData);
}
return rawData;
}
/** Returns whether the device state based auto-rotation settings are enabled. */
public static boolean isDeviceStateRotationEnabled(Context context) {
return RotationPolicy.isRotationLockToggleVisible(context)
&& DeviceStateRotationLockSettingsManager.isDeviceStateRotationLockEnabled(context);
}
/**
* Returns whether the device state based auto-rotation settings are enabled for the
* accessibility settings page.
*/
public static boolean isDeviceStateRotationEnabledForA11y(Context context) {
return RotationPolicy.isRotationSupported(context)
&& DeviceStateRotationLockSettingsManager.isDeviceStateRotationLockEnabled(context);
}
}

View File

@@ -47,6 +47,7 @@ import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
/**
* SmartAutoRotateController controls whether auto rotation is enabled
@@ -54,6 +55,8 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
public class SmartAutoRotateController extends TogglePreferenceController implements
Preference.OnPreferenceChangeListener, LifecycleObserver {
protected Preference mPreference;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final SensorPrivacyManager mPrivacyManager;
private final PowerManager mPowerManager;
@@ -63,7 +66,9 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
updateState(mPreference);
}
};
protected Preference mPreference;
private final DeviceStateRotationLockSettingsManager mDeviceStateAutoRotateSettingsManager;
private final DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
mDeviceStateRotationLockSettingsListener = () -> updateState(mPreference);
private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
public SmartAutoRotateController(Context context, String preferenceKey) {
@@ -73,6 +78,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
mPrivacyManager
.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference));
mPowerManager = context.getSystemService(PowerManager.class);
mDeviceStateAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(
context);
}
public void init(Lifecycle lifecycle) {
@@ -89,6 +96,9 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
}
protected boolean isRotationLocked() {
if (DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)) {
return mDeviceStateAutoRotateSettingsManager.isRotationLockedForAllStates();
}
return RotationPolicy.isRotationLocked(mContext);
}
@@ -127,6 +137,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
};
}
RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener);
mDeviceStateAutoRotateSettingsManager.registerListener(
mDeviceStateRotationLockSettingsListener);
}
@OnLifecycleEvent(ON_STOP)
@@ -136,6 +148,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
mRotationPolicyListener = null;
}
mDeviceStateAutoRotateSettingsManager.unregisterListener(
mDeviceStateRotationLockSettingsListener);
}
@Override

View File

@@ -77,6 +77,7 @@ public class SmartAutoRotatePreferenceController extends TogglePreferenceControl
@Override
public int getAvailabilityStatus() {
return RotationPolicy.isRotationLockToggleVisible(mContext)
&& !DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}

View File

@@ -34,10 +34,14 @@ import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.widget.FooterPreference;
import java.util.List;
/**
* Preference fragment used for auto rotation
*/
@@ -60,6 +64,15 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
public void onAttach(Context context) {
super.onAttach(context);
use(SmartAutoRotateController.class).init(getLifecycle());
DeviceStateAutoRotationHelper.initControllers(
getLifecycle(),
useAll(DeviceStateAutoRotateSettingController.class)
);
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return DeviceStateAutoRotationHelper.createPreferenceControllers(context);
}
@Override
@@ -79,7 +92,9 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
@VisibleForTesting
void createHeader(SettingsActivity activity) {
if (isRotationResolverServiceAvailable(activity)) {
boolean deviceStateRotationEnabled =
DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(activity);
if (isRotationResolverServiceAvailable(activity) && !deviceStateRotationEnabled) {
final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
switchBar.setTitle(
getContext().getString(R.string.auto_rotate_settings_primary_switch_title));
@@ -127,5 +142,12 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.auto_rotate_settings);
new BaseSearchIndexProvider(R.xml.auto_rotate_settings) {
@Override
public List<SearchIndexableRaw> getRawDataToIndex(
Context context, boolean enabled) {
return DeviceStateAutoRotationHelper.getRawDataToIndex(context, enabled);
}
};
}