diff options
| author | Daniel Sandler <dsandler@google.com> | 2010-08-17 00:41:00 -0400 |
|---|---|---|
| committer | Daniel Sandler <dsandler@google.com> | 2010-11-04 16:55:29 -0400 |
| commit | b73617de462579f7c12c25a4c2747c576f00f6a2 (patch) | |
| tree | 1f070d8a32c97062feca491ed9675af8d7c874dc | |
| parent | 1ab022b8c8b063d95a591bf40109986c5b1bbb11 (diff) | |
| download | frameworks_base-b73617de462579f7c12c25a4c2747c576f00f6a2.zip frameworks_base-b73617de462579f7c12c25a4c2747c576f00f6a2.tar.gz frameworks_base-b73617de462579f7c12c25a4c2747c576f00f6a2.tar.bz2 | |
Rotation lock.
IWindowManager now supports two new methods,
freezeRotation() and thawRotation(), that allow a caller to
temporarily stash the device's current rotation as the
default rotation (when no other constraints are present).
The system bar uses this to implement a user-accessible
rotation lock by calling freezeRotation() and then turning
off accelerometer-based display rotation; unless overridden
by an app, the display will continue to appear in the frozen
rotation until the rotation is unlocked by the user (either
via the rotation lock icon in the system bar or by checking
"rotate screen automatically" in Settings).
Bug: 2949639
Change-Id: Icd21c169d1053719590e72401f229424b254622f
15 files changed, 234 insertions, 2 deletions
diff --git a/api/current.xml b/api/current.xml index c7cddac..9173afd 100644 --- a/api/current.xml +++ b/api/current.xml @@ -161089,6 +161089,17 @@ visibility="public" > </field> +<field name="USER_ROTATION" + type="java.lang.String" + transient="false" + volatile="false" + value=""user_rotation"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="USE_GOOGLE_MAIL" type="java.lang.String" transient="false" diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2229964..9c72dec 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1573,6 +1573,16 @@ public final class Settings { public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation"; /** + * Default screen rotation when no other policy applies. + * When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a + * preference, this rotation value will be used. Must be one of the + * {@link android.view.Surface#ROTATION_0 Surface rotation constants}. + * + * @see Display#getRotation + */ + public static final String USER_ROTATION = "user_rotation"; + + /** * Whether the audible DTMF tones are played by the dialer when dialing. The value is * boolean (1 or 0). */ @@ -1806,6 +1816,7 @@ public final class Settings { TIME_12_24, DATE_FORMAT, ACCELEROMETER_ROTATION, + USER_ROTATION, DTMF_TONE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING, EMERGENCY_TONE, diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index d4dd05c..a54f342 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -156,4 +156,17 @@ interface IWindowManager * calls back when it changes. */ int watchRotation(IRotationWatcher watcher); + + /** + * Lock the device orientation to the current rotation. Sensor input will + * be ignored until thawRotation() is called. + * @hide + */ + void freezeRotation(); + + /** + * Release the orientation lock imposed by freezeRotation(). + * @hide + */ + void thawRotation(); } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 1a341e1..e78d6a8 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -362,6 +362,13 @@ public interface WindowManagerPolicy { * modify the rotation. */ public final int USE_LAST_ROTATION = -1000; + + /** When not otherwise specified by the activity's screenOrientation, rotation should be + * determined by the system (that is, using sensors). */ + public final int USER_ROTATION_FREE = 0; + /** When not otherwise specified by the activity's screenOrientation, rotation is set by + * the user. */ + public final int USER_ROTATION_LOCKED = 1; /** * Perform initialization of the policy. @@ -787,4 +794,14 @@ public interface WindowManagerPolicy { * Return false to disable key repeat events from being generated. */ public boolean allowKeyRepeat(); + + /** + * Inform the policy that the user has chosen a preferred orientation ("rotation lock"). + * + * @param mode One of {@link WindowManagerPolicy#USER_ROTATION_LOCKED} or + * {@link * WindowManagerPolicy#USER_ROTATION_FREE}. + * @param rotation One of {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90}, + * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. + */ + public void setUserRotationMode(int mode, int rotation); } diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 8de507e..8a6e82d 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -103,4 +103,6 @@ 0x120016=0x03050601:0x03040501:0x03030401:0x03020301:0x03070301:0x03010301:0x03000301; </string> + <!-- Default for Settings.System.USER_ROTATION --> + <integer name="def_user_rotation">0</integer> </resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 9ac832b..593edc8 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -61,7 +61,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 59; + private static final int DATABASE_VERSION = 60; private Context mContext; @@ -775,6 +775,23 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 59; } + if (upgradeVersion == 59) { + // Persistence for the rotation lock feature. + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + stmt = db.compileStatement("INSERT INTO system(name,value)" + + " VALUES(?,?);"); + loadBooleanSetting(stmt, Settings.System.USER_ROTATION, + R.integer.def_user_rotation); // should be zero degrees + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) stmt.close(); + } + upgradeVersion = 60; + } + // *** Remember to update DATABASE_VERSION above! if (upgradeVersion != currentVersion) { diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-land-mdpi/ic_sysbar_rotate_off.png Binary files differindex adaadf7..adaadf7 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png +++ b/packages/SystemUI/res/drawable-land-mdpi/ic_sysbar_rotate_off.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off.png Binary files differnew file mode 100644 index 0000000..9e6793a --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-port-mdpi/ic_sysbar_rotate_off.png Binary files differindex fdc0ac7..fdc0ac7 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png +++ b/packages/SystemUI/res/drawable-port-mdpi/ic_sysbar_rotate_off.png diff --git a/packages/SystemUI/res/values-land/strings.xml b/packages/SystemUI/res/values-land/strings.xml new file mode 100644 index 0000000..e05e36b --- /dev/null +++ b/packages/SystemUI/res/values-land/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2010, 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. + */ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Rotation lock toast text: shown when rotation lock is turned on in landscape orientation. + --> + <string name="toast_rotation_locked">Screen is now locked in landscape orientation.</string> +</resources> diff --git a/packages/SystemUI/res/values-port/strings.xml b/packages/SystemUI/res/values-port/strings.xml new file mode 100644 index 0000000..d3ab67b --- /dev/null +++ b/packages/SystemUI/res/values-port/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2010, 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. + */ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Rotation lock toast text: shown when rotation lock is turned on in portrait orientation. + --> + <string name="toast_rotation_locked">Screen is now locked in portrait orientation.</string> +</resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 701aa9f..f34dc22 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -84,5 +84,11 @@ --> <string name="recent_tasks_empty">No recent applications.</string> + <!-- Rotation lock toast text: shown when rotation lock is turned off (and the screen will + auto-rotate based on the accelerometer). --> + <string name="toast_rotation_free">Screen will rotate automatically.</string> + <!-- Rotation lock toast text: shown when rotation lock is turned on and the orientation is + undefined. --> + <string name="toast_rotation_locked">Screen rotation is now locked.</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java index a0f5be6..b4a9d76 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java @@ -55,6 +55,7 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.IWindowManager; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.widget.Button; @@ -74,6 +75,8 @@ import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; import com.android.internal.telephony.cdma.TtyIntent; +import com.android.server.WindowManagerService; + import com.android.systemui.statusbar.*; import com.android.systemui.R; @@ -102,6 +105,8 @@ public class SystemPanel extends LinearLayout implements StatusBarPanel { private TextView mBatteryText; private TextView mSignalText; + private final IWindowManager mWM; + private final AudioManager mAudioManager; private final WifiManager mWifiManager; private final TelephonyManager mPhone; @@ -397,6 +402,11 @@ public class SystemPanel extends LinearLayout implements StatusBarPanel { public SystemPanel(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + // our mighty overlord + mWM = IWindowManager.Stub.asInterface( + ServiceManager.getService("window")); + + // get notified of phone state changes TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); @@ -437,6 +447,7 @@ public class SystemPanel extends LinearLayout implements StatusBarPanel { }); mSoundButton = (ImageButton)findViewById(R.id.sound); + mSoundButton.setAlpha(getSilentMode() ? 0x7F : 0xFF); mSoundButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { setSilentMode(!getSilentMode()); @@ -444,9 +455,22 @@ public class SystemPanel extends LinearLayout implements StatusBarPanel { } }); mOrientationButton = (ImageButton)findViewById(R.id.orientation); + mOrientationButton.setImageResource( + getAutoRotate() + ? R.drawable.ic_sysbar_rotate_on + : R.drawable.ic_sysbar_rotate_off); mOrientationButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - Toast.makeText(getContext(), "Orientation control not implemented; please adjust neck angle.", Toast.LENGTH_SHORT).show(); + setAutoRotate(!getAutoRotate()); + mOrientationButton.setImageResource( + getAutoRotate() + ? R.drawable.ic_sysbar_rotate_on + : R.drawable.ic_sysbar_rotate_off); + Toast.makeText(getContext(), + getAutoRotate() + ? R.string.toast_rotation_free + : R.string.toast_rotation_locked, + Toast.LENGTH_SHORT).show(); } }); @@ -709,4 +733,31 @@ public class SystemPanel extends LinearLayout implements StatusBarPanel { ? R.drawable.sysbar_toggle_bg_on : R.drawable.sysbar_toggle_bg_off); } + + void setAutoRotate(boolean rot) { + try { + ContentResolver cr = getContext().getContentResolver(); + if (rot) { + mWM.thawRotation(); + } else { + mWM.freezeRotation(); + } + } catch (android.os.RemoteException exc) { + } + } + + boolean getAutoRotate() { + ContentResolver cr = getContext().getContentResolver(); + return 1 == Settings.System.getInt(cr, + Settings.System.ACCELEROMETER_ROTATION, + 1); + } + + int getDisplayRotation() { + try { + return mWM.getRotation(); + } catch (android.os.RemoteException exc) { + return 0; + } + } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index af1bf59..2f2f943 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -230,6 +230,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidOpenRotation; int mCarDockRotation; int mDeskDockRotation; + + int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; + int mUserRotation = Surface.ROTATION_0; + boolean mCarDockEnablesAccelerometer; boolean mDeskDockEnablesAccelerometer; int mLidKeyboardAccessibility; @@ -336,6 +340,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.ACCELEROMETER_ROTATION), false, this); resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.USER_ROTATION), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_OFF_TIMEOUT), false, this); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.POINTER_LOCATION), false, this); @@ -678,10 +684,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { "fancy_rotation_anim", 0) != 0 ? 0x80 : 0; int accelerometerDefault = Settings.System.getInt(resolver, Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION); + + // set up rotation lock state + mUserRotationMode = (mAccelerometerDefault == 0) + ? WindowManagerPolicy.USER_ROTATION_LOCKED + : WindowManagerPolicy.USER_ROTATION_FREE; + mUserRotation = Settings.System.getInt(resolver, + Settings.System.USER_ROTATION, + Surface.ROTATION_0); + if (mAccelerometerDefault != accelerometerDefault) { mAccelerometerDefault = accelerometerDefault; updateOrientationListenerLp(); } + if (mSystemReady) { int pointerLocation = Settings.System.getInt(resolver, Settings.System.POINTER_LOCATION, 0); @@ -2280,6 +2296,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mCarDockRotation; } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { return mDeskDockRotation; + } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { + return mUserRotation; } else { if (useSensorForOrientationLp(orientation)) { return mOrientationListener.getCurrentRotation(lastRotation); @@ -2323,6 +2341,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation; } + + // User rotation: to be used when all else fails in assigning an orientation to the device + public void setUserRotationMode(int mode, int rot) { + ContentResolver res = mContext.getContentResolver(); + mUserRotationMode = mode; + if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { + mUserRotation = rot; + Settings.System.putInt(res, + Settings.System.ACCELEROMETER_ROTATION, + 0); + Settings.System.putInt(res, + Settings.System.USER_ROTATION, + rot); + } else { + Settings.System.putInt(res, + Settings.System.ACCELEROMETER_ROTATION, + 1); + } + } + public boolean detectSafeMode() { try { int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index dbc7f48..41b3da6 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -4842,6 +4842,26 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void freezeRotation() { + if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, + "setRotation()")) { + throw new SecurityException("Requires SET_ORIENTATION permission"); + } + + mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation); + setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); + } + + public void thawRotation() { + if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, + "setRotation()")) { + throw new SecurityException("Requires SET_ORIENTATION permission"); + } + + mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 0); + setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); + } + public void setRotation(int rotation, boolean alwaysSendConfiguration, int animFlags) { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, |
