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