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
17package com.android.systemui.qs.tiles;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.res.Configuration;
22
23import android.provider.Settings;
24import android.service.quicksettings.Tile;
25import android.widget.Switch;
26
27import com.android.internal.logging.MetricsLogger;
28import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
29import com.android.systemui.Dependency;
30import com.android.systemui.R;
31import com.android.systemui.qs.QSHost;
32import com.android.systemui.plugins.qs.QSTile.BooleanState;
33import com.android.systemui.qs.tileimpl.QSTileImpl;
34import com.android.systemui.statusbar.policy.RotationLockController;
35import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
36
37/** Quick settings tile: Rotation **/
38public class RotationLockTile extends QSTileImpl<BooleanState> {
39    private final AnimationIcon mPortraitToAuto
40            = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation,
41            R.drawable.ic_portrait_from_auto_rotate);
42    private final AnimationIcon mAutoToPortrait
43            = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation,
44            R.drawable.ic_portrait_to_auto_rotate);
45
46    private final AnimationIcon mLandscapeToAuto
47            = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation,
48            R.drawable.ic_landscape_from_auto_rotate);
49    private final AnimationIcon mAutoToLandscape
50            = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation,
51            R.drawable.ic_landscape_to_auto_rotate);
52
53    private final RotationLockController mController;
54
55    public RotationLockTile(QSHost host) {
56        super(host);
57        mController = Dependency.get(RotationLockController.class);
58    }
59
60    @Override
61    public BooleanState newTileState() {
62        return new BooleanState();
63    }
64
65    public void setListening(boolean listening) {
66        if (mController == null) return;
67        if (listening) {
68            mController.addCallback(mCallback);
69        } else {
70            mController.removeCallback(mCallback);
71        }
72    }
73
74    @Override
75    public Intent getLongClickIntent() {
76        return new Intent(Settings.ACTION_DISPLAY_SETTINGS);
77    }
78
79    @Override
80    protected void handleClick() {
81        if (mController == null) return;
82        final boolean newState = !mState.value;
83        mController.setRotationLocked(!newState);
84        refreshState(newState);
85    }
86
87    @Override
88    public CharSequence getTileLabel() {
89        return getState().label;
90    }
91
92    @Override
93    protected void handleUpdateState(BooleanState state, Object arg) {
94        if (mController == null) return;
95        final boolean rotationLocked = mController.isRotationLocked();
96        // TODO: Handle accessibility rotation lock and whatnot.
97
98        state.value = !rotationLocked;
99        final boolean portrait = isCurrentOrientationLockPortrait(mController, mContext);
100        if (rotationLocked) {
101            final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label
102                    : R.string.quick_settings_rotation_locked_landscape_label;
103            state.label = mContext.getString(label);
104            state.icon = portrait ? mAutoToPortrait : mAutoToLandscape;
105        } else {
106            state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
107            state.icon = portrait ? mPortraitToAuto : mLandscapeToAuto;
108        }
109        state.contentDescription = getAccessibilityString(rotationLocked);
110        state.expandedAccessibilityClassName = Switch.class.getName();
111        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
112    }
113
114    public static boolean isCurrentOrientationLockPortrait(RotationLockController controller,
115            Context context) {
116        int lockOrientation = controller.getRotationLockOrientation();
117        if (lockOrientation == Configuration.ORIENTATION_UNDEFINED) {
118            // Freely rotating device; use current rotation
119            return context.getResources().getConfiguration().orientation
120                    != Configuration.ORIENTATION_LANDSCAPE;
121        } else {
122            return lockOrientation != Configuration.ORIENTATION_LANDSCAPE;
123        }
124    }
125
126    @Override
127    public int getMetricsCategory() {
128        return MetricsEvent.QS_ROTATIONLOCK;
129    }
130
131    /**
132     * Get the correct accessibility string based on the state
133     *
134     * @param locked Whether or not rotation is locked.
135     */
136    private String getAccessibilityString(boolean locked) {
137        if (locked) {
138            return mContext.getString(R.string.accessibility_quick_settings_rotation_value,
139                    isCurrentOrientationLockPortrait(mController, mContext)
140                            ? mContext.getString(
141                                    R.string.quick_settings_rotation_locked_portrait_label)
142                            : mContext.getString(
143                                    R.string.quick_settings_rotation_locked_landscape_label))
144                    + "," + mContext.getString(R.string.accessibility_quick_settings_rotation);
145
146        } else {
147            return mContext.getString(R.string.accessibility_quick_settings_rotation);
148        }
149    }
150
151    @Override
152    protected String composeChangeAnnouncement() {
153        return getAccessibilityString(mState.value);
154    }
155
156    private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() {
157        @Override
158        public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
159            refreshState(rotationLocked);
160        }
161    };
162}
163