Android Configuration
来源:互联网 发布:阿里云mysql远程连接 编辑:程序博客网 时间:2024/06/16 13:45
Android Configuration学习随笔
在学习资源加载时发现Configuration有决定性的作用,所以详细看了下Configuration相关的内容。
看Configuration时需要先明白一个设计:系统中有两个configuration, 一个是common的configuration,暂且叫service configuration, 一个是Activity的override configuration.
原则是override configuration的优先级比较高,如果存在override configuration会优先使用。
所有的Configuration初始化从WMS开始,先从DisplayManagerService去拿基本的display信息,然后WMS中也会根据用户设置进行一些初始化。并把得到的Configuration设置重新设置给DMS,同时也会设置给AMS。
另外AMS在启动新的Task时也会为根据每个task的bounds计算override configuration。
Launch一个新的Activity时给的configuration参数:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
Service Configuration
- Service configuration的初始化
WMS起来时,如果display已经准备好,就开始对configuration进行初始化
1). 从DMS获取display info对DisplayConent初始化
2). 读取用户设置的display信息进行设置
3). 对AMS的configuration进行设置
4). AMS中的更新会再借助WMS完成计算,由于WMS中可能再对configuration做调整,所以会再把更新后的Configuration sync会DMS. overrideconfiguration.
public void displayReady() {
for (Display display : mDisplays) {
displayReady(display.getDisplayId());
}
synchronized(mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
readForcedDisplayPropertiesLocked(displayContent);
mDisplayReady = true;
}
try { mActivityManager.updateConfiguration(null);} catch (RemoteException e) {}
}
从DMS获取最原始的Display信息,给DisplayContent进行设置
void initializeDisplayBaseInfo() {
// Bootstrap the default logical display from the display manager.
final DisplayInfo newDisplayInfo =
mService.mDisplayManagerInternal.getDisplayInfo(mDisplayId);
if (newDisplayInfo != null) {
mDisplayInfo.copyFrom(newDisplayInfo);
}
mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
}
ActivityManagerService
AMS内的config通过WMS计算得到
public void updateConfiguration(Configuration values) {
synchronized(this) {
if (values == null && mWindowManager != null) {
// sentinel: fetch the current configuration from the window manager
values = mWindowManager.computeNewConfiguration();
}
}
WindowManagerService
WMS内部计算时,
1. 先更新display信息
2. 此时,displayInfo已经是更新过的,用来再计算config
private Configuration computeNewConfigurationLocked() {
if (!mDisplayReady) {
return null;
}
Configuration config = new Configuration();
config.fontScale = 0;
computeScreenConfigurationLocked(config);
return config;
}
/* Do not call if mDisplayReady == false /
void computeScreenConfigurationLocked(Configuration config) {
final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(
config.uiMode);
final int dw = displayInfo.logicalWidth;final int dh = displayInfo.logicalHeight;config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) / mDisplayMetrics.density);config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) / mDisplayMetrics.density);final boolean rotated = (mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270);computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh, mDisplayMetrics.density, config);config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) | ((displayInfo.flags & Display.FLAG_ROUND) != 0 ? Configuration.SCREENLAYOUT_ROUND_YES : Configuration.SCREENLAYOUT_ROUND_NO);config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, mDisplayMetrics, dw, dh);config.densityDpi = displayInfo.logicalDensityDpi;// Update the configuration based on available input devices, lid switch,// and platform configuration.config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;config.keyboard = Configuration.KEYBOARD_NOKEYS;config.navigation = Configuration.NAVIGATION_NONAV;// Let the policy update hidden states.config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
先拿到displayContent, DisplayContent中的一些内容可能已经被WMS做了新的设置,(例如PhoneWindowManager的设置),再计算其他一些更新
然后和DisplayManagerService同步,将更新后的overrideConfig设置过去
displayContent中的其他内容更新
最后还计算了一下CompatibleScreenScale,不晓得有啥用?
/* Do not call if mDisplayReady == false /
DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
// TODO(multidisplay): For now, apply Configuration to main screen only.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
// Use the effective "visual" dimensions based on current rotationfinal boolean rotated = (mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270);final int realdw = rotated ? displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;final int realdh = rotated ? displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;int dw = realdw;int dh = realdh;// Update application display metrics.final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode);final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode);final DisplayInfo displayInfo = displayContent.getDisplayInfo();displayInfo.rotation = mRotation;displayInfo.logicalWidth = dw;displayInfo.logicalHeight = dh;displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;displayInfo.appWidth = appWidth;displayInfo.appHeight = appHeight;displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);displayInfo.getAppMetrics(mDisplayMetrics);mDisplayManagerInternal.**setDisplayInfoOverrideFromWindowManager**( displayContent.getDisplayId(), displayInfo);displayContent.mBaseDisplayRect.set(0, 0, dw, dh);if (false) { Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);}mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, mCompatDisplayMetrics);return displayInfo;
}
设置OverrideDisplayInfo到DisplayManagerService
public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
if (info != null) {
if (mOverrideDisplayInfo == null) {
mOverrideDisplayInfo = new DisplayInfo(info);
mInfo = null;
return true;
}
if (!mOverrideDisplayInfo.equals(info)) {
mOverrideDisplayInfo.copyFrom(info);
mInfo = null;
return true;
}
} else if (mOverrideDisplayInfo != null) {
mOverrideDisplayInfo = null;
mInfo = null;
return true;
}
return false;
}
override configuration
根据bounds算的override config
Configuration updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
mFullscreen = bounds == null;if (mFullscreen) { if (mBounds != null && StackId.persistTaskBounds(stack.mStackId)) { mLastNonFullscreenBounds = mBounds; } mBounds = null; mOverrideConfig = Configuration.EMPTY;} else { mTmpRect.set(bounds); adjustForMinimalTaskDimensions(mTmpRect); if (mBounds == null) { mBounds = new Rect(mTmpRect); } else { mBounds.set(mTmpRect); } if (stack == null || StackId.persistTaskBounds(stack.mStackId)) { mLastNonFullscreenBounds = mBounds; } mOverrideConfig = **calculateOverrideConfig**(mTmpRect, insetBounds, mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);}return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
如下函数可以看到override configuration的计算过程,例如根据宽高直接计算到新的的orientation.
所以对一个Activity做resize, 如果width > height, 会重新加载landscape的资源。
private Configuration calculateOverrideConfig(Rect bounds, Rect insetBounds,
boolean overrideWidth, boolean overrideHeight) {
mTmpNonDecorBounds.set(bounds);
mTmpStableBounds.set(bounds);
subtractNonDecorInsets(
mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
overrideWidth, overrideHeight);
subtractStableInsets(
mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
overrideWidth, overrideHeight);
// For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,// i.e. the screen area without the system bars.final Configuration serviceConfig = mService.mConfiguration;final Configuration config = new Configuration(Configuration.EMPTY);// TODO(multidisplay): Update Dp to that of display stack is on.final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;config.screenWidthDp = Math.min((int)(mTmpStableBounds.width() / density), serviceConfig.screenWidthDp);config.screenHeightDp = Math.min((int)(mTmpStableBounds.height() / density), serviceConfig.screenHeightDp);// TODO: Orientation?config.orientation = (config.screenWidthDp <= config.screenHeightDp) ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;// Always set fontScale to be euqal to global. Can't set to 0, as that makes the override// config not equal to EMPTY. Also can't set to 1, as Configuration.updateFrom will use// the override scale as long as it's non-zero, and we'll always use 1.config.fontScale = serviceConfig.fontScale;// For calculating screen layout, we need to use the non-decor inset screen area for the// calculation for compatibility reasons, i.e. screen area without system bars that could// never go away in Honeycomb.final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);;config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds( insetBounds != null ? insetBounds : bounds);return config;
}
- android Configuration
- android Configuration
- Android Configuration
- Android SD Configuration
- android Configuration详解
- Android Build SD Configuration
- 疯狂android讲义---Configuration
- android Configuration详解
- android configuration example
- 【Android】Configuration Changes
- android Configuration系统设置
- android Configuration系统设置
- Android ADT Configuration
- 51-android.rules configuration
- Android Configuration系统设置
- Android的Configuration
- Android的Configuration类
- android - Searchable Configuration
- proguar混淆使用总结
- 线程的使用
- python 类属性 实例属性 特性
- 事务问题,Executing an update delete query
- Codevs 1066&&洛谷 P1514 引水入城(修bug%……¥题号写反了好尴尬#……%@&&now!=m)
- Android Configuration
- 【实战】android中几个常用的对话框
- 顺序队列
- Event事件
- caffe 与cudnn版本不匹配 ./include/caffe/util/cudnn.hpp:127:41: error: too few arguments to function
- Android 实战开发 帧动画
- 快捷键
- Let’s Encrypt 免费SSL证书自动续期的方法
- ci框架 加载驱动&ci框架使用redis