1 /*
2  * Copyright (C) 2014 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.systemui.qs.tiles;
18 
19 import android.content.Intent;
20 import android.content.res.Configuration;
21 import android.content.res.Resources;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.provider.Settings;
25 import android.service.quicksettings.Tile;
26 import android.view.View;
27 import android.widget.Switch;
28 
29 import androidx.annotation.Nullable;
30 
31 import com.android.internal.logging.MetricsLogger;
32 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
33 import com.android.systemui.R;
34 import com.android.systemui.dagger.qualifiers.Background;
35 import com.android.systemui.dagger.qualifiers.Main;
36 import com.android.systemui.plugins.ActivityStarter;
37 import com.android.systemui.plugins.FalsingManager;
38 import com.android.systemui.plugins.qs.QSTile.BooleanState;
39 import com.android.systemui.plugins.statusbar.StatusBarStateController;
40 import com.android.systemui.qs.QSHost;
41 import com.android.systemui.qs.logging.QSLogger;
42 import com.android.systemui.qs.tileimpl.QSTileImpl;
43 import com.android.systemui.statusbar.policy.RotationLockController;
44 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
45 
46 import javax.inject.Inject;
47 
48 /** Quick settings tile: Rotation **/
49 public class RotationLockTile extends QSTileImpl<BooleanState> {
50 
51     private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_auto_rotate);
52     private final RotationLockController mController;
53 
54     @Inject
RotationLockTile( QSHost host, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, MetricsLogger metricsLogger, StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, RotationLockController rotationLockController )55     public RotationLockTile(
56             QSHost host,
57             @Background Looper backgroundLooper,
58             @Main Handler mainHandler,
59             FalsingManager falsingManager,
60             MetricsLogger metricsLogger,
61             StatusBarStateController statusBarStateController,
62             ActivityStarter activityStarter,
63             QSLogger qsLogger,
64             RotationLockController rotationLockController
65     ) {
66         super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
67                 statusBarStateController, activityStarter, qsLogger);
68         mController = rotationLockController;
69         mController.observe(this, mCallback);
70     }
71 
72     @Override
newTileState()73     public BooleanState newTileState() {
74         return new BooleanState();
75     }
76 
77     @Override
getLongClickIntent()78     public Intent getLongClickIntent() {
79         return new Intent(Settings.ACTION_AUTO_ROTATE_SETTINGS);
80     }
81 
82     @Override
handleClick(@ullable View view)83     protected void handleClick(@Nullable View view) {
84         final boolean newState = !mState.value;
85         mController.setRotationLocked(!newState);
86         refreshState(newState);
87     }
88 
89     @Override
getTileLabel()90     public CharSequence getTileLabel() {
91         return getState().label;
92     }
93 
94     @Override
handleUpdateState(BooleanState state, Object arg)95     protected void handleUpdateState(BooleanState state, Object arg) {
96         final boolean rotationLocked = mController.isRotationLocked();
97 
98         state.value = !rotationLocked;
99         state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
100         state.icon = mIcon;
101         state.contentDescription = getAccessibilityString(rotationLocked);
102         state.expandedAccessibilityClassName = Switch.class.getName();
103         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
104     }
105 
isCurrentOrientationLockPortrait(RotationLockController controller, Resources resources)106     public static boolean isCurrentOrientationLockPortrait(RotationLockController controller,
107             Resources resources) {
108         int lockOrientation = controller.getRotationLockOrientation();
109         if (lockOrientation == Configuration.ORIENTATION_UNDEFINED) {
110             // Freely rotating device; use current rotation
111             return resources.getConfiguration().orientation
112                     != Configuration.ORIENTATION_LANDSCAPE;
113         } else {
114             return lockOrientation != Configuration.ORIENTATION_LANDSCAPE;
115         }
116     }
117 
118     @Override
getMetricsCategory()119     public int getMetricsCategory() {
120         return MetricsEvent.QS_ROTATIONLOCK;
121     }
122 
123     /**
124      * Get the correct accessibility string based on the state
125      *
126      * @param locked Whether or not rotation is locked.
127      */
getAccessibilityString(boolean locked)128     private String getAccessibilityString(boolean locked) {
129         return mContext.getString(R.string.accessibility_quick_settings_rotation);
130     }
131 
132     @Override
composeChangeAnnouncement()133     protected String composeChangeAnnouncement() {
134         return getAccessibilityString(mState.value);
135     }
136 
137     private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() {
138         @Override
139         public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
140             refreshState(rotationLocked);
141         }
142     };
143 }
144