diff options
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, |