1 /* 2 * Copyright (C) 2018 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 package com.android.launcher3.states; 17 18 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; 19 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 20 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 21 import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE; 22 23 import static com.android.launcher3.Utilities.ATLEAST_NOUGAT; 24 25 import android.app.Activity; 26 import android.content.SharedPreferences; 27 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 28 import android.content.res.Resources; 29 30 import com.android.launcher3.R; 31 import com.android.launcher3.Utilities; 32 33 /** 34 * Utility class to manage launcher rotation 35 */ 36 public class RotationHelper implements OnSharedPreferenceChangeListener { 37 38 public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation"; 39 40 public static boolean getAllowRotationDefaultValue() { 41 if (ATLEAST_NOUGAT) { 42 // If the device was scaled, used the original dimensions to determine if rotation 43 // is allowed of not. 44 Resources res = Resources.getSystem(); 45 int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp 46 * res.getDisplayMetrics().densityDpi / DENSITY_DEVICE_STABLE; 47 return originalSmallestWidth >= 600; 48 } 49 return false; 50 } 51 52 public static final int REQUEST_NONE = 0; 53 public static final int REQUEST_ROTATE = 1; 54 public static final int REQUEST_LOCK = 2; 55 56 private final Activity mActivity; 57 private final SharedPreferences mPrefs; 58 59 private final boolean mIgnoreAutoRotateSettings; 60 private boolean mAutoRotateEnabled; 61 62 /** 63 * Rotation request made by {@link InternalStateHandler}. This supersedes any other request. 64 */ 65 private int mStateHandlerRequest = REQUEST_NONE; 66 /** 67 * Rotation request made by a Launcher State 68 */ 69 private int mCurrentStateRequest = REQUEST_NONE; 70 71 // This is used to defer setting rotation flags until the activity is being created 72 private boolean mInitialized; 73 public boolean mDestroyed; 74 75 private int mLastActivityFlags = -1; 76 77 public RotationHelper(Activity activity) { 78 mActivity = activity; 79 80 // On large devices we do not handle auto-rotate differently. 81 mIgnoreAutoRotateSettings = mActivity.getResources().getBoolean(R.bool.allow_rotation); 82 if (!mIgnoreAutoRotateSettings) { 83 mPrefs = Utilities.getPrefs(mActivity); 84 mPrefs.registerOnSharedPreferenceChangeListener(this); 85 mAutoRotateEnabled = mPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, 86 getAllowRotationDefaultValue()); 87 } else { 88 mPrefs = null; 89 } 90 } 91 92 @Override 93 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { 94 mAutoRotateEnabled = mPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, 95 getAllowRotationDefaultValue()); 96 notifyChange(); 97 } 98 99 public void setStateHandlerRequest(int request) { 100 if (mStateHandlerRequest != request) { 101 mStateHandlerRequest = request; 102 notifyChange(); 103 } 104 } 105 106 public void setCurrentStateRequest(int request) { 107 if (mCurrentStateRequest != request) { 108 mCurrentStateRequest = request; 109 notifyChange(); 110 } 111 } 112 113 public void initialize() { 114 if (!mInitialized) { 115 mInitialized = true; 116 notifyChange(); 117 } 118 } 119 120 public void destroy() { 121 if (!mDestroyed) { 122 mDestroyed = true; 123 if (mPrefs != null) { 124 mPrefs.unregisterOnSharedPreferenceChangeListener(this); 125 } 126 } 127 } 128 129 private void notifyChange() { 130 if (!mInitialized || mDestroyed) { 131 return; 132 } 133 134 final int activityFlags; 135 if (mStateHandlerRequest != REQUEST_NONE) { 136 activityFlags = mStateHandlerRequest == REQUEST_LOCK ? 137 SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED; 138 } else if (mCurrentStateRequest == REQUEST_LOCK) { 139 activityFlags = SCREEN_ORIENTATION_LOCKED; 140 } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE 141 || mAutoRotateEnabled) { 142 activityFlags = SCREEN_ORIENTATION_UNSPECIFIED; 143 } else { 144 // If auto rotation is off, allow rotation on the activity, in case the user is using 145 // forced rotation. 146 activityFlags = SCREEN_ORIENTATION_NOSENSOR; 147 } 148 if (activityFlags != mLastActivityFlags) { 149 mLastActivityFlags = activityFlags; 150 mActivity.setRequestedOrientation(activityFlags); 151 } 152 } 153 154 @Override 155 public String toString() { 156 return String.format("[mStateHandlerRequest=%d, mCurrentStateRequest=%d," 157 + " mLastActivityFlags=%d, mIgnoreAutoRotateSettings=%b, mAutoRotateEnabled=%b]", 158 mStateHandlerRequest, mCurrentStateRequest, mLastActivityFlags, 159 mIgnoreAutoRotateSettings, mAutoRotateEnabled); 160 } 161 } 162