rotation的判断cdn是否生效怎么不生效

2598人阅读
Android Framework
Android(8)
Android&系统屏幕旋转调研
本文档是在全志A33平台&Android&系统中,关于屏幕旋转方面的技术调研。
2015年4月14日
决定屏幕方向有两个层面,一个是&Linux&内核层的&FB&方向(这里暂不深入),驱动上做的修改,另一个是&Android&OS&上的修改。
在&Linux&内核初始化以后,init进程启动,紧接着启动了Zygote。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引&导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android&SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。
如上图,Zygote启动以后,初始化了&System.Settings,开始了SystemUI&和&Settings&的进程、监听屏幕旋转机制和传感器管理器。当来自&SystemUI&或者&Settings&对&System.Settings&数据库的设置生效,监听屏幕旋转机制就打开,开始读取来由自底层设备驱动经过HAL经过JNI到传感器管理器的数据,对屏幕进行旋转设置。
最终实现状态栏的快速设置功能是在&SystemUI&上。所以先从&SystemUI&入手。
Android&4.4,是由&Google&公司制作和研发的代号为&KitKat&的手机操作系统,于北京时间&2013&年&9&月&4&日凌晨对外公布了该&Android&新版本的名称,为&Android&4.4&(代号&KitKat&奇巧)。
Android&4.4&同时适用于Phone和Tablet(TV),因此,对于&Phone&来说&SystemUI&指的是:StatusBar(状态栏)、&NavigationBar(导航栏)。而对于&Tablet&或者是&TV&来说&SystemUI&指的是:CombinedBar(包括了&StatusBar&和&NavigationBar)。
Android&的&Phone&的信号,蓝牙标志,Wifi&标志等等这些状态显示标志都会在&StatusBar&上显示。当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的&SystemUI,因此对于整个&Android&系统来说,SystemUI&都有举足轻重的作用。
1.1.2.1.从AndroidManifest.xml开始
在&Android&4.4&中,Google&整合了&Phone&和&Tablet(TV)&的&SystemUI,也就说可以根据设备的类型自动匹配相应的&SystemUI。首先从&AndroidManifest.xml&入手。
&!--&Wifi&Display&--&
&uses-permission&android:name=&android.permission.CONFIGURE_WIFI_DISPLAY&&/&
&uses-permission&android:name=&android.permission.ACCESS_SURFACE_FLINGER&&/&
&uses-permission&android:name=&android.permission.RECORD_AUDIO&&/&
&uses-permission&android:name=&android.permission.CAPTURE_AUDIO_OUTPUT&&/&
&application
android:persistent=&true&
android:allowClearUserData=&false&
android:allowBackup=&false&
android:hardwareAccelerated=&true&
android:label=&@string/app_label&
android:icon=&@*android:drawable/platlogo&
android:process=&com.android.systemui&
android:supportsRtl=&true&&
&!--&Broadcast&receiver&that&gets&the&broadcast&at&boot&time&and&starts
up&everything&else.
TODO:&Should&have&an&android:permission&attribute
&service&android:name=&SystemUIService&
android:exported=&true&
&!--&started&from&PhoneWindowManager
TODO:&Should&have&an&android:permission&attribute&--&
&service&android:name=&.screenshot.TakeScreenshotService&
android:process=&:screenshot&
android:exported=&false&&/&
&service&android:name=&.LoadAverageService&
android:exported=&true&&/&
&service&android:name=&.ImageWallpaper&
android:permission=&android.permission.BIND_WALLPAPER&
android:exported=&true&&/&
根据以上代码我们可以发现这其中注册了很多&Service,同时也包括了广播。但这里我们只关注&SystemUIService。首先要找到&SystemUIService&是如何启动的。Service&的启动,不外乎&startService(intent)&和&bindService(intent),它们都是以&intent&为对象,由于&intent&的声明也需要&SystemUIService,因此我们可以据此搜索关键词&SystemUIService&。
1.1.2.2.SystemUIService分析
经过搜索发现:
frameworks/base/services/java/com/android/server/SystemServer.java
static&final&void&startSystemUi(Context&context)&{
Intent&intent&=&new&Intent();
intent.setComponent(new&ComponentName(&com.android.systemui&,
&com.android.systemui.SystemUIService&));
//Slog.d(TAG,&&Starting&service:&&&+&intent);
context.startServiceAsUser(intent,&UserHandle.OWNER);
这部分是开始了&SystemUI,可以确认下面代码是上面服务的具体实现:
frameworks/base/packages/systemui/src/com/android/systemui/SystemUIService.java&
public&class&SystemUIService&extends&Service&{
&&&&private&static&final&String&TAG&=&&SystemUIService&;
&&&&&*&The&classes&of&the&stuff&to&start.
&&&&private&final&Class&?&[]&SERVICES&=&new&Class[]&{
&&&&&&&&&&&&com.android.systemui.recent.Recents.class,
&&&&&&&&&&&&com.android.systemui.statusbar.SystemBars.class,
&&&&&&&&&&&&com.android.systemui.usb.StorageNotification.class,
&&&&&&&&&&&&com.android.systemui.power.PowerUI.class,
&&&&&&&&&&&&com.android.systemui.media.RingtonePlayer.class,
&&&&&&&&&&&&com.android.systemui.settings.SettingsUI.class,
&&&&&*&Hold&a&reference&on&the&stuff&we&start.
&&&&private&final&SystemUI[]&mServices&=&new&SystemUI[SERVICES.length];
&&&&@Override
&&&&public&void&onCreate()&{
&&&&&&&&HashMap&Class&?&,&Object&&components&=&
&&&&&&&&&&&&new&HashMap&Class&?&,&Object&();
&&&&&&&&final&int&N&=&SERVICES.
&&&&&&&&for&(int&i=0;&i&N;&i++)&{
&&&&&&&&&&&&Class&?&&cl&=&SERVICES[i];
&&&&&&&&&&&&Log.d(TAG,&&loading:&&&+&cl);
&&&&&&&&&&&&try&{
&&&&&&&&&&&&&&&&mServices[i]&=&(SystemUI)cl.newInstance();
&&&&&&&&&&&&}&catch&(IllegalAccessException&ex)&{
&&&&&&&&&&&&&&&&throw&new&RuntimeException(ex);
&&&&&&&&&&&&}&catch&(InstantiationException&ex)&{
&&&&&&&&&&&&&&&&throw&new&RuntimeException(ex);
&&&&&&&&&&&&}
&&&&&&&&&&&&mServices[i].mContext&=&
&&&&&&&&&&&&mServices[i].mComponents&=&
&&&&&&&&&&&&Log.d(TAG,&&running:&&&+&mServices[i]);
&&&&&&&&&&&&mServices[i].start();
这里初始化了以下类
Recent(最近打开程序)
com.android.systemui.recent.Recents.class
Statusbar(状态栏)
com.android.systemui.statusbar.SystemBars.class
USBStorageNotification(USB存储设备通知) com.android.systemui.usb.StorageNotification.class
com.android.systemui.power.PowerUI.class
RingtonePlayer
com.android.systemui.media.RingtonePlayer.class
SettingsUI(设置界面)
com.android.systemui.settings.SettingsUI.class
4.0以前版本,这里都是整合在一起的,4.4这里开始分离出来,分一个个模块。以后若是针对某个模块分析,在这里开始了分支。
1.1.2.3.Statusbar分析
接下来重点是&Statusbar(状态栏),这个类构建在:
/frameworks/base/packages/systemui/src/com/android/systemui/statusbar/SystemBars.java&分析得出接下来调用了frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
//&创建一个快速设置菜单QuickSettings的实例&
QuickSettings&mQS;
mQS&=&new&QuickSettings(mContext,&mSettingsContainer);
类原型来自:
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/QuickSettings.java&
这里出现了关键代码,添加删除下拉快速设置可以模仿如下内容添加:
//&声明下文所需的RotationLockController类
private&RotationLockController&mRotationLockC
//&声明下文所需的QuickSettingsModel&类
private&QuickSettingsModel&mM
//&R.bool.quick_settings_show_rotation_lock&作为一个配置设置项
//&位于frameworks/base/packages/systemui/res/value/Config.xml提供了原始的设置
//&由于自适应机制,这里真正调用的是
//&位于frameworks/base/packages/systemui/res/values-sw600dp/Config.xml
//&类似的按钮也可以在这里设置是否需要显示
//&DEBUG_GONE_TILES设置调试时屏蔽选项
//&这里作为旋转屏幕部分的开始,用了两个配置项做约束条件
if&(mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)||&DEBUG_GONE_TILES)&{
&&&&&&&&//&QuickSettingsBasicTile&提供了监听按钮是否按下的方法。
&&&&&&&&//&原型位于:
&&&&&&&&//&frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/QuickSettingsBasicTile.java&
&&&&&&&&//&新建快速设置的按钮,这里新建了一个按钮的对象
final&QuickSettingsBasicTile&rotationLockTile
=&new&QuickSettingsBasicTile(mContext);
&&&&&&&&//&设置按钮的Listenter,用于监听按钮是否被按下
rotationLockTile.setOnClickListener(new&View.OnClickListener()&{
&&&&&&&&&&
&&&&&&&&&&//&这里开始创建按钮按下的方法
&&&&&&public&void&onClick(View&view)&{
&&&&&&&&&&&&&&//&声明了一个locked变量用来表示屏幕当前的锁定状态
&&&&&&&&&&&&&&//&取值自isRotationLocked&方法,该方法提供获取屏幕的锁定状态
&&&&&&&&&&&&&&//&详见
&&&&&&final&boolean&locked&=&
&&&&&&&&&&&&&&&&&&&&&&&&mRotationLockController.isRotationLocked();
&&&&&&&&&&&&&&//&调用了RotationLockController.setRotationLocked方法
&&&&&&&&&&&&&&//&该方法提供提供了设置了设置屏幕旋转锁定与否的功能
&&&&&&&&&&&&&&//&如果传入的参数,即locked的值
&&&&&&&&&&&&&&//&为true,则锁定屏幕旋转
&&&&&&&&&&&&&&//&为false,则解锁屏幕旋转
&&&&&&&&&&&&&&//&这里locked取反,使得每次按下按钮时,锁定、解锁状态相互切换
&&&&&&&&&&&&&&//&详见&
&&mRotationLockController.setRotationLocked(!locked);
&&&&&&&&//&addRotationLockTile是由QuickSettingsModel提供的方法
&&&&&&&&//&用来设置旋转按钮上面标签、图标的变化。
&&&&&&&&//&rotationLockTile&、mRotationLockController&两个类的上下文传入该方法
&&&&&&&&//&并创建了刷新的回调函数
&&&&&&&&//&详见&
mModel.addRotationLockTile(rotationLockTile,&mRotationLockController,
new&QuickSettingsModel.RefreshCallback()&{
&&&&&&&&&&&&&&&&//&QuickSettingsTileView&提供了设置按钮各种显示相关的方法和参数
&&&&&&&&&&&&&&&&//&State&在QuickSettingsModel中实现
&&&&&&&&&&&&&&&&//&static&class&State&{
&&&&&&&&&&&&&&&&//&&&&&int&iconId;
&&&&&&&&&&&&&&&&//&&&&&String&
&&&&&&&&&&&&&&&&//&&&&&boolean&enabled&=&
&&&&&&&&&&&&&&&&//&}
&&&&&&&&&&&&&&&&//&作为父类,其生成了很多用于各种设置的子类
&&&&&&&&&&&&&&&&//&其中有QuickSettingsModel.RotationLockState
&&&&&&&&&&&&&&&&//&实现刷新界面的方法,当按钮发生改变的时候
&&&&&&&&&&&&&&&&//&这里被调用到用于刷新按钮上的图标和标签
public&void&refreshView(QuickSettingsTileView&view,&State&state) {
&&&&&&&&&&&&&&&&&&&&&&&&//&声明rotationLockState&用于存储当前屏幕锁定状态
&&&&&&&&&&&&&&&&&&&&&&&&//&从传参得到的state
&&&&&&&&&&&&&&&&&&&&&&&&//&强制转换成QuickSettingsModel.RotationLockState
&&&&&&&&&&&&&&&&&&&&&&&&//&并将其赋值给rotationLockState&
QuickSettingsModel.RotationLockState&rotationLockState&=
(QuickSettingsModel.RotationLockState)&
&&&&&&&&&&&&&&&&&&&&&&&&//&Visibility的三个属性
&&&&&&&&&&&&&&&&&&&&&&&&//&VISIBLE:设置控件可见
&&&&&&&&&&&&&&&&&&&&&&&&//&INVISIBLE:设置控件不可见
&&&&&&&&&&&&&&&&&&&&&&&&//&GONE:设置控件隐藏
&&&&&&&&&&&&&&&&&&&&&&&&//&而INVISIBLE和GONE的主要区别是:
&&&&&&&&&&&&&&&&&&&&&&&&//&当控件visibility属性为INVISIBLE时,
&&&&&&&&&&&&&&&&&&&&&&&&//&界面保留了view控件所占有的空间;
&&&&&&&&&&&&&&&&&&&&&&&&//&而控件属性为GONE时,界面则不保留view控件所占有的空间。
&&&&&&&&&&&&&&&&&&&&&&&&//&这里设置当rotationLockState.visible
&&&&&&&&&&&&&&&&&&&&&&&&//&为true,往view.setVisibility传入View.VISIBLE
&&&&&&&&&&&&&&&&&&&&&&&&//&为false,则传入View.GONE
view.setVisibility(rotationLockState.visible ?&View.VISIBLE&:&View.GONE);
&&&&&&&&&&&&&&&&&&&&&&&&//&检测图标状态设置是否存在,是的话
&&&&&&&&&&&&&&&&&&&&&&&&if&(state.iconId&!=&0)&{
//&首先清空已有的图标
&&&&&&&&&&&&&&&&& rotationLockTile.setImageDrawable(null);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//&设置图标
rotationLockTile.setImageResource(state.iconId); }
&&&&&&&&&&&&&&&&&&&&&&&&//&检测标签状态设置是否存在,是的话
&&&&&&&&&&&&&&&&&&&&&&&&if&(state.label&!=&null)&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//&设置标签
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&rotationLockTile.setText(state.label);
&&&&&&&&//&传入了按钮的句柄,把该按钮加入并显示出来
&&&&&&&&//&详见&
parent.addView(rotationLockTile);
用于判断屏幕旋转是否处于锁定状态
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/policy/RotationLockController.java
public&boolean&isRotationLocked()&{
&&&&&&&&&//&如果旋转开关被支持则调用RotationPolicy.isRotationLocked
&&&&&&&&&//&用来返回屏幕旋转锁定状态
&&&&&&&&&//&详见&
&&&&&&&&&if&(RotationPolicy.isRotationLockToggleSupported(mContext))&{
&&&&&&&&&&&&&&&&&return&RotationPolicy.isRotationLocked(mContext);
&&&&&&&&&}
&&&&&&&&&return&
用于判断屏幕旋转是否处于锁定状态
frameworks/base/core/java/com/android/internal/view/RotationPolicy.java
public&static&boolean&isRotationLocked(Context&context)&{
&&&&&&&&return&Settings.System.getIntForUser(
&&&&&&&&&&&&&&&&&&&&&&context.getContentResolver(),
&&&&&&&&&&&&&&&&&&&&&&Settings.System.ACCELEROMETER_ROTATION,
&&&&&&&&&&&&&&&&&&&&&&0,
&&&&&&&&&&&&&&&&&&&&&&UserHandle.USER_CURRENT)&==&0;
//&这里调用了返回系统API&Settings.System.getIntForUser读取系统设置
//&读取了ACCELEROMETER_ROTATION的值
//&ACCELEROMETER_ROTATION&是&Settings.System&的一个键值,
//&决定了是否使用加速度计控制屏幕旋转角度。
1.1.2.3.2.分析RotationLockController.setRotationLocked方法
用于设置屏幕旋转是否处于锁定状态
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/policy/RotationLockController.java
public&void&setRotationLocked(boolean&locked)&{
&&&&&&&&//&如果旋转开关被支持则返回RotationPolicy.isRotationLocked
&&&&&&&&//&用于判断屏幕选装是否锁定
&&&&&&&&//&详见&
&&&&&&&&if&(RotationPolicy.isRotationLockToggleSupported(mContext))&{
&&&&&&&&&&&&&&&&RotationPolicy.setRotationLock(mContext,&locked);
1.1.2.3.2.1.分析RotationLockController.setRotationLocked方法
用于设置屏幕锁定与否
frameworks/base/core/java/com/android/internal/view/RotationPolicy.java
public&static&void&setRotationLock(Context&context,&final&boolean&enabled)&{
&&&&&&&&//&向&Settings.System.&写入HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY
&&&&&&&&//&如果0,那么不隐藏旋转锁切换的可访问性(尽管它可能因其他原因不可用)。
&&&&&&&&//&如果1,那么旋转锁切换隐藏。
&&&&&&&&Settings.System.putIntForUser(
&&&&&&&&&&&&&&&&context.getContentResolver(),
&&&&&&&&&&&&&&&&Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,&
&&&&&&&&&&&&&&&&0,
&&&&&&&&&&&&&&&&UserHandle.USER_CURRENT);
&&&&&&&&//&AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,
&&&&&&&&//&在类中实现异步操作,并提供接口反馈当前异步执行的程度
&&&&&&&&//&(可以通过接口实现UI进度更新),&&&&&&&&
&&&&&&&&//&最后反馈执行的结果给UI主线程.
&&&&&&&&AsyncTask.execute(new&Runnable()&{
&&&&&&&&&&&&public&void&run()&{
&&&&&&&&&&&&&&&&try&{
&&&&&&&&&&&&&&&&&&&&//获取系统WindowManager服务,该类提供了关于窗口管理方面的方法
&&&&&&&&&&&&&&&&&&&&IWindowManager&wm&=&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&WindowManagerGlobal.getWindowManagerService();
&&&&&&&&&&&&&&&&&&&&//&传参为&true,
&&&&&&&&&&&&&&&&&&&&//&则&wm.freezeRotation(-1)&锁定屏幕,并设置&-1&表示默认值
&&&&&&&&&&&&&&&&&&&&//&传参为&false,
&&&&&&&&&&&&&&&&&&&&//&则&wm.thawRotation()&设定有加速度计决定屏幕方向
&&&&&&&&&&&&&&&&&&&&if&(enabled)&{
&&&&&&&&&&&&&&&&&&&&&&&&//&freezeRotation&详见&
&&&&&&&&&&&&&&&&&&&&&&&&wm.freezeRotation(-1);
&&&&&&&&&&&&&&&&&&&&}&else&{
&&&&&&&&&&&&&&&&&&&&&&&&//&thawRotation详见&
&&&&&&&&&&&&&&&&&&&&&&&&wm.thawRotation();
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&}&catch&(RemoteException&exc)&{
&&&&&&&&&&&&&&&&&&&&Log.w(TAG,&&Unable&to&save&auto-rotate&setting&);
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&}
&&&&&&&&});
1.1.2.3.2.1.1.分析freezeRotation
用于锁定屏幕方向
位于:frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
public&void&freezeRotation(int&rotation)&{
//&第一步,检查相对应的权限。
&&&&if&(!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
&freezeRotation()&))&{
throw&new&SecurityException(&Requires&SET_ORIENTATION&permission&);
&&&&//第二步,如果传入的rotation值小于-1或者大于270度则抛出异常
if&(rotation&&&-1&||&rotation&&&Surface.ROTATION_270)&{
throw&new&IllegalArgumentException(&Rotation&argument&must&be&-1&or&a&v alid&&+&&rotation&constant.&);
if&(DEBUG_ORIENTATION)
&&&&&&&&&&&&Slog.v(TAG,&&freezeRotation:&mRotation=&&+&mRotation);
long&origId&=&Binder.clearCallingIdentity();
&&&&&&&&&&&&//&PhoneWindowManager.setUserRotationMode
&&&&&&&&&&&&//&用于设置屏幕旋转锁定模式
&&&&&&&&&&&&//&详见&
mPolicy.setUserRotationMode(
&&&&&&&&&&&&&&&&WindowManagerPolicy.USER_ROTATION_LOCKED,
&&&&rotation&==&-1&?&mRotation&:&rotation);
&&&&}&finally&{
Binder.restoreCallingIdentity(origId);
&&&&//&更新旋转状态
&&&&updateRotationUnchecked(false,&false);
1.1.2.3.2.1.1.1.进一步分析PhoneWindowManager.setUserRotationMode
用于设置旋转模式
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
public&void&setUserRotationMode(int&mode,&int&rot)&{
ContentResolver&res&=&mContext.getContentResolver();
&&&&//&如果传参等于&USER_ROTATION_LOCKED
if&(mode&==&WindowManagerPolicy.USER_ROTATION_LOCKED)&{
&&&&&&&&//&通过&Settings.System&设置&Settings.System.USER_ROTATION
&&&&&&&&//&为传参&rot&的值,即设置屏幕旋转角度
Settings.System.putIntForUser(res,
Settings.System.USER_ROTATION,
UserHandle.USER_CURRENT);
&&&&&&&&//&通过&Settings.System&设置&Settings.System.ACCELEROMETER_ROTATION
&&&&&&&&//&为0,即设置不根据加速度计改变屏幕方向
&&&& Settings.System.putIntForUser(res,
Settings.System.ACCELEROMETER_ROTATION,
UserHandle.USER_CURRENT);
&&&&&&&&&&&&//&通过&Settings.System&设置&Settings.System.ACCELEROMETER_ROTATION
&&&&&&&&&&&&//&为1,即设置根据加速度计改变屏幕方向
Settings.System.putIntForUser(res,
Settings.System.ACCELEROMETER_ROTATION,
UserHandle.USER_CURRENT);
1.1.2.3.2.1.2.分析thawRotation
用于设置屏幕旋转由加速度计决定
位于:frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
public&void&thawRotation()&{
&&&&//&第一步,检查权限。
&&&&if&(!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
&&&&&&&&&&thawRotation()&))&{
&&&&&&&&&throw&new&SecurityException(&Requires&SET_ORIENTATION&permission&);
if&(DEBUG_ORIENTATION)
&&&&&Slog.v(TAG,&&thawRotation:&mRotation=&&+&mRotation);
&&&&long&origId&=&Binder.clearCallingIdentity();
&&&&&&&&//&PhoneWindowManager.setUserRotationMode&用于设置屏幕旋转锁定模式
&&&&//&详见&
&&&&&&&&mPolicy.setUserRotationMode(
&&&&&&&&&&&&WindowManagerPolicy.USER_ROTATION_FREE,
&&&&&&&&&&&&777);&//&rot&not&used
&&&&}&finally&{
&&&&&&&&Binder.restoreCallingIdentity(origId);
&&&&//&更新旋转状态
&&&&updateRotationUnchecked(false,&false);
调用了QuickSettingsModel.addRotationLockTile&值,用于设置快速设置的图标、标签,提供其刷新的方法
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
void&addRotationLockTile(QuickSettingsTileView&view,
&&&&&&&&&&&&RotationLockController&rotationLockController,
&&&&&&&&&&&&RefreshCallback&cb)&{
&&&&&&&&//&传入设置菜单的按钮
&&&&&&&&mRotationLockTile&=&
&&&&&&&&//&传入回调
&&&&&&&&mRotationLockCallback&=&
&&&&&&&&//&传入旋转控制类
&&&&&&&&mRotationLockController&=&rotationLockC
&&&&&&&&//&使旋转状态改变图标标签等状态
&&&&&&&&//&详见&
&&&&&&&&onRotationLockChanged();
1.1.2.3.1.分析QuickSettingsModel.onRotationLockChanged&方法
用于调用&QuickSettingsModel.onRotationLockChanged&,使旋转状态改变图标标签等状态
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
void&onRotationLockChanged()&{
&&&&&&&&//&调用&QuickSettingsModel.onRotationLockStateChanged
&&&&&&&&//&实现旋转状态改变图标标签等状态
&&&&&&&&//&传入判断是否锁屏状态方法及判断按钮是否可见方法
&&&&&&&&//&详见&
&&&&&&&&onRotationLockStateChanged(
&&&&&&&&&&&&&&&&mRotationLockController.isRotationLocked(),
&&&&&&&&&&&&&&&&mRotationLockController.isRotationLockAffordanceVisible());
实现旋转状态改变图标标签等状态
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
public&void&onRotationLockStateChanged(boolean&rotationLocked,&boolean&affordanceVisible)&{
&&&&//&传入锁屏状态是否可见
mRotationLockState.visible&=&affordanceV
//&传入屏幕旋转是否是锁屏状态
mRotationLockState.enabled&=&rotationL
//&判断屏幕状态,
//&为true,锁屏,则mRotationLockState.iconId赋值指向锁屏图标的资源
//&为false,锁屏,则mRotationLockState.iconId赋值指向旋转图标的资源
&&&&mRotationLockState.iconId&=&rotationLocked
&&&&&&&?&R.drawable.ic_qs_rotation_locked
&&&&&&&:&R.drawable.ic_qs_auto_
//&判断屏幕状态,
//&为true,锁屏,则mRotationLockState.iconId赋值指向锁屏标签的资源
//&为false,锁屏,则mRotationLockState.iconId赋值指向旋转标签的资源
&&&&mRotationLockState.label&=&rotationLocked
&&&&&&&?&mContext.getString(R.string.quick_settings_rotation_locked_label)
&&&&&&&:&mContext.getString(R.string.quick_settings_rotation_unlocked_label);
&&&//&刷新状态
&&&mRotationLockCallback.refreshView(mRotationLockTile,&mRotationLockState);
//&添加子视图。如果没有设置布局参数,那么使用默认值。
//&传入时,我们只传入一个child参数,这时候再加入index参数
public&void&addView(View&child)&{
&&&&addView(child,&-1);
//&加入index参数
public&void&addView(View&child,&int&index)&{
&&&&//&尝试用getLayoutParams获取params参数
LayoutParams&params&=&child.getLayoutParams();
//&如果获取不到params
if&(params&==&null)&{
&&&&//&尝试使用generateDefaultLayoutParams获得
&&&&&&&&params&=&generateDefaultLayoutParams();
&&&&&&&&//&如果获取不到则抛出异常
&&&&&&&&if&(params&==&null)&{
&&&&&&&&&&&&throw&new&IllegalArgumentException(
&&&&&&&&&&&&&&&&&generateDefaultLayoutParams()&cannot&return&null&);
//&传入params到有三个参数的addView
&&&&addView(child,&index,&params);
//&添加一个与指定的子视图布局参数
public&void&addView(View&child,&int&index,&LayoutParams&params)&{
&&&&&&&&if&(DBG)&{
&&&&&&&&&&&&System.out.println(this&+&&&addView&);
&&&&&&&&//&addViewInner()&将会调用&child.requestLayout()&当设置一个布局参数
&&&&&&&&//&所以调用之前调用&requestLayout()&,
&&&&&&&&//&因此child的请求会被要求在这一层
&&&&&&&&requestLayout();
&&&&&&&&//&调用该方法可以是绘图缓存失效
&&&&&&&&invalidate(true);
&&&&&&&&//&实现显示绘图部分
&&&&&&&&addViewInner(child,&index,&params,&false);
1.1.3.关于Settings.System
Settings.System.提供类似Settings.System.putIntForUser、getIntForUser等系统设置的API,它的作用可以对系统的全局设置数据库进行操作。具体可以参考官方API文档,或者在阅读源码:
frameworks/base/core/java/android/provider/Settings.java
指令&USER_ROTATION&作用:
当没有其他设置有效时设置默认屏幕旋转方向。
当&ACCELEROMETER_ROTATION&为零,必须设置这个值。
指令&ACCELEROMETER_ROTATION&作用:
控制加速度计是否会被用来改变屏幕取向。如果为0,它将不能使用,除非显式地请求由应用程序;如果1,那么它将使用默认情况下,除非显式由应用程序禁用。
Settings.System&提供了一套键值对的形式,将一些特定的值以全局的模式保存到&Setting&的数据库中。我们可以通过它提供的&get&或者&put&的方法对其中的数据进行读写。我们也可以在&frameworks&中添加自己所需要的一些特定值。
在应用程序层面,如需操作在&AndroidMainfes.xml&添加权限:
&uses-permission&android:name=&android.permission.READ_SETTINGS&&/&
&uses-permission&android:name=&android.permission.WRITE_SETTINGS&&/&
Settings.System&由&frameworks/base/core/java/android/provider/Setting.java实现。
Zygote&启动了&WindowManager&以后,调用了&PhoneManager的&rotationForOrientationLw,其实际调用了&WindowOrientationListener,WindowOrientationListener&中监听了&Sensor&的值,对旋转方向进行了判断,实现、对四个不同方向做出响应&。
OrientationListener提供了一个抽象的旋转监听机制。
OrientationEventListener提供了具体的实现。
传感器架构分析
Android&4.4&系统支持了20种传感器,其中加速度传感器提供了手机旋转的矢量。
Android&传感器系统由以下几部分构成:
Java应用程序
Framework框架层
SensorManager.java
SensorListener.java
SensorEvent.Java
android_hardware_SensorManager.cpp
com_android_server_SensorService.java
HAL硬件抽象层
设备驱动程序
比如加速度传感器
各部分之间架构图如下:
一般加速度模块使用I2C对硬件进行操作,生成了设备节点,对上层提供例如open(),&read(),&write(),&ioctl(),&poll()等函数调用的方式。
硬件抽象层
与底层设备驱动程序进行交互。
用于交互的关键是文件描述符fd,fd通过open()打开加速度传感器的设备节点而得到,
即&fd&=&open&(&/dev/bma220&,&O_RDONLY);
这里的/dev/bma220这个设备节点是举个例子,因为目前设备上没有对应的硬件。
其他的函数调用如read(),&write()等都通过该文件描述符fd对加速度传感器进行操作。
JNI提供了从C++语言到JAVA语言的转换,它为Java&Framework层提供一系列接口,而这些接口函数的具体实现中,利用例如module-&methods-&open(),sSensorDevice-&data_open(),&sSensorDevice-&poll()等回调函数与硬件抽象层进行交互。而这些open(),&poll()回调函数在硬件抽象层中具体实现。
Java&Framework
Framework层提供各种类和类的对象,可作为系统的守护进程运行,也可供上层应用程序的使用。
例如类SensorManager,它作为系统的守护进程在初始化的时候开始运行,其子类SensorThread中的子类&SensorThreadRunnable通过sensors_data_poll()实现了对G-sensor数据的轮询访问,而&sensors_data_poll()通过JNI层转换到硬件抽象层去具体实现poll()。
把快速设置栏中的“屏幕锁定/自由旋转”按钮改成“旋转屏幕”按钮,实现每按一次屏幕旋转递增90°。
frameworks/base/core/java/com/android/internal/view/RotationPolicy.java
在&RotationPolicy&类里添加:
public&static&int&rota&=&0;
在&setRotationLock&方法里面,删除调用重力自由旋转的可能性:
//if&(enabled)&{
//&&&&wm.freezeRotation(-1);
//}&else&{
//&&&&wm.thawRotation();
//&注释掉以上部分
final&int&cur&=&wm.getRotation();//获取当前屏幕旋转防线的值,4个方向用0~3表示
rota++;
if(rota&&&3)
&&&&rota&=&0;
wm.freezeRotation(rota);//每次被调用锁定旋转的时候设置新的锁定方向,即原来方向的下一个方向
frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
做如下修改:
public&void&onRotationLockStateChanged(boolean&rotationLocked,&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&boolean&affordanceVisible)&{
&&&&&&&&mRotationLockState.visible&=&affordanceV
&&&&&&&&mRotationLockState.enabled&=&rotationL
//&&&&&&&&mRotationLockState.iconId&=&rotationLocked
//&&&&&&&&&&&&&&&&?&R.drawable.ic_qs_rotation_locked
//&&&&&&&&&&&&&&&&:&R.drawable.ic_qs_auto_
//&注释掉以上部分
&&&&&&&&//&强制的设置图标固定显示“旋转屏幕图标”
&&&&&&&&mRotationLockState.iconId&=&R.drawable.ic_qs_auto_
//mRotationLockState.label&=&rotationLocked
//&&&&?&mContext.getString(R.string.quick_settings_rotation_locked_label)
//&&&&:&mContext.getString(R.string.quick_settings_rotation_unlocked_label);
//&注释掉以上部分
&&&&&&&&//&强制的设置图标固定显示“旋转屏幕标签”
&&&&&&&&mRotationLockState.label&=&mContext.getString(R.string.quick_settings_rotation_sreen_label);
&&&&&&&&mRotationLockCallback.refreshView(mRotationLockTile,&mRotationLockState);
frameworks/base/packages/SystemUI/res/values/strings.xml
&string&name=&quick_settings_rotation_sreen_label&&Rotate&Sreen&/string&
图标标签的中文翻译:
android/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
&string&name=&quick_settings_rotation_sreen_label&&&旋转屏幕&&/string&
思路是模仿休眠菜单进行添加
休眠部分读取设置菜单的主要原理:
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
//&把实际数值更新到界面上
private&void&updateTimeoutPreferenceDescription(long&currentTimeout)&{
ListPreference&preference&=&mScreenTimeoutP
&&&&//&声明一个字符串变量summary用于存储临时字符串
&&&&&String&
&&&&&//&若超时时间小于0,这种情况则置空临时字符串
&&&&if&(currentTimeout&&&0)&{
summary&=&&&;
&&&&&&&&//&声明变量entries&,存储读取自preference.getEntries,表示读取到的记录的内容
final&CharSequence[]&entries&=&preference.getEntries();
&&&&&&&&//&声明变量values&,存储读取自preference.getEntryValues,表示读取到的记录所在的值
final&CharSequence[]&values&=&preference.getEntryValues();
&&&&&&&&//&如果读取到的记录和记录长度为0,则置空字符串
if&(entries&==&null&||&entries.length&==&0)&{
summary&=&&&;
int&best&=&0;
for&(int&i&=&0;&i&&&values.&i++)&{
long&timeout&=&Long.parseLong(values[i].toString());
&&&&&&& if&(currentTimeout&&=&timeout)&{
&&&&& best&=&i;
//&最后一项永不休眠
&&&&&&&&//&如果到了最后一项
if&(best&==&values.length&-&1)
&&&&&&&&&&&&//&设置字符串为“永远休眠”字样
summary&=&preference.getContext().getString(R.string.never_sleep);
&&&&&&&&&&&&//&设置字符串为XX分钟休眠
summary&=&
&&&&&&&&&&&&&&&&&preference.getContext().getString(
&&&&&&&&&&&&&&&&&R.string.screen_timeout_summary,
&&&&&&&&&entries[best]);
&&&&//&把设置好的字符串显示到菜单项上
preference.setSummary(summary);
public&boolean&onPreferenceChange(Preference&preference,&Object&objValue)&{
final&String&key&=&preference.getKey();
if&(KEY_SCREEN_TIMEOUT.equals(key))&{
int&value&=&Integer.parseInt((String)&objValue);
&&&&&&&&&&&&//&调用Settings.System.putInt
&&&&&&&&&&&&//&设置SCREEN_OFF_TIMEOUT,用于设置屏幕关闭时间的
Settings.System.putInt(
&&&&&&&&&&&&&&&&getContentResolver(),&
&&&&&&&&&&&&&&&&SCREEN_OFF_TIMEOUT,&
&&&&&&&&&&&&&&&&value);
&&&&&&&&&&&&//&传入最新数值,更新最新的数值到界面上
updateTimeoutPreferenceDescription(value);
}&catch&(NumberFormatException&e)&{
Log.e(TAG,&&could&not&persist&screen&timeout&setting&,&e);
(省略...)
实现在设置菜单中设置屏幕旋转角度的核心方法:
使用Settings.System.putInt,对USER_ROTATION的值进行设置。
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
if&(KEY_SCREEN_ROTATION.equals(key))&{
&&&&//&读取设置项上的值
int&value&=&Integer.parseInt((String)&objValue);
&&&&&&&&//&通过&Settings.System.putInt&写入系统的数据库
Settings.System.putInt(getContentResolver(),&USER_ROTATION,&value);
&&&&&&&&//&把系统最新值显示到菜单上
updateRotationPreferenceDescription(value);
}&catch&(NumberFormatException&e)&{
Log.e(TAG,&&could&not&...ask&Jangel&,&e);
起着把最新设置的值显示到菜单上的作用
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
import&static&android.provider.Settings.System.USER_ROTATION;
private&static&final&int&FALLBACK_SCREEN_ROTATION_VALUE&=&0;
private&static&final&String&KEY_SCREEN_ROTATION&=&&screen_rotation&;
private&ListPreference&mScreenRotationP
mScreenRotationPreference&=&(ListPreference)&findPreference(KEY_SCREEN_ROTATION);
final&long&currentRotation&=&Settings.System.getLong(resolver,&USER_ROTATION,
FALLBACK_SCREEN_ROTATION_VALUE);
mScreenRotationPreference.setValue(String.valueOf(currentRotation));
mScreenRotationPreference.setOnPreferenceChangeListener(this);
disableUnusableTimeouts(mScreenRotationPreference);
updateRotationPreferenceDescription(currentRotation);
private&void&updateRotationPreferenceDescription(long&currentRotation)&{
ListPreference&preference&=&mScreenRotationP
&&&&//&处理不支持的值
if&(currentRotation&&&0)&{
//&Unsupported&value
summary&=&&&;
& final&CharSequence[]&entries2&=&preference.getEntries();
&&& final&CharSequence[]&values2&=&preference.getEntryValues();
& if&(entries2&==&null&||&entries2.length&==&0)&{
summary&=&&&;
int&best&=&0;
for&(int&i&=&0;&i&&&values2.&i++)&{
long&rota&=&Long.parseLong(values2[i].toString());
if&(currentRotation&&=&rota)&{
summary&=&preference.getContext().getString(R.string.screen_rotati on_summary,entries2[best]);
添加了设置菜单选项,并为每个选项赋值:
packages/apps/Settings/res/values/arrays.xml
&&&&&!--Display&settings.Srceen_rotation.&add&by&Jangel--&
&&&&&string-array&name=&screen_rotation_entries&&
&&&&&&&&&item&0° &/item&&
&&&&&&& &item&90° &/item&
&&&&&&&&&item&180° &/item&
&&&&&&&&&item&270° &/item&
&&&&&/string-array&
&&&&&!--&Do&not&translate.这部分内容是取其具体数值,不要对其进行语言翻译&--&
&&&&&string-array&name=&screen_rotation_values&&translatable=&false&&
&&&&&&&&&!--&Do&not&translate.&--&
&&&&&&&&&item&0&/item&
&&&&&&&&&!--&Do&not&translate.&--&
&&&&&&&&&item&1&/item&
&&&&&&&&&!--&Do&not&translate.&--&
&&&&&&&&&item&2&/item&
&&&&&&&&&!--&Do&not&translate.&--&
&&&&&&&&&item&3&/item&
&/string-array&
packages/apps/Settings/res/values/strings.xml
&!--add&by&Jangel--&
&&&&&string&name=&screen_rotation&&Rotation&/string&
&string&name=&screen_rotation_summary&&Rotate&screen&&xliff:g&id=&rotation_description&&%1$s&/xliff:g&&/string&
同理,需要对以上xml文件进行中文翻译,这里不再详述。
packages/apps/Settings/res/xml/display_settings.xml
&!--add&by&Jangel--&
&&&&&&&&&ListPreference
&&&&&&&&&&&&&&&&android:key=&screen_rotation&
&&&&&&&&&&&&&&&&android:title=&@string/screen_rotation&
&&&&&&&&&&&&&&&&android:summary=&@string/screen_rotation_summary&
&&&&&&&&&&&&&&&&android:persistent=&false&
&&&&&&&&&&&&&&&&android:entries=&@array/screen_rotation_entries&
&&&&&&&&&&&&&&&&android:entryValues=&@array/screen_rotation_values&&/&
//设置为横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//&设置为竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
也可以通过xml实现:
//在配置文件中,设为横
android:screenOrientation=&landscape&
//在配置文件中,设为竖屏
android:screenOrientation=&portrait&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:44340次
排名:千里之外
原创:37篇
转载:24篇
评论:12条
(3)(1)(1)(3)(1)(1)(1)(1)(2)(7)(9)(7)(1)(1)(5)(9)(6)(1)(1)

我要回帖

更多关于 crop rotation 的文章

 

随机推荐