| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.view; |
| |
| import android.content.Context; |
| import android.content.pm.PackageManager; |
| import android.content.res.Configuration; |
| import android.database.ContentObserver; |
| import android.net.Uri; |
| import android.os.AsyncTask; |
| import android.os.Handler; |
| import android.os.RemoteException; |
| import android.os.UserHandle; |
| import android.provider.Settings; |
| import android.util.DisplayMetrics; |
| import android.util.Log; |
| import android.view.IWindowManager; |
| import android.view.Surface; |
| import android.view.WindowManagerGlobal; |
| |
| import com.android.internal.R; |
| |
| /** |
| * Provides helper functions for configuring the display rotation policy. |
| */ |
| public final class RotationPolicy { |
| private static final String TAG = "RotationPolicy"; |
| private static final int CURRENT_ROTATION = -1; |
| |
| public static final int NATURAL_ROTATION = Surface.ROTATION_0; |
| |
| private RotationPolicy() { |
| } |
| |
| /** |
| * Gets whether the device supports rotation. In general such a |
| * device has an accelerometer and has the portrait and landscape |
| * features. |
| * |
| * @param context Context for accessing system resources. |
| * @return Whether the device supports rotation. |
| */ |
| public static boolean isRotationSupported(Context context) { |
| PackageManager pm = context.getPackageManager(); |
| return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER) |
| && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT) |
| && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE) |
| && context.getResources().getBoolean( |
| com.android.internal.R.bool.config_supportAutoRotation); |
| } |
| |
| /** |
| * Returns the orientation that will be used when locking the orientation from system UI |
| * with {@link #setRotationLock}. |
| * |
| * If the device only supports locking to its natural orientation, this will be either |
| * Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE, |
| * otherwise Configuration.ORIENTATION_UNDEFINED if any orientation is lockable. |
| */ |
| public static int getRotationLockOrientation(Context context) { |
| if (areAllRotationsAllowed(context)) { |
| return Configuration.ORIENTATION_UNDEFINED; |
| } |
| final DisplayMetrics metrics = context.getResources().getDisplayMetrics(); |
| final int rotation = |
| context.getResources().getConfiguration().windowConfiguration.getRotation(); |
| final boolean rotated = rotation % 2 != 0; |
| final int w = rotated ? metrics.heightPixels : metrics.widthPixels; |
| final int h = rotated ? metrics.widthPixels : metrics.heightPixels; |
| return w < h ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; |
| } |
| |
| /** |
| * Returns true if the rotation-lock toggle should be shown in system UI. |
| */ |
| public static boolean isRotationLockToggleVisible(Context context) { |
| return isRotationSupported(context) && |
| Settings.System.getIntForUser(context.getContentResolver(), |
| Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0, |
| UserHandle.USER_CURRENT) == 0; |
| } |
| |
| /** |
| * Returns true if rotation lock is enabled. |
| */ |
| public static boolean isRotationLocked(Context context) { |
| return Settings.System.getIntForUser(context.getContentResolver(), |
| Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0; |
| } |
| |
| /** |
| * Enables or disables rotation lock from the system UI toggle. |
| */ |
| public static void setRotationLock(Context context, final boolean enabled, String caller) { |
| final int rotation = areAllRotationsAllowed(context) |
| || useCurrentRotationOnRotationLockChange(context) ? CURRENT_ROTATION |
| : NATURAL_ROTATION; |
| setRotationLockAtAngle(context, enabled, rotation, caller); |
| } |
| |
| /** |
| * Enables or disables rotation lock at a specific rotation from system UI. |
| */ |
| public static void setRotationLockAtAngle(Context context, final boolean enabled, |
| final int rotation, String caller) { |
| Settings.System.putIntForUser(context.getContentResolver(), |
| Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0, |
| UserHandle.USER_CURRENT); |
| |
| setRotationLock(enabled, rotation, caller); |
| } |
| |
| /** |
| * Enables or disables natural rotation lock from Accessibility settings. |
| * |
| * If rotation is locked for accessibility, the system UI toggle is hidden to avoid confusion. |
| */ |
| public static void setRotationLockForAccessibility(Context context, final boolean enabled, |
| String caller) { |
| Settings.System.putIntForUser(context.getContentResolver(), |
| Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0, |
| UserHandle.USER_CURRENT); |
| |
| setRotationLock(enabled, NATURAL_ROTATION, caller); |
| } |
| |
| private static boolean areAllRotationsAllowed(Context context) { |
| return context.getResources().getBoolean(R.bool.config_allowAllRotations); |
| } |
| |
| private static boolean useCurrentRotationOnRotationLockChange(Context context) { |
| return context.getResources().getBoolean( |
| R.bool.config_useCurrentRotationOnRotationLockChange); |
| } |
| |
| private static void setRotationLock(final boolean enabled, final int rotation, |
| final String caller) { |
| AsyncTask.execute(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); |
| if (enabled) { |
| wm.freezeRotation(rotation, caller); |
| } else { |
| wm.thawRotation(caller); |
| } |
| } catch (RemoteException exc) { |
| Log.w(TAG, "Unable to save auto-rotate setting"); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Registers a listener for rotation policy changes affecting the caller's user |
| */ |
| public static void registerRotationPolicyListener(Context context, |
| RotationPolicyListener listener) { |
| registerRotationPolicyListener(context, listener, UserHandle.getCallingUserId()); |
| } |
| |
| /** |
| * Registers a listener for rotation policy changes affecting a specific user, |
| * or USER_ALL for all users. |
| */ |
| public static void registerRotationPolicyListener(Context context, |
| RotationPolicyListener listener, int userHandle) { |
| context.getContentResolver().registerContentObserver(Settings.System.getUriFor( |
| Settings.System.ACCELEROMETER_ROTATION), |
| false, listener.mObserver, userHandle); |
| context.getContentResolver().registerContentObserver(Settings.System.getUriFor( |
| Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY), |
| false, listener.mObserver, userHandle); |
| } |
| |
| /** |
| * Unregisters a listener for rotation policy changes. |
| */ |
| public static void unregisterRotationPolicyListener(Context context, |
| RotationPolicyListener listener) { |
| context.getContentResolver().unregisterContentObserver(listener.mObserver); |
| } |
| |
| /** |
| * Listener that is invoked whenever a change occurs that might affect the rotation policy. |
| */ |
| public static abstract class RotationPolicyListener { |
| final ContentObserver mObserver = new ContentObserver(new Handler()) { |
| @Override |
| public void onChange(boolean selfChange, Uri uri) { |
| RotationPolicyListener.this.onChange(); |
| } |
| }; |
| |
| public abstract void onChange(); |
| } |
| } |