• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 import android.content.SharedPreferences;
23 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
24 
25 import com.android.launcher3.BaseActivity;
26 import com.android.launcher3.DeviceProfile;
27 import com.android.launcher3.Utilities;
28 import com.android.launcher3.util.ActivityTracker;
29 import com.android.launcher3.util.UiThreadHelper;
30 
31 /**
32  * Utility class to manage launcher rotation
33  */
34 public class RotationHelper implements OnSharedPreferenceChangeListener,
35         DeviceProfile.OnDeviceProfileChangeListener {
36 
37     private static final String TAG = "RotationHelper";
38 
39     public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
40 
41     public static final int REQUEST_NONE = 0;
42     public static final int REQUEST_ROTATE = 1;
43     public static final int REQUEST_LOCK = 2;
44 
45     private BaseActivity mActivity;
46     private SharedPreferences mSharedPrefs = null;
47 
48     private boolean mIgnoreAutoRotateSettings;
49     private boolean mForceAllowRotationForTesting;
50     private boolean mHomeRotationEnabled;
51 
52     /**
53      * Rotation request made by
54      * {@link ActivityTracker.SchedulerCallback}.
55      * This supersedes any other request.
56      */
57     private int mStateHandlerRequest = REQUEST_NONE;
58     /**
59      * Rotation request made by an app transition
60      */
61     private int mCurrentTransitionRequest = REQUEST_NONE;
62     /**
63      * Rotation request made by a Launcher State
64      */
65     private int mCurrentStateRequest = REQUEST_NONE;
66 
67     // This is used to defer setting rotation flags until the activity is being created
68     private boolean mInitialized;
69     private boolean mDestroyed;
70 
71     // Initialize mLastActivityFlags to a value not used by SCREEN_ORIENTATION flags
72     private int mLastActivityFlags = -999;
73 
RotationHelper(BaseActivity activity)74     public RotationHelper(BaseActivity activity) {
75         mActivity = activity;
76     }
77 
setIgnoreAutoRotateSettings(boolean ignoreAutoRotateSettings)78     private void setIgnoreAutoRotateSettings(boolean ignoreAutoRotateSettings) {
79         // On large devices we do not handle auto-rotate differently.
80         mIgnoreAutoRotateSettings = ignoreAutoRotateSettings;
81         if (!mIgnoreAutoRotateSettings) {
82             if (mSharedPrefs == null) {
83                 mSharedPrefs = Utilities.getPrefs(mActivity);
84                 mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
85             }
86             mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
87                     mActivity.getDeviceProfile().allowRotation);
88         } else {
89             if (mSharedPrefs != null) {
90                 mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
91                 mSharedPrefs = null;
92             }
93         }
94     }
95 
96     @Override
onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s)97     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
98         if (mDestroyed) return;
99         boolean wasRotationEnabled = mHomeRotationEnabled;
100         mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
101                 mActivity.getDeviceProfile().allowRotation);
102         if (mHomeRotationEnabled != wasRotationEnabled) {
103             notifyChange();
104         }
105     }
106 
107     @Override
onDeviceProfileChanged(DeviceProfile dp)108     public void onDeviceProfileChanged(DeviceProfile dp) {
109         boolean ignoreAutoRotateSettings = dp.allowRotation;
110         if (mIgnoreAutoRotateSettings != ignoreAutoRotateSettings) {
111             setIgnoreAutoRotateSettings(ignoreAutoRotateSettings);
112             notifyChange();
113         }
114     }
115 
setStateHandlerRequest(int request)116     public void setStateHandlerRequest(int request) {
117         if (mStateHandlerRequest != request) {
118             mStateHandlerRequest = request;
119             notifyChange();
120         }
121     }
122 
setCurrentTransitionRequest(int request)123     public void setCurrentTransitionRequest(int request) {
124         if (mCurrentTransitionRequest != request) {
125             mCurrentTransitionRequest = request;
126             notifyChange();
127         }
128     }
129 
setCurrentStateRequest(int request)130     public void setCurrentStateRequest(int request) {
131         if (mCurrentStateRequest != request) {
132             mCurrentStateRequest = request;
133             notifyChange();
134         }
135     }
136 
137     // Used by tests only.
forceAllowRotationForTesting(boolean allowRotation)138     public void forceAllowRotationForTesting(boolean allowRotation) {
139         mForceAllowRotationForTesting = allowRotation;
140         notifyChange();
141     }
142 
initialize()143     public void initialize() {
144         if (!mInitialized) {
145             mInitialized = true;
146             setIgnoreAutoRotateSettings(mActivity.getDeviceProfile().allowRotation);
147             mActivity.addOnDeviceProfileChangeListener(this);
148             notifyChange();
149         }
150     }
151 
destroy()152     public void destroy() {
153         if (!mDestroyed) {
154             mDestroyed = true;
155             mActivity.removeOnDeviceProfileChangeListener(this);
156             mActivity = null;
157             if (mSharedPrefs != null) {
158                 mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
159             }
160         }
161     }
162 
notifyChange()163     private void notifyChange() {
164         if (!mInitialized || mDestroyed) {
165             return;
166         }
167 
168         final int activityFlags;
169         if (mStateHandlerRequest != REQUEST_NONE) {
170             activityFlags = mStateHandlerRequest == REQUEST_LOCK ?
171                     SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
172         } else if (mCurrentTransitionRequest != REQUEST_NONE) {
173             activityFlags = mCurrentTransitionRequest == REQUEST_LOCK ?
174                     SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
175         } else if (mCurrentStateRequest == REQUEST_LOCK) {
176             activityFlags = SCREEN_ORIENTATION_LOCKED;
177         } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE
178                 || mHomeRotationEnabled || mForceAllowRotationForTesting) {
179             activityFlags = SCREEN_ORIENTATION_UNSPECIFIED;
180         } else {
181             // If auto rotation is off, allow rotation on the activity, in case the user is using
182             // forced rotation.
183             activityFlags = SCREEN_ORIENTATION_NOSENSOR;
184         }
185         if (activityFlags != mLastActivityFlags) {
186             mLastActivityFlags = activityFlags;
187             UiThreadHelper.setOrientationAsync(mActivity, activityFlags);
188         }
189     }
190 
191     /**
192      * @return how many factors {@param newRotation} is rotated 90 degrees clockwise.
193      * E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise...
194      * A value of 0 means no rotation has been applied
195      */
deltaRotation(int oldRotation, int newRotation)196     public static int deltaRotation(int oldRotation, int newRotation) {
197         int delta = newRotation - oldRotation;
198         if (delta < 0) delta += 4;
199         return delta;
200     }
201 
202     @Override
toString()203     public String toString() {
204         return String.format("[mStateHandlerRequest=%d, mCurrentStateRequest=%d, "
205                         + "mLastActivityFlags=%d, mIgnoreAutoRotateSettings=%b, "
206                         + "mHomeRotationEnabled=%b, mForceAllowRotationForTesting=%b]",
207                 mStateHandlerRequest, mCurrentStateRequest, mLastActivityFlags,
208                 mIgnoreAutoRotateSettings, mHomeRotationEnabled, mForceAllowRotationForTesting);
209     }
210 }
211