am 89230e3b: am 458fc5f5: Merge "Fix issue #3041660: Camera image flips upside down when rotating device" into gingerbread

Merge commit '89230e3b7b9ec455373e3f60b62ff65589a9c57d'

* commit '89230e3b7b9ec455373e3f60b62ff65589a9c57d':
  Fix issue #3041660: Camera image flips upside down when rotating device
This commit is contained in:
Dianne Hackborn
2010-10-05 12:54:41 -07:00
committed by Android Git Automerger
6 changed files with 224 additions and 41 deletions

View File

@@ -55076,6 +55076,17 @@
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_FULL_SENSOR"
type="int"
transient="false"
volatile="false"
value="10"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_LANDSCAPE"
type="int"
transient="false"
@@ -55109,6 +55120,28 @@
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_REVERSE_LANDSCAPE"
type="int"
transient="false"
volatile="false"
value="8"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_REVERSE_PORTRAIT"
type="int"
transient="false"
volatile="false"
value="9"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_SENSOR"
type="int"
transient="false"
@@ -55120,6 +55153,28 @@
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_SENSOR_LANDSCAPE"
type="int"
transient="false"
volatile="false"
value="6"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_SENSOR_PORTRAIT"
type="int"
transient="false"
volatile="false"
value="7"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SCREEN_ORIENTATION_UNSPECIFIED"
type="int"
transient="false"

View File

@@ -216,10 +216,41 @@ public class ActivityInfo extends ComponentInfo
public static final int SCREEN_ORIENTATION_SENSOR = 4;
/**
* Constant corresponding to <code>sensor</code> in
* Constant corresponding to <code>nosensor</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_NOSENSOR = 5;
/**
* Constant corresponding to <code>sensorLandscape</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6;
/**
* Constant corresponding to <code>sensorPortrait</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7;
/**
* Constant corresponding to <code>reverseLandscape</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
/**
* Constant corresponding to <code>reversePortrait</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;
/**
* Constant corresponding to <code>fullSensor</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10;
/**
* The preferred screen orientation this activity would like to run in.
* From the {@link android.R.attr#screenOrientation} attribute, one of
@@ -229,7 +260,12 @@ public class ActivityInfo extends ComponentInfo
* {@link #SCREEN_ORIENTATION_USER},
* {@link #SCREEN_ORIENTATION_BEHIND},
* {@link #SCREEN_ORIENTATION_SENSOR},
* {@link #SCREEN_ORIENTATION_NOSENSOR}.
* {@link #SCREEN_ORIENTATION_NOSENSOR},
* {@link #SCREEN_ORIENTATION_SENSOR_LANDSCAPE},
* {@link #SCREEN_ORIENTATION_SENSOR_PORTRAIT},
* {@link #SCREEN_ORIENTATION_REVERSE_LANDSCAPE},
* {@link #SCREEN_ORIENTATION_REVERSE_PORTRAIT},
* {@link #SCREEN_ORIENTATION_FULL_SENSOR}.
*/
public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;

View File

@@ -28,6 +28,11 @@ import android.util.Log;
* A special helper class used by the WindowManager
* for receiving notifications from the SensorManager when
* the orientation of the device has changed.
*
* NOTE: If changing anything here, please run the API demo
* "App/Activity/Screen Orientation" to ensure that all orientation
* modes still work correctly.
*
* @hide
*/
public abstract class WindowOrientationListener {
@@ -103,6 +108,10 @@ public abstract class WindowOrientationListener {
}
}
public void setAllow180Rotation(boolean allowed) {
mSensorEventListener.setAllow180Rotation(allowed);
}
public int getCurrentRotation(int lastRotation) {
if (mEnabled) {
return mSensorEventListener.getCurrentRotation(lastRotation);
@@ -151,19 +160,20 @@ public abstract class WindowOrientationListener {
private static final int ROTATION_0 = 0;
private static final int ROTATION_90 = 1;
private static final int ROTATION_270 = 2;
private static final int ROTATION_180 = 3;
// Mapping our internal aliases into actual Surface rotation values
private static final int[] INTERNAL_TO_SURFACE_ROTATION = new int[] {
Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270,
Surface.ROTATION_180};
// Mapping Surface rotation values to internal aliases.
// We have no constant for Surface.ROTATION_180. That should never happen, but if it
// does, we'll arbitrarily choose a mapping.
private static final int[] SURFACE_TO_INTERNAL_ROTATION = new int[] {
ROTATION_0, ROTATION_90, ROTATION_90, ROTATION_270};
ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270};
// Threshold ranges of orientation angle to transition into other orientation states.
// The first list is for transitions from ROTATION_0, the next for ROTATION_90, etc.
// The first list is for transitions from ROTATION_0, ROTATION_90, ROTATION_270,
// and then ROTATION_180.
// ROTATE_TO defines the orientation each threshold range transitions to, and must be kept
// in sync with this.
// We generally transition about the halfway point between two states with a swing of 30
@@ -172,13 +182,32 @@ public abstract class WindowOrientationListener {
{{60, 180}, {180, 300}},
{{0, 30}, {195, 315}, {315, 360}},
{{0, 45}, {45, 165}, {330, 360}},
};
// Handle situation where we are currently doing 180 rotation
// but that is no longer allowed.
{{0, 45}, {45, 135}, {135, 225}, {225, 315}, {315, 360}},
};
// See THRESHOLDS
private static final int[][] ROTATE_TO = new int[][] {
{ROTATION_90, ROTATION_270},
{ROTATION_0, ROTATION_270, ROTATION_0},
{ROTATION_0, ROTATION_90, ROTATION_0},
{ROTATION_0, ROTATION_90, ROTATION_0, ROTATION_270, ROTATION_0},
};
// Thresholds that allow all 4 orientations.
private static final int[][][] THRESHOLDS_WITH_180 = new int[][][] {
{{60, 165}, {165, 195}, {195, 300}},
{{0, 30}, {165, 195}, {195, 315}, {315, 360}},
{{0, 45}, {45, 165}, {165, 195}, {330, 360}},
{{0, 45}, {45, 135}, {225, 315}, {315, 360}},
};
// See THRESHOLDS_WITH_180
private static final int[][] ROTATE_TO_WITH_180 = new int[][] {
{ROTATION_90, ROTATION_180, ROTATION_270},
{ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0},
{ROTATION_0, ROTATION_270, ROTATION_180, ROTATION_0},
{ROTATION_0, ROTATION_90, ROTATION_270, ROTATION_0},
};
// Maximum absolute tilt angle at which to consider orientation data. Beyond this (i.e.
@@ -188,7 +217,7 @@ public abstract class WindowOrientationListener {
// Additional limits on tilt angle to transition to each new orientation. We ignore all
// data with tilt beyond MAX_TILT, but we can set stricter limits on transitions to a
// particular orientation here.
private static final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, 65, 65};
private static final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, 65, 65, 40};
// Between this tilt angle and MAX_TILT, we'll allow orientation changes, but we'll filter
// with a higher time constant, making us less sensitive to change. This primarily helps
@@ -228,6 +257,8 @@ public abstract class WindowOrientationListener {
private static final float ACCELERATING_LOWPASS_ALPHA =
computeLowpassAlpha(ACCELERATING_TIME_CONSTANT_MS);
private boolean mAllow180Rotation = false;
private WindowOrientationListener mOrientationListener;
private int mRotation = ROTATION_0; // Current orientation state
private float mTiltAngle = 0; // low-pass filtered
@@ -249,6 +280,10 @@ public abstract class WindowOrientationListener {
return (float) SAMPLING_PERIOD_MS / (timeConstantMs + SAMPLING_PERIOD_MS);
}
void setAllow180Rotation(boolean allowed) {
mAllow180Rotation = allowed;
}
int getCurrentRotation(int lastRotation) {
if (mTiltDistrust > 0) {
// we really don't know the current orientation, so trust what's currently displayed
@@ -259,7 +294,9 @@ public abstract class WindowOrientationListener {
private void calculateNewRotation(float orientation, float tiltAngle) {
if (localLOGV) Log.i(TAG, orientation + ", " + tiltAngle + ", " + mRotation);
int thresholdRanges[][] = THRESHOLDS[mRotation];
final boolean allow180Rotation = mAllow180Rotation;
int thresholdRanges[][] = allow180Rotation
? THRESHOLDS_WITH_180[mRotation] : THRESHOLDS[mRotation];
int row = -1;
for (int i = 0; i < thresholdRanges.length; i++) {
if (orientation >= thresholdRanges[i][0] && orientation < thresholdRanges[i][1]) {
@@ -269,13 +306,15 @@ public abstract class WindowOrientationListener {
}
if (row == -1) return; // no matching transition
int rotation = ROTATE_TO[mRotation][row];
int rotation = allow180Rotation
? ROTATE_TO_WITH_180[mRotation][row] : ROTATE_TO[mRotation][row];
if (tiltAngle > MAX_TRANSITION_TILT[rotation]) {
// tilted too far flat to go to this rotation
return;
}
if (localLOGV) Log.i(TAG, " new rotation = " + rotation);
if (localLOGV) Log.i(TAG, "orientation " + orientation + " gives new rotation = "
+ rotation);
mRotation = rotation;
mOrientationListener.onOrientationChanged(INTERNAL_TO_SURFACE_ROTATION[mRotation]);
}

View File

@@ -497,10 +497,10 @@
orientation will changed based on how the user rotates the device -->
<enum name="unspecified" value="-1" />
<!-- Would like to have the screen in a landscape orientation: that
is, with the display wider than it is tall. -->
is, with the display wider than it is tall, ignoring sensor data. -->
<enum name="landscape" value="0" />
<!-- Would like to have the screen in a portrait orientation: that
is, with the display taller than it is wide. -->
is, with the display taller than it is wide, ignoring sensor data. -->
<enum name="portrait" value="1" />
<!-- Use the user's current preferred orientation of the handset. -->
<enum name="user" value="2" />
@@ -513,6 +513,24 @@
<!-- Always ignore orientation determined by orientation sensor:
the display will not rotate when the user moves the device. -->
<enum name="nosensor" value="5" />
<!-- Would like to have the screen in landscape orientation, but can
use the sensor to change which direction the screen is facing. -->
<enum name="sensorLandscape" value="6" />
<!-- Would like to have the screen in portrait orientation, but can
use the sensor to change which direction the screen is facing. -->
<enum name="sensorPortait" value="7" />
<!-- Would like to have the screen in landscape orientation, turned in
the opposite direction from normal landscape. -->
<enum name="reverseLandscape" value="8" />
<!-- Would like to have the screen in portrait orientation, turned in
the opposite direction from normal portrait. -->
<enum name="reversePortait" value="9" />
<!-- Orientation is determined by a physical orientation sensor:
the display will rotate based on how the user moves the device.
This allows any of the 4 possible rotations, regardless of what
the device will normally do (for example some devices won't
normally use 180 degree rotation). -->
<enum name="fullSensor" value="10" />
</attr>
<!-- Specify one or more configuration changes that the activity will

View File

@@ -296,7 +296,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLandscapeRotation = -1; // default landscape rotation
int mSeascapeRotation = -1; // "other" landscape rotation, 180 degrees from mLandscapeRotation
int mPortraitRotation = -1;
int mPortraitRotation = -1; // default portrait rotation
int mUpsideDownRotation = -1; // "other" portrait rotation
// Nothing to see here, move along...
int mFancyRotationAnimation;
@@ -364,26 +365,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean useSensorForOrientationLp(int appOrientation) {
// The app says use the sensor.
if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
return true;
}
// The user preference says we can rotate, and the app is willing to rotate.
// Note we include SCREEN_ORIENTATION_LANDSCAPE since we can use the sensor to choose
// between the two possible landscape rotations.
if (mAccelerometerDefault != 0 &&
(appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
return true;
}
// We're in a dock that has a rotation affinity, an the app is willing to rotate.
// We're in a dock that has a rotation affinity, and the app is willing to rotate.
if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR)
|| (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) {
// Note we override the nosensor flag here.
if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
return true;
}
}
@@ -397,7 +397,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* screen is switched off.
*/
boolean needSensorRunningLp() {
if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
// If the application has explicitly requested to follow the
// orientation, then we need to turn the sensor or.
return true;
@@ -2133,21 +2136,42 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (d.getWidth() > d.getHeight()) {
mPortraitRotation = Surface.ROTATION_90;
mLandscapeRotation = Surface.ROTATION_0;
mUpsideDownRotation = Surface.ROTATION_270;
mSeascapeRotation = Surface.ROTATION_180;
} else {
mPortraitRotation = Surface.ROTATION_0;
mLandscapeRotation = Surface.ROTATION_90;
mUpsideDownRotation = Surface.ROTATION_180;
mSeascapeRotation = Surface.ROTATION_270;
}
}
synchronized (mLock) {
if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
//always return portrait if orientation set to portrait
return mPortraitRotation;
} else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
return getCurrentLandscapeRotation(lastRotation);
switch (orientation) {
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
//always return portrait if orientation set to portrait
return mPortraitRotation;
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
//always return landscape if orientation set to landscape
return mLandscapeRotation;
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
//always return portrait if orientation set to portrait
return mUpsideDownRotation;
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
//always return seascape if orientation set to reverse landscape
return mSeascapeRotation;
case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
//return either landscape rotation based on the sensor
mOrientationListener.setAllow180Rotation(false);
return getCurrentLandscapeRotation(lastRotation);
case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
mOrientationListener.setAllow180Rotation(true);
return getCurrentPortraitRotation(lastRotation);
}
mOrientationListener.setAllow180Rotation(
orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
// case for nosensor meaning ignore sensor and consider only lid
// or orientation sensor disabled
//or case.unspecified
@@ -2167,18 +2191,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private int getCurrentLandscapeRotation(int lastRotation) {
// landscape-only apps can take either landscape rotation
if (useSensorForOrientationLp(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
if (isLandscapeOrSeascape(sensorRotation)) {
return sensorRotation;
}
int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
if (isLandscapeOrSeascape(sensorRotation)) {
return sensorRotation;
}
// try to preserve the old rotation if it was landscape
if (isLandscapeOrSeascape(lastRotation)) {
return lastRotation;
}
// default to one of the two landscape rotations
// default to one of the primary landscape rotation
return mLandscapeRotation;
}
@@ -2186,6 +2207,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation;
}
private int getCurrentPortraitRotation(int lastRotation) {
int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
if (isAnyPortrait(sensorRotation)) {
return sensorRotation;
}
// try to preserve the old rotation if it was portrait
if (isAnyPortrait(lastRotation)) {
return lastRotation;
}
// default to one of the primary portrait rotations
return mPortraitRotation;
}
private boolean isAnyPortrait(int sensorRotation) {
return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation;
}
public boolean detectSafeMode() {
try {
int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);

View File

@@ -3387,11 +3387,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
// If this application has requested an explicit orientation,
// then use it.
if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
or == ActivityInfo.SCREEN_ORIENTATION_USER) {
if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
&& or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
return or;
}
findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);