横屏 竖屏 代码流程
来源:互联网 发布:盛一伦非凡搭档知乎 编辑:程序博客网 时间:2024/06/05 08:48
[Android移植] 关于android2.3调试g-sensor(2012-02-21 16:11:17)
it
android由于工作上的需要,特地写了这么一份关于调试g-sensor的内容.
1.首先确定你要调试的设备的屏幕的横竖屏如何设置。
在代码中我们主要的流程如下:
os 启动后 :
WindowManagerService.java中ENABLE_SCREEN
–>performEnableScreen()
–>mPolicy.enableScreenAfterBoot()/setRotation()
–>setRotationUnchecked()
–>PhoneWindowManager.java中的rotationForOrientationLw
–>Surface.setOrientation()
基本上流程就是如上,只要稍微跟踪一下就可以了。
下面大概对上面主要code进行注释说明:
- //下面的方法主要用于判断屏幕是否需要进行一个新的旋转
- public boolean setRotationUncheckedLock
ed(int rotation, int animFlags) { -
boolean changed; - //rotation从外面传入当前的rotation以及animFlags 最后的标签
- //如果rotation等于系统第一次启动则rotation赋值为mRequestedRotation此时为0
-
if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) { -
rotation = mRequestedRotation; -
} else { -
mRequestedRotation = rotation; -
mLastRotationFlags = animFlags; -
} -
if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation); - //此时的rotation为老的rotation,下面通过mPolicy.rotationForOrientationLw
()进行获取新的rotation -
rotation = mPolicy.rotationForOrientationLw (mForcedAppOrientation, -
mRotation, mDisplayEnabled); -
if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation); -
changed = mDisplayEnabled && mRotation != rotation; - //如果获取新的rotation与旧的rotation一样则不做改变
- //否则进入下面函数进行调整
-
if (changed) { -
if (DEBUG_ORIENTATION) Slog.v(TAG, -
"Rotation changed to " + rotation -
+ " from " + mRotation -
+ " (forceApp=" + mForcedAppOrientation -
+ ", req=" + mRequestedRotation + ")"); -
mRotation = rotation; -
mWindowsFreezingScreen = true; -
mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); -
mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), -
2000); -
mWaitingForConfig = true; -
mLayoutNeeded = true; -
startFreezingDisplayLock ed(); -
Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); -
mInputManager.setDisplayOrientation(0, rotation); -
if (mDisplayEnabled) { - //Surface.setOrientation()这里将进行调整Orientation
-
Surface.setOrientation(0, rotation, animFlags); -
} -
for (int i=mWindows.size()-1; i>=0; i--) { -
WindowState w = mWindows.get(i); -
if (w.mSurface != null) { -
w.mOrientationChanging = true; -
} -
} -
for (int i=mRotationWatchers.size()-1; i>=0; i--) { -
try { -
mRotationWatchers.get(i).onRotationChanged(rotation); -
} catch (RemoteException e) { -
} -
} -
} //end if changed -
return changed; -
}
下面在对rotationForOrientationLw
在setRotationUncheckedLock
- otationForOrientationLw(int orientation, int lastRotation,
-
boolean displayEnabled) { -
if (mPortraitRotation < 0) { -
// Initialize the rotation angles for each orientation once. -
Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) -
.getDefaultDisplay(); - //这里的d.getWidth() 和 d.getHeight()得到的是物理屏幕的宽高。
- //平板跟手机不一样。平板的宽比高大
- //(0度时位于//landscape模式,右转90度进入porit模式),
- //而手机是高比宽大(0度是位于porit模式,右转90度进入landscape模式)。
- //所以下面我做的是对平板的修改
-
if (d.getWidth() > d.getHeight()) { -
//mPortraitRotation = Surface.ROTATION_90; -
mPortraitRotation = Surface.ROTATION_270; -
mLandscapeRotation = Surface.ROTATION_0; -
//mUpsideDownRotation = Surface.ROTATION_270; -
mUpsideDownRotation = Surface.ROTATION_90; -
mSeascapeRotation = Surface.ROTATION_180; -
} else { -
mPortraitRotation = Surface.ROTATION_0; -
//mLandscapeRotation = Surface.ROTATION_90; -
mLandscapeRotation = Surface.ROTATION_270; -
mUpsideDownRotation = Surface.ROTATION_180; -
//mSeascapeRotation = Surface.ROTATION_270; -
mSeascapeRotation = Surface.ROTATION_90; -
} -
} - ......
- }
2.如果g-sensor在旋转上有不旋转的方向或者方向不是很灵敏,则我们从下面进行分析:
主要流程如下:
–>WindowOrientationListene
–>computeNewOrientation()
–>filterOrientation()
–>calculateNewRotation()
calculateNewRotation()
–>mOrientationListener.onOrientationChanged()
PhoneWindowManager.java 中的onOrientationChanged()
–>mWindowManager.setRotation()
首先在android中的x,y,z定义如下摘自http://developer.android.com/ref ... re/SensorEvent.html :
Class Overview
This class represents a Sensor event and holds informations such as the sensor’s type, the time-stamp, accuracy and of course the sensor’s data.
Definition of the coordinate system used by the SensorEvent API.
The coordinate-system is defined relative to the screen of the phone in its default orientation. The axes are not swapped when the device’s screen orientation changes.
The X axis is horizontal and points to the right, the Y axis is vertical and points up and the Z axis points towards the outside of the front face of the screen. In this system, coordinates behind the screen have negative Z values.
Sensors coordinate-system diagram.
Note: This coordinate system is different from the one used in the Android 2D APIs where the origin is in the top-left corner.
frameworks/base/core/java/android/view/WindowOrientationListene
WindowOrientationListene
每次sensor有进行改变时都会调用到以下函数进行计算Orientation。
- public void onSensorChanged(SensorEvent event) {
-
// the vector given in the SensorEvent points straight up (towards the sky) under ideal -
// conditions (the phone is not accelerating). i'll call this upVector elsewhere. -
float x = event.values[_DATA_X]; -
float y = event.values[_DATA_Y]; -
float z = event.values[_DATA_Z]; -
float magnitude = vectorMagnitude(x, y, z); -
float deviation = Math.abs(magnitude - SensorManager.STANDARD_GRAVITY); -
handleAccelerationDistru st(deviation); -
// only filter tilt when we're accelerating -
float alpha = 1; -
if (mAccelerationDistrust > 0) { -
alpha = ACCELERATING_LOWPASS_ALPHA; -
} -
float newTiltAngle = tiltAngle(z, magnitude); -
mTiltAngle = lowpassFilter(newTiltAngle, mTiltAngle, alpha); -
float absoluteTilt = Math.abs(mTiltAngle); -
checkFullyTilted(absoluteTilt); -
if (mTiltDistrust > 0) { -
return; // when fully tilted, ignore orientation entirely -
} - //下面通过x,y计算得到新的OrientationAngle,计算方法如下
- //
private float computeNewOrientation(float x, float y) { - //
float orientationAngle = (float) -Math.atan2(-x, y) * RADIANS_TO_DEGREES; -
// atan2 returns [-180, 180]; normalize to [0, 360] - //
if (orientationAngle < 0) { - //
orientationAngle += 360; - //
} - //
return orientationAngle; - //
} -
float newOrientationAngle = computeNewOrientation(x, y); - //通过下面函数计算出Orientation的值。
-
filterOrientation(absoluteTilt, newOrientationAngle); -
calculateNewRotation(mOrientationAngle, absoluteTilt); -
}
这里对calculateNewRotation进行分析前必须先对SensorEventListenerImpl类中的一些变量先进行解释:
- private static final int[][][] THRESHOLDS = new int[][][] {
- {{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},
- };
- 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}},
- };
- 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},
- };
- //当设备平放,屏幕朝正上方。以下四个常量分别代表:
- 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;//屏幕底部侧立时,屏幕会旋转到这个方向
- //如上则
- // {ROTATION_90, ROTATION_180, ROTATION_270}
- //对应落在的范围为 {{60, 165}, {165, 195}, {195, 300}}
- //{ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0}
- //对应落在的范围为 {{0, 30}, {165, 195}, {195, 315}, {315, 360}}
- //{ROTATION_0, ROTATION_270, ROTATION_180, ROTATION_0}
- //对应落在的范围为 {{0, 45}, {45, 165}, {165, 195}, {330, 360}}
- //{ROTATION_0, ROTATION_90, ROTATION_270, ROTATION_0}
- //对应落在的范围为{{0, 45}, {45, 135}, {225, 315}, {315, 360}}
- //所以如果需要微调的话只要修改对应的范围既可
- //当前屏幕旋转方向为ROTATION_0时,取int[][] threshold=THRESHOLDS_WITH_180[0];
- //此时的范围为:{{60, 165}, {165, 195}, {195, 300}}
- //当前屏幕旋转方向为ROTATION_90时,取int[][] threshold=THRESHOLDS_WITH_180[1];
- //此时的范围为:{{0, 30}, {165, 195}, {195, 315}, {315, 360}}
- //当前屏幕旋转方向为ROTATION_270时,取int[][] threshold=THRESHOLDS_WITH_180[2];
- //此时的范围为:{{0, 45}, {45, 165}, {165, 195}, {330, 360}}
- //当前屏幕旋转方向为ROTATION_180时,取int[][] threshold=THRESHOLDS_WITH_180[3];
- //此时的范围为:{{0, 45}, {45, 135}, {225, 315}, {315, 360}}
- //例如当前我们的位置为ROTATION_90那么此时我们的THRESHOLDS_WITH_180就
- //为{{0, 30}, {165, 195}, {195, 315}, {315, 360}}
- //,然后通过filterOrientation计算出的orientation值落在了第2个元素围内,则到ROTATE_TO_WITH_180找到对应的值,
- //这里为ROTATION_180,则此时把方向选装到ROTATION_180
对上面的变量稍微了解后对下面的分析就很简单了。
- private void calculateNewRotation(float orientation, float tiltAngle) {
- //这里的orientation,tiltAngle,mRotation为gsensor获取到的最新的数据
-
if (localLOGV) Log.i(TAG, orientation + ", " + tiltAngle + ", " + mRotation); - //是否允许180度旋转,这里定义的其实就是变成了360度旋转了,
- //如果mAllow180Rotation为false时,上面的变量中使用的为THRESHOLDS以及ROTATE_TO
- //如果为ture则为THRESHOLDS_WITH_180与ROTATE_TO_WITH_180
-
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]) { -
row = i; -
break; -
} -
} -
if (row == -1) return; // no matching transition -
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, "orientation " + orientation + " gives new rotation = " -
+ rotation); -
mRotation = rotation; - //这里通过WindowOrientationListene
r监听调用onOrientationChanged中的setRotation从而旋转界面 -
mOrientationListener.onOrientationChanged(INTERNAL_TO_SURFACE_ROTATION[mRotation]); -
}
onOrientationChanged()的实现在PhoneWindowManager.java 中,如下:
- class MyOrientationListener extends WindowOrientationListene
r { -
MyOrientationListener(Context context) { -
super(context); -
} -
@Override -
public void onOrientationChanged(int rotation) { -
// Send updates based on orientation value -
if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation); -
try { -
mWindowManager.setRotation(rotation, false, -
mFancyRotationAnimation); -
SystemProperties.set("service.screen.rotation", ""+rotation); -
} catch (RemoteException e) { -
// Ignore -
} -
} -
}
基本上整个流程到此结束。
转载时请注明出处和作者
文章出处:http://www.code007.org/
作者:Code007
- 横屏 竖屏 代码流程
- Eboot代码流程 [转]
- Eboot代码流程
- Eboot代码流程
- Eboot代码流程
- Eboot代码流程
- Eboot代码流程
- SVN代码提交流程
- SVN代码提交流程
- 代码启动Windchill流程
- Sensor 代码流程分析
- android boot 代码流程
- 代码提交流程经验总结
- 代码执行流程
- NFC代码流程
- android boot 代码流程
- Sensor 代码流程分析
- FBReaderJ流程(代码层面)
- 邮件客户端
- 一次性输入多条记录
- 关于Linq
- 数组乘积--满足result[i] = input数组中除了input[i]之外所有数的乘积
- 处理c语言的命令行参数
- 横屏 竖屏 代码流程
- Ehcache 集群示例系列1:RMI manual方式(手动发现方式)
- VMWare启动速度过快导致无法按F2进入BIOS解决方法
- Linux C语言连接MySQL 增删改查操作
- 神奇的图像处理算法
- 给ZENCART的产品增加新字段
- xcode设置字体
- 学习使用ucosii
- php sql 防注入