您的位置:首页 > 其它

sensor工作流程

2012-02-29 15:30 176 查看
编写本文的目的是为何第三方软件uc浏览器8.2.2版在我们的设备上安装后是竖屏(portrait)显示的,而不是我们想要的横屏显示(landscape)。我反编译了这个apk里的AndroidManifest.xml,发现和屏幕方向相关的代码:android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
在这里设定了默认方向为portrait(竖屏)显示的,而configChanges属性是在设备有gsensor时有反应的,如果没有gsensor就是默认的方向显示。在Activity里有重写了
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
…...
}
这样是对屏幕方向改变时做相应的反应。这样做的好处是不会导致Acivity重启,即关闭一个Acitivity又创建一个Activity,会导致onDestroy,onCreate等事件的发生,因而屏幕切换可能会导致与Acitivity
状态相关的应用出错。如果你设置了这个选项, 当手机旋转后,当前 Activity 之后调用onConfigurationChanged() 方法. 而不跑 onCreate 方法等.
整体框架如下:





其中在frameworks里又关联了几个重要的类,比如,Configuration.java在frameworks/base/core/java/android/content/res下这里定义了常量:
public static final int ORIENTATION_UNDEFINED = 0;
public static final int ORIENTATION_PORTRAIT = 1;
public static final int ORIENTATION_LANDSCAPE = 2;
public static final int ORIENTATION_SQUARE = 3;
这些常量就是屏幕方向。
这个类实现了Parcelable, Comparable<Configuration>接口。在Parcelable.java接口里有public void writeToParcel(Parcel dest, int flags);
* Specific orientation value for a window.
* May be any of the same values allowed
* for {@link android.content.pm.ActivityInfo#screenOrientation}.
* If not set, a default value of
* {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}
* will be used.
*/
public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
看英文注释这是默认的屏幕方向值。
然后在这个类的
public void writeToParcel(Parcel out, int parcelableFlags) {
….
out.writeInt(screenOrientation);//往Parcel读 screenOrientation
}
public LayoutParams(Parcel in) {
….
screenOrientation = in.readInt();//在 Parcel读 screenOrientation
}
public final int copyFrom(LayoutParams o) {
int changes = 0;
…..
if (screenOrientation != o.screenOrientation) {
screenOrientation = o.screenOrientation;
changes |= SCREEN_ORIENTATION_CHANGED;
return changes;
}

刚才有发现了 screenOrientation的默认值为ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED。我在追综到 ActivityInfo这个类里,发现;了定义几个屏幕方向的几个常量,这些常量是在AndroidManifest.xml里各个应用主界面activity的屏幕方向的:
/**
* Options that have been set in the activity declaration in the
* manifest: {@link #FLAG_MULTIPROCESS},
* {@link #FLAG_FINISH_ON_TASK_LAUNCH}, {@link #FLAG_CLEAR_TASK_ON_LAUNCH},
* {@link #FLAG_ALWAYS_RETAIN_TASK_STATE},
* {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS},
* {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY},
* {@link #FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS}.
*/
public int flags;

/**
* Constant corresponding to <code>unspecified</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_UNSPECIFIED = -1;
/**
* Constant corresponding to <code>landscape</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_LANDSCAPE = 0;
/**
* Constant corresponding to <code>portrait</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_PORTRAIT = 1;
/**
* Constant corresponding to <code>user</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_USER = 2;
/**
* Constant corresponding to <code>behind</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_BEHIND = 3;
/**
* Constant corresponding to <code>sensor</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_SENSOR = 4;

/**
* Constant corresponding to <code>sensor</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_NOSENSOR = 5;
/**
* The preferred screen orientation this activity would like to run in.
* From the {@link android.R.attr#screenOrientation} attribute, one of
* {@link #SCREEN_ORIENTATION_UNSPECIFIED},
* {@link #SCREEN_ORIENTATION_LANDSCAPE},
* {@link #SCREEN_ORIENTATION_PORTRAIT},
* {@link #SCREEN_ORIENTATION_USER},
* {@link #SCREEN_ORIENTATION_BEHIND},
* {@link #SCREEN_ORIENTATION_SENSOR},
* {@link #SCREEN_ORIENTATION_NOSENSOR}.
*/
public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;

ActivityInfo.java也实现了Parcelable接口,说明也能往里面读和写屏幕方向。
在与ActivityInfo.java同目录(frameworks/base/core/java/android/content/pm)下有AcitivityInfo.aidl在这里只封装了parcelable ActivityInfo;。
那么现在只有一条线索去追踪屏幕方向切换的实现原理和流程了。那就是WindowManager.java相关的类。我们知道WindowManager.java是给上层调用的服务,所以我发现了IWindowManager.aidl在相同目录下(frameworks/base/core/java/android/view).

系统启动windowManger.java时,它会启动phoneWindowManager.java,该类有一个内部类myOrientationListener扩展自windowOrientationListener.java。
windowOrientationListener.java是一个辅助类,当device的方向发生变化时,供windowManger.java调用,用来接收数据。
windowOrientationListener.java 内部在sensorManger.java中进行了注册,它回监听G-sensor传来的数据,即x,y,z方向的加速度,收到数据后经过转换处理,若满足Roate条件则调用
IwindowManager接口的实现类windowManagerService.java中的setRotation()方法实现转屏。

SensorManager通过polling的方式从设备得到Sensor数据, Sensor数据的结构定义在sensor.h里,
其中SensorManager只处理了 vector.v, vector.status, time三个域, 分发给已注册的对这些消息的监听者

比如第一项 vector.v包含x,y,z三个方向的信息值,就是由 WindowOrientataionLister注册的,
当 SensorManager获取到这三个值之后,会传递给 WindowOrientataionLister,后者代码位于:
frameworkd/base/core/java/android/view/WindowOrientationListener.java
WindowOrientataionLister接收到这三个值之后,会计算出设备对应的orientation,并且执行 onOrientationChanged函数进一步上传

WindowOrientataionLister是个纯虚类,如果在APK里需要控制方向,可以重载一个实例,
而Android的系统实例对应在 PhoneWindowManager.java里,名字为MyOrientationListener
frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java

如果需要旋转, MyOrientationListener则会调用以下代码进行窗口旋转:
mWindowManager.setRotation(rotation, false, mFancyRotationAnimation);

现在追踪到SensorManager.java在目录frameworks/base/core/java/android/hardware下,同目录下有
ISensorservice.aidl,因为在SensorManager.java类里有:
public SensorManager(Looper mainLooper) {
mSensorService = ISensorService.Stub.asInterface(
ServiceManager.getService(Context.SENSOR_SERVICE));
…..
}
在frameworks/base/services/java/com/android/server下有SensorService.java.这个类是通过JNI方法调用HAL层的Sensor.cpp里的方法,对硬件实现初始化和控制。

在frameworks/base/core/jni/android_hardware_SensorManager.cpp和frameworks/base/services/jni/com_android_server_SensorService.cpp中都
#include <hardware/sensors.h>
在这个头文件中我发现#define SENSOR_TYPE_ORIENTATION         3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: