Home | History | Annotate | Download | only in states
      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