blob: 9fefd00c6d30c250e951849728bc7e7c16340669 [file] [log] [blame]
Jeff Brown207673cd2012-06-05 17:47:11 -07001/*
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
17package com.android.internal.view;
18
19import android.content.Context;
Svetoslav79578b22013-04-29 16:55:57 -070020import android.content.pm.PackageManager;
John Spurlock8ab172e2013-12-19 16:39:23 -050021import android.content.res.Configuration;
Jeff Brown207673cd2012-06-05 17:47:11 -070022import android.database.ContentObserver;
John Spurlock8ab172e2013-12-19 16:39:23 -050023import android.graphics.Point;
Jeff Brown207673cd2012-06-05 17:47:11 -070024import android.net.Uri;
25import android.os.AsyncTask;
26import android.os.Handler;
27import android.os.RemoteException;
Christopher Tate5e08af02012-09-21 17:17:22 -070028import android.os.UserHandle;
Jeff Brown207673cd2012-06-05 17:47:11 -070029import android.provider.Settings;
30import android.util.Log;
John Spurlock8ab172e2013-12-19 16:39:23 -050031import android.view.Display;
Jeff Brown207673cd2012-06-05 17:47:11 -070032import android.view.IWindowManager;
33import android.view.Surface;
Jeff Brown98365d72012-08-19 20:30:52 -070034import android.view.WindowManagerGlobal;
Jeff Brown207673cd2012-06-05 17:47:11 -070035
John Spurlock8ab172e2013-12-19 16:39:23 -050036import com.android.internal.R;
37
Jeff Brown207673cd2012-06-05 17:47:11 -070038/**
39 * Provides helper functions for configuring the display rotation policy.
40 */
41public final class RotationPolicy {
42 private static final String TAG = "RotationPolicy";
John Spurlock8ab172e2013-12-19 16:39:23 -050043 private static final int CURRENT_ROTATION = -1;
44 private static final int NATURAL_ROTATION = Surface.ROTATION_0;
Jeff Brown207673cd2012-06-05 17:47:11 -070045
46 private RotationPolicy() {
47 }
48
49 /**
Svetoslav79578b22013-04-29 16:55:57 -070050 * Gets whether the device supports rotation. In general such a
51 * device has an accelerometer and has the portrait and landscape
52 * features.
53 *
54 * @param context Context for accessing system resources.
55 * @return Whether the device supports rotation.
56 */
57 public static boolean isRotationSupported(Context context) {
58 PackageManager pm = context.getPackageManager();
59 return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)
60 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
61 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
62 }
63
64 /**
John Spurlock8ab172e2013-12-19 16:39:23 -050065 * Returns the orientation that will be used when locking the orientation from system UI
66 * with {@link #setRotationLock}.
Jeff Brown207673cd2012-06-05 17:47:11 -070067 *
John Spurlock8ab172e2013-12-19 16:39:23 -050068 * If the device only supports locking to its natural orientation, this will be either
69 * Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE,
70 * otherwise Configuration.ORIENTATION_UNDEFINED if any orientation is lockable.
Jeff Brown207673cd2012-06-05 17:47:11 -070071 */
John Spurlock8ab172e2013-12-19 16:39:23 -050072 public static int getRotationLockOrientation(Context context) {
73 if (!areAllRotationsAllowed(context)) {
74 final Point size = new Point();
75 final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
76 try {
77 wm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, size);
78 return size.x < size.y ?
79 Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
80 } catch (RemoteException e) {
81 Log.w(TAG, "Unable to get the display size");
82 }
83 }
84 return Configuration.ORIENTATION_UNDEFINED;
Jeff Brown207673cd2012-06-05 17:47:11 -070085 }
86
87 /**
John Spurlock8ab172e2013-12-19 16:39:23 -050088 * Returns true if the rotation-lock toggle should be shown in system UI.
Jeff Brown207673cd2012-06-05 17:47:11 -070089 */
90 public static boolean isRotationLockToggleVisible(Context context) {
John Spurlock8ab172e2013-12-19 16:39:23 -050091 return isRotationSupported(context) &&
Christopher Tate5e08af02012-09-21 17:17:22 -070092 Settings.System.getIntForUser(context.getContentResolver(),
93 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
94 UserHandle.USER_CURRENT) == 0;
Jeff Brown207673cd2012-06-05 17:47:11 -070095 }
96
97 /**
98 * Returns true if rotation lock is enabled.
99 */
100 public static boolean isRotationLocked(Context context) {
Christopher Tate5e08af02012-09-21 17:17:22 -0700101 return Settings.System.getIntForUser(context.getContentResolver(),
102 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
Jeff Brown207673cd2012-06-05 17:47:11 -0700103 }
104
105 /**
John Spurlock8ab172e2013-12-19 16:39:23 -0500106 * Enables or disables rotation lock from the system UI toggle.
Jeff Brown207673cd2012-06-05 17:47:11 -0700107 */
108 public static void setRotationLock(Context context, final boolean enabled) {
Christopher Tate5e08af02012-09-21 17:17:22 -0700109 Settings.System.putIntForUser(context.getContentResolver(),
110 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
111 UserHandle.USER_CURRENT);
Jeff Brown207673cd2012-06-05 17:47:11 -0700112
John Spurlock8ab172e2013-12-19 16:39:23 -0500113 final int rotation = areAllRotationsAllowed(context) ? CURRENT_ROTATION : NATURAL_ROTATION;
114 setRotationLock(enabled, rotation);
Jeff Brown207673cd2012-06-05 17:47:11 -0700115 }
116
117 /**
John Spurlock8ab172e2013-12-19 16:39:23 -0500118 * Enables or disables natural rotation lock from Accessibility settings.
Jeff Brown207673cd2012-06-05 17:47:11 -0700119 *
John Spurlock8ab172e2013-12-19 16:39:23 -0500120 * If rotation is locked for accessibility, the system UI toggle is hidden to avoid confusion.
Jeff Brown207673cd2012-06-05 17:47:11 -0700121 */
122 public static void setRotationLockForAccessibility(Context context, final boolean enabled) {
Christopher Tate5e08af02012-09-21 17:17:22 -0700123 Settings.System.putIntForUser(context.getContentResolver(),
124 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0,
125 UserHandle.USER_CURRENT);
Jeff Brown207673cd2012-06-05 17:47:11 -0700126
John Spurlock8ab172e2013-12-19 16:39:23 -0500127 setRotationLock(enabled, NATURAL_ROTATION);
128 }
129
130 private static boolean areAllRotationsAllowed(Context context) {
131 return context.getResources().getBoolean(R.bool.config_allowAllRotations);
132 }
133
134 private static void setRotationLock(final boolean enabled, final int rotation) {
Jeff Brown207673cd2012-06-05 17:47:11 -0700135 AsyncTask.execute(new Runnable() {
136 @Override
137 public void run() {
138 try {
Jeff Brown98365d72012-08-19 20:30:52 -0700139 IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
Jeff Brown207673cd2012-06-05 17:47:11 -0700140 if (enabled) {
John Spurlock8ab172e2013-12-19 16:39:23 -0500141 wm.freezeRotation(rotation);
Jeff Brown207673cd2012-06-05 17:47:11 -0700142 } else {
143 wm.thawRotation();
144 }
145 } catch (RemoteException exc) {
146 Log.w(TAG, "Unable to save auto-rotate setting");
147 }
148 }
149 });
150 }
151
152 /**
Christopher Tate5e08af02012-09-21 17:17:22 -0700153 * Registers a listener for rotation policy changes affecting the caller's user
Jeff Brown207673cd2012-06-05 17:47:11 -0700154 */
155 public static void registerRotationPolicyListener(Context context,
156 RotationPolicyListener listener) {
Christopher Tate5e08af02012-09-21 17:17:22 -0700157 registerRotationPolicyListener(context, listener, UserHandle.getCallingUserId());
158 }
159
160 /**
161 * Registers a listener for rotation policy changes affecting a specific user,
162 * or USER_ALL for all users.
163 */
164 public static void registerRotationPolicyListener(Context context,
165 RotationPolicyListener listener, int userHandle) {
Jeff Brown207673cd2012-06-05 17:47:11 -0700166 context.getContentResolver().registerContentObserver(Settings.System.getUriFor(
167 Settings.System.ACCELEROMETER_ROTATION),
Christopher Tate5e08af02012-09-21 17:17:22 -0700168 false, listener.mObserver, userHandle);
Jeff Brown207673cd2012-06-05 17:47:11 -0700169 context.getContentResolver().registerContentObserver(Settings.System.getUriFor(
170 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY),
Christopher Tate5e08af02012-09-21 17:17:22 -0700171 false, listener.mObserver, userHandle);
Jeff Brown207673cd2012-06-05 17:47:11 -0700172 }
173
174 /**
175 * Unregisters a listener for rotation policy changes.
176 */
177 public static void unregisterRotationPolicyListener(Context context,
178 RotationPolicyListener listener) {
179 context.getContentResolver().unregisterContentObserver(listener.mObserver);
180 }
181
182 /**
183 * Listener that is invoked whenever a change occurs that might affect the rotation policy.
184 */
185 public static abstract class RotationPolicyListener {
186 final ContentObserver mObserver = new ContentObserver(new Handler()) {
187 public void onChange(boolean selfChange, Uri uri) {
188 RotationPolicyListener.this.onChange();
189 }
190 };
191
192 public abstract void onChange();
193 }
194}