1 /* 2 * Copyright (C) 2012 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.internal.view; 18 19 import android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.database.ContentObserver; 22 import android.net.Uri; 23 import android.os.AsyncTask; 24 import android.os.Build; 25 import android.os.Handler; 26 import android.os.RemoteException; 27 import android.os.UserHandle; 28 import android.provider.Settings; 29 import android.util.Log; 30 import android.view.IWindowManager; 31 import android.view.Surface; 32 import android.view.WindowManagerGlobal; 33 34 /** 35 * Provides helper functions for configuring the display rotation policy. 36 */ 37 public final class RotationPolicy { 38 private static final String TAG = "RotationPolicy"; 39 40 private RotationPolicy() { 41 } 42 43 /** 44 * Gets whether the device supports rotation. In general such a 45 * device has an accelerometer and has the portrait and landscape 46 * features. 47 * 48 * @param context Context for accessing system resources. 49 * @return Whether the device supports rotation. 50 */ 51 public static boolean isRotationSupported(Context context) { 52 PackageManager pm = context.getPackageManager(); 53 return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER) 54 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT) 55 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE); 56 } 57 58 /** 59 * Returns true if the device supports the rotation-lock toggle feature 60 * in the system UI or system bar. 61 * 62 * When the rotation-lock toggle is supported, the "auto-rotate screen" option in 63 * Display settings should be hidden, but it should remain available in Accessibility 64 * settings. 65 */ 66 public static boolean isRotationLockToggleSupported(Context context) { 67 return isRotationSupported(context) 68 && context.getResources().getConfiguration().smallestScreenWidthDp >= 600; 69 } 70 71 /** 72 * Returns true if the rotation-lock toggle should be shown in the UI. 73 */ 74 public static boolean isRotationLockToggleVisible(Context context) { 75 return isRotationLockToggleSupported(context) && 76 Settings.System.getIntForUser(context.getContentResolver(), 77 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0, 78 UserHandle.USER_CURRENT) == 0; 79 } 80 81 /** 82 * Returns true if rotation lock is enabled. 83 */ 84 public static boolean isRotationLocked(Context context) { 85 return Settings.System.getIntForUser(context.getContentResolver(), 86 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0; 87 } 88 89 /** 90 * Enables or disables rotation lock. 91 * 92 * Should be used by the rotation lock toggle. 93 */ 94 public static void setRotationLock(Context context, final boolean enabled) { 95 Settings.System.putIntForUser(context.getContentResolver(), 96 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0, 97 UserHandle.USER_CURRENT); 98 99 AsyncTask.execute(new Runnable() { 100 @Override 101 public void run() { 102 try { 103 IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); 104 if (enabled) { 105 wm.freezeRotation(-1); 106 } else { 107 wm.thawRotation(); 108 } 109 } catch (RemoteException exc) { 110 Log.w(TAG, "Unable to save auto-rotate setting"); 111 } 112 } 113 }); 114 } 115 116 /** 117 * Enables or disables rotation lock and adjusts whether the rotation lock toggle 118 * should be hidden for accessibility purposes. 119 * 120 * Should be used by Display settings and Accessibility settings. 121 */ 122 public static void setRotationLockForAccessibility(Context context, final boolean enabled) { 123 Settings.System.putIntForUser(context.getContentResolver(), 124 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0, 125 UserHandle.USER_CURRENT); 126 127 AsyncTask.execute(new Runnable() { 128 @Override 129 public void run() { 130 try { 131 IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); 132 if (enabled) { 133 wm.freezeRotation(Surface.ROTATION_0); 134 } else { 135 wm.thawRotation(); 136 } 137 } catch (RemoteException exc) { 138 Log.w(TAG, "Unable to save auto-rotate setting"); 139 } 140 } 141 }); 142 } 143 144 /** 145 * Registers a listener for rotation policy changes affecting the caller's user 146 */ 147 public static void registerRotationPolicyListener(Context context, 148 RotationPolicyListener listener) { 149 registerRotationPolicyListener(context, listener, UserHandle.getCallingUserId()); 150 } 151 152 /** 153 * Registers a listener for rotation policy changes affecting a specific user, 154 * or USER_ALL for all users. 155 */ 156 public static void registerRotationPolicyListener(Context context, 157 RotationPolicyListener listener, int userHandle) { 158 context.getContentResolver().registerContentObserver(Settings.System.getUriFor( 159 Settings.System.ACCELEROMETER_ROTATION), 160 false, listener.mObserver, userHandle); 161 context.getContentResolver().registerContentObserver(Settings.System.getUriFor( 162 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY), 163 false, listener.mObserver, userHandle); 164 } 165 166 /** 167 * Unregisters a listener for rotation policy changes. 168 */ 169 public static void unregisterRotationPolicyListener(Context context, 170 RotationPolicyListener listener) { 171 context.getContentResolver().unregisterContentObserver(listener.mObserver); 172 } 173 174 /** 175 * Listener that is invoked whenever a change occurs that might affect the rotation policy. 176 */ 177 public static abstract class RotationPolicyListener { 178 final ContentObserver mObserver = new ContentObserver(new Handler()) { 179 public void onChange(boolean selfChange, Uri uri) { 180 RotationPolicyListener.this.onChange(); 181 } 182 }; 183 184 public abstract void onChange(); 185 } 186 }