1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.display;
18 
19 import static androidx.lifecycle.Lifecycle.Event.ON_START;
20 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
21 
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 
25 import androidx.annotation.VisibleForTesting;
26 import androidx.lifecycle.Lifecycle;
27 import androidx.lifecycle.LifecycleObserver;
28 import androidx.lifecycle.OnLifecycleEvent;
29 import androidx.preference.PreferenceScreen;
30 import androidx.preference.SwitchPreferenceCompat;
31 import androidx.preference.TwoStatePreference;
32 
33 import com.android.settings.R;
34 import com.android.settings.core.TogglePreferenceController;
35 import com.android.settings.overlay.FeatureFactory;
36 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
37 import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
38 import com.android.settingslib.search.SearchIndexableRaw;
39 
40 import java.util.List;
41 
42 /** Controller for device state based auto rotation preferences. */
43 public class DeviceStateAutoRotateSettingController extends TogglePreferenceController implements
44         LifecycleObserver {
45 
46     private TwoStatePreference mPreference;
47 
48     private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager;
49     private final int mOrder;
50     private final DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
51             mDeviceStateRotationLockSettingsListener = () -> updateState(mPreference);
52     private final int mDeviceState;
53     private final String mDeviceStateDescription;
54     private final MetricsFeatureProvider mMetricsFeatureProvider;
55 
56     @VisibleForTesting
DeviceStateAutoRotateSettingController(Context context, int deviceState, String deviceStateDescription, int order, MetricsFeatureProvider metricsFeatureProvider)57     DeviceStateAutoRotateSettingController(Context context, int deviceState,
58             String deviceStateDescription, int order,
59             MetricsFeatureProvider metricsFeatureProvider) {
60         super(context, getPreferenceKeyForDeviceState(deviceState));
61         mMetricsFeatureProvider = metricsFeatureProvider;
62         mDeviceState = deviceState;
63         mDeviceStateDescription = deviceStateDescription;
64         mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(context);
65         mOrder = order;
66     }
67 
DeviceStateAutoRotateSettingController(Context context, int deviceState, String deviceStateDescription, int order)68     public DeviceStateAutoRotateSettingController(Context context, int deviceState,
69             String deviceStateDescription, int order) {
70         this(context, deviceState, deviceStateDescription, order,
71                 FeatureFactory.getFeatureFactory().getMetricsFeatureProvider());
72     }
73 
init(Lifecycle lifecycle)74     void init(Lifecycle lifecycle) {
75         lifecycle.addObserver(this);
76     }
77 
78     @OnLifecycleEvent(ON_START)
onStart()79     void onStart() {
80         mAutoRotateSettingsManager.registerListener(mDeviceStateRotationLockSettingsListener);
81     }
82 
83     @OnLifecycleEvent(ON_STOP)
onStop()84     void onStop() {
85         mAutoRotateSettingsManager.unregisterListener(mDeviceStateRotationLockSettingsListener);
86     }
87 
88     @Override
displayPreference(PreferenceScreen screen)89     public void displayPreference(PreferenceScreen screen) {
90         mPreference = new SwitchPreferenceCompat(mContext);
91         mPreference.setTitle(mDeviceStateDescription);
92         mPreference.setKey(getPreferenceKey());
93         mPreference.setOrder(mOrder);
94         screen.addPreference(mPreference);
95         super.displayPreference(screen);
96     }
97 
98     @Override
getAvailabilityStatus()99     public int getAvailabilityStatus() {
100         return DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)
101                 ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
102     }
103 
104     @Override
getPreferenceKey()105     public String getPreferenceKey() {
106         return getPreferenceKeyForDeviceState(mDeviceState);
107     }
108 
getPreferenceKeyForDeviceState(int deviceState)109     private static String getPreferenceKeyForDeviceState(int deviceState) {
110         return "auto_rotate_device_state_" + deviceState;
111     }
112 
113     @Override
isChecked()114     public boolean isChecked() {
115         return !mAutoRotateSettingsManager.isRotationLocked(mDeviceState);
116     }
117 
118     @Override
setChecked(boolean isChecked)119     public boolean setChecked(boolean isChecked) {
120         boolean isRotationLocked = !isChecked;
121         logSettingChanged(isChecked);
122         mAutoRotateSettingsManager.updateSetting(mDeviceState, isRotationLocked);
123         return true;
124     }
125 
logSettingChanged(boolean isChecked)126     private void logSettingChanged(boolean isChecked) {
127         boolean isRotationLocked = !isChecked;
128         mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK,
129                 isRotationLocked);
130 
131         int actionCategory = isChecked
132                 ? SettingsEnums.ACTION_ENABLE_AUTO_ROTATION_DEVICE_STATE
133                 : SettingsEnums.ACTION_DISABLE_AUTO_ROTATION_DEVICE_STATE;
134         mMetricsFeatureProvider.action(mContext, actionCategory, /* value= */ mDeviceState);
135     }
136 
137     @Override
updateRawDataToIndex(List<SearchIndexableRaw> rawData)138     public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
139         SearchIndexableRaw indexable = new SearchIndexableRaw(mContext);
140         indexable.key = getPreferenceKey();
141         indexable.title = mDeviceStateDescription;
142         // Maybe pass screen title as param?
143         indexable.screenTitle = mContext.getString(R.string.accelerometer_title);
144         rawData.add(indexable);
145     }
146 
147     @Override
getSliceHighlightMenuRes()148     public int getSliceHighlightMenuRes() {
149         return R.string.menu_key_display;
150     }
151 
152     @Override
isSliceable()153     public boolean isSliceable() {
154         return true; // Maybe set to false if in accessibility settings screen
155     }
156 
157     @Override
isPublicSlice()158     public boolean isPublicSlice() {
159         return true;
160     }
161 }
162