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.res.Configuration; 20 21 import com.android.internal.logging.MetricsLogger; 22 import com.android.systemui.R; 23 import com.android.systemui.qs.QSTile; 24 import com.android.systemui.statusbar.policy.RotationLockController; 25 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback; 26 27 /** Quick settings tile: Rotation **/ 28 public class RotationLockTile extends QSTile<QSTile.BooleanState> { 29 private final AnimationIcon mPortraitToAuto 30 = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation); 31 private final AnimationIcon mAutoToPortrait 32 = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation); 33 34 private final AnimationIcon mLandscapeToAuto 35 = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation); 36 private final AnimationIcon mAutoToLandscape 37 = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation); 38 39 private final RotationLockController mController; 40 41 public RotationLockTile(Host host) { 42 super(host); 43 mController = host.getRotationLockController(); 44 } 45 46 @Override 47 protected BooleanState newTileState() { 48 return new BooleanState(); 49 } 50 51 public void setListening(boolean listening) { 52 if (mController == null) return; 53 if (listening) { 54 mController.addRotationLockControllerCallback(mCallback); 55 } else { 56 mController.removeRotationLockControllerCallback(mCallback); 57 } 58 } 59 60 @Override 61 protected void handleClick() { 62 if (mController == null) return; 63 MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); 64 final boolean newState = !mState.value; 65 mController.setRotationLocked(newState); 66 refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE); 67 } 68 69 @Override 70 protected void handleUpdateState(BooleanState state, Object arg) { 71 if (mController == null) return; 72 final boolean rotationLocked = arg != null ? ((UserBoolean) arg).value 73 : mController.isRotationLocked(); 74 final boolean userInitiated = arg != null ? ((UserBoolean) arg).userInitiated : false; 75 state.visible = mController.isRotationLockAffordanceVisible(); 76 if (state.value == rotationLocked && state.contentDescription != null) { 77 // No change and initialized, no need to update all the values. 78 return; 79 } 80 state.value = rotationLocked; 81 final boolean portrait = isCurrentOrientationLockPortrait(); 82 final AnimationIcon icon; 83 if (rotationLocked) { 84 final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label 85 : R.string.quick_settings_rotation_locked_landscape_label; 86 state.label = mContext.getString(label); 87 icon = portrait ? mAutoToPortrait : mAutoToLandscape; 88 } else { 89 state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label); 90 icon = portrait ? mPortraitToAuto : mLandscapeToAuto; 91 } 92 icon.setAllowAnimation(userInitiated); 93 state.icon = icon; 94 state.contentDescription = getAccessibilityString(rotationLocked, 95 R.string.accessibility_rotation_lock_on_portrait, 96 R.string.accessibility_rotation_lock_on_landscape, 97 R.string.accessibility_rotation_lock_off); 98 } 99 100 private boolean isCurrentOrientationLockPortrait() { 101 int lockOrientation = mController.getRotationLockOrientation(); 102 if (lockOrientation == Configuration.ORIENTATION_UNDEFINED) { 103 // Freely rotating device; use current rotation 104 return mContext.getResources().getConfiguration().orientation 105 != Configuration.ORIENTATION_LANDSCAPE; 106 } else { 107 return lockOrientation != Configuration.ORIENTATION_LANDSCAPE; 108 } 109 } 110 111 @Override 112 public int getMetricsCategory() { 113 return MetricsLogger.QS_ROTATIONLOCK; 114 } 115 116 /** 117 * Get the correct accessibility string based on the state 118 * 119 * @param locked Whether or not rotation is locked. 120 * @param idWhenPortrait The id which should be used when locked in portrait. 121 * @param idWhenLandscape The id which should be used when locked in landscape. 122 * @param idWhenOff The id which should be used when the rotation lock is off. 123 * @return 124 */ 125 private String getAccessibilityString(boolean locked, int idWhenPortrait, int idWhenLandscape, 126 int idWhenOff) { 127 int stringID; 128 if (locked) { 129 stringID = isCurrentOrientationLockPortrait() ? idWhenPortrait: idWhenLandscape; 130 } else { 131 stringID = idWhenOff; 132 } 133 return mContext.getString(stringID); 134 } 135 136 @Override 137 protected String composeChangeAnnouncement() { 138 return getAccessibilityString(mState.value, 139 R.string.accessibility_rotation_lock_on_portrait_changed, 140 R.string.accessibility_rotation_lock_on_landscape_changed, 141 R.string.accessibility_rotation_lock_off_changed); 142 } 143 144 private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() { 145 @Override 146 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) { 147 refreshState(rotationLocked ? UserBoolean.BACKGROUND_TRUE 148 : UserBoolean.BACKGROUND_FALSE); 149 } 150 }; 151 } 152