From b73617de462579f7c12c25a4c2747c576f00f6a2 Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Tue, 17 Aug 2010 00:41:00 -0400 Subject: [PATCH] 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 --- api/current.xml | 11 ++++ core/java/android/provider/Settings.java | 11 ++++ core/java/android/view/IWindowManager.aidl | 13 +++++ .../android/view/WindowManagerPolicy.java | 17 ++++++ .../SettingsProvider/res/values/defaults.xml | 2 + .../providers/settings/DatabaseHelper.java | 19 ++++++- .../ic_sysbar_rotate_off.png} | Bin .../drawable-mdpi/ic_sysbar_rotate_off.png | Bin 0 -> 548 bytes .../ic_sysbar_rotate_off.png} | Bin packages/SystemUI/res/values-land/strings.xml | 23 ++++++++ packages/SystemUI/res/values-port/strings.xml | 23 ++++++++ packages/SystemUI/res/values/strings.xml | 6 ++ .../statusbar/tablet/SystemPanel.java | 53 +++++++++++++++++- .../policy/impl/PhoneWindowManager.java | 38 +++++++++++++ .../android/server/WindowManagerService.java | 20 +++++++ 15 files changed, 234 insertions(+), 2 deletions(-) rename packages/SystemUI/res/{drawable-mdpi/ic_sysbar_rotate_off_lanscape.png => drawable-land-mdpi/ic_sysbar_rotate_off.png} (100%) create mode 100644 packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off.png rename packages/SystemUI/res/{drawable-mdpi/ic_sysbar_rotate_off_portrait.png => drawable-port-mdpi/ic_sysbar_rotate_off.png} (100%) create mode 100644 packages/SystemUI/res/values-land/strings.xml create mode 100644 packages/SystemUI/res/values-port/strings.xml diff --git a/api/current.xml b/api/current.xml index c7cddac27f1b5..9173afd5339d8 100644 --- a/api/current.xml +++ b/api/current.xml @@ -161089,6 +161089,17 @@ visibility="public" > + + + + 0 diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 9ac832b31e7b7..593edc8865913 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 similarity index 100% rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png rename to 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 new file mode 100644 index 0000000000000000000000000000000000000000..9e6793ad434a5a773b93885682f824382844dca4 GIT binary patch literal 548 zcmV+<0^9wGP)e5nEh?SFc8H_=>Mb}WCQ2~WdW3I&~$>b0qF+apmc&# zSRfk|CTN(TbO1nYt@W0GAvK0b3i>|~`rujtrXT|exFm@U)_Po6N1DI}@kv!x zC76P{ZnwLt$>9@kx7&UghLYT45CoA4A7gVfw=zx@fY^Xjg>Vn#^ZESgFBZnXz^7;Y zq$=_#ZOr;$6CNC~A25UX8;V}FkvCx({;!}WEQzH1Tb^(wkH!g))1y>@V<_PC6%sl$IN51uTX0 z7IyX(@TP=rbdCy0n*~HJ+?^U*Ns>rQB{l?BSZSB!{Am^D+OI~)b5r~tKn|>i(@PBb z`^Kq#`aSP$e%+TNl;w8!7wk3;y z>u^p0ayh3=cDr4MjUbkR0rR~9X-THQZ@O44UiNM}EPNyoasIbf`Diq{u6fbuU88nc muhpsos(>n>3aA3U6!-)kdzKbi<%aG60000 + + + + Screen is now locked in landscape orientation. + diff --git a/packages/SystemUI/res/values-port/strings.xml b/packages/SystemUI/res/values-port/strings.xml new file mode 100644 index 0000000000000..d3ab67bb7863c --- /dev/null +++ b/packages/SystemUI/res/values-port/strings.xml @@ -0,0 +1,23 @@ + + + + + Screen is now locked in portrait orientation. + diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 701aa9ff15066..f34dc22a449d7 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -84,5 +84,11 @@ --> No recent applications. + + Screen will rotate automatically. + + Screen rotation is now locked. 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 a0f5be635ecca..b4a9d760cbe42 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 af1bf59c26f73..2f2f943401596 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; @@ -335,6 +339,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this); 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( @@ -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 dbc7f480ce49c..41b3da681cf74 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,