1.简介
学习下屏幕亮度相关的内容
- 默认的亮度哪里设置的
- 设置里的亮度调节seekbar,如何修改亮度,如何获取亮度
2.DisplayDeviceConfig.java
有两种静态方法可以创建实例
2.1.实例化1
这种是先看product或者vendor目录下有没有对应的xml,有的话读取,没有的话就通过2.2的另外一种方法实例化
arduino
public static DisplayDeviceConfig create(Context context, long physicalDisplayId,
boolean isFirstDisplay) {
final DisplayDeviceConfig config = createWithoutDefaultValues(context, physicalDisplayId,
isFirstDisplay);
config.copyUninitializedValuesFromSecondaryConfig(loadDefaultConfigurationXml(context));
return config;
}
>createWithoutDefaultValues
arduino
private static DisplayDeviceConfig createWithoutDefaultValues(Context context,
long physicalDisplayId, boolean isFirstDisplay) {
DisplayDeviceConfig config;
//从product目录下找
config = loadConfigFromDirectory(context, Environment.getProductDirectory(),
physicalDisplayId);
if (config != null) {
return config;
}
//从vendor目录下找
config = loadConfigFromDirectory(context, Environment.getVendorDirectory(),
physicalDisplayId);
if (config != null) {
return config;
}
//都没找到,使用默认的config.xml,这就是第二种实例化的方法,见2.2
return create(context, isFirstDisplay);
}
>相关的变量
arduino
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d";
private static final String NO_SUFFIX_FORMAT = "%d";
>loadConfigFromDirectory
arduino
private static DisplayDeviceConfig loadConfigFromDirectory(Context context,
File baseDirectory, long physicalDisplayId) {
DisplayDeviceConfig config;
//这种文件名和设备物理id有关,id里包含固定的bit
config = getConfigFromSuffix(context, baseDirectory, STABLE_ID_SUFFIX_FORMAT,
physicalDisplayId);
if (config != null) {
return config;
}
//其实也是id,不过id里去掉了固定的bit
final long withoutStableFlag = physicalDisplayId & ~STABLE_FLAG;
config = getConfigFromSuffix(context, baseDirectory, NO_SUFFIX_FORMAT, withoutStableFlag);
if (config != null) {
return config;
}
// 第三种使用的物理地址的端口id当文件名
final DisplayAddress.Physical physicalAddress =
DisplayAddress.fromPhysicalDisplayId(physicalDisplayId);
int port = physicalAddress.getPort();
config = getConfigFromSuffix(context, baseDirectory, PORT_SUFFIX_FORMAT, port);
return config;
}
>getConfigFromSuffix
arduino
private static final String ETC_DIR = "etc";
private static final String DISPLAY_CONFIG_DIR = "displayconfig";
private static final String CONFIG_FILE_FORMAT = "display_%s.xml";
arduino
private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory,
String suffixFormat, long idNumber) {
//假设idNumber是xxxx,结果是id_xxxx 或者xxxx,根据format决定
final String suffix = String.format(Locale.ROOT, suffixFormat, idNumber);
//display_%s.xml 把%s替换成上边的suffix
final String filename = String.format(Locale.ROOT, CONFIG_FILE_FORMAT, suffix);
final File filePath = Environment.buildPath(
baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename);
final DisplayDeviceConfig config = new DisplayDeviceConfig(context);
if (config.initFromFile(filePath)) {
//初始化成功表明文件存在,那么config的数据就是解析文件获取的
return config;
}
//文件不存在,返回空
return null;
}
2.2.实例化2
这里也分两种,一种使用xml文件,一种使用默认值
arduino
public static DisplayDeviceConfig create(Context context, boolean useConfigXml) {
final DisplayDeviceConfig config;
if (useConfigXml) {
config = getConfigFromGlobalXml(context);
} else {
config = getConfigFromPmValues(context);
}
return config;
}
>getConfigFromGlobalXml
arduino
private static DisplayDeviceConfig getConfigFromGlobalXml(Context context) {
DisplayDeviceConfig config = new DisplayDeviceConfig(context);
config.initFromGlobalXml();
return config;
}
>getConfigFromPmValues
arduino
private static DisplayDeviceConfig getConfigFromPmValues(Context context) {
DisplayDeviceConfig config = new DisplayDeviceConfig(context);
config.initFromDefaultValues();
return config;
}
>initFromGlobalXml
方法里又有很多方法,看名字大概就知道加载的是啥,我们简单看几个即可
scss
private void initFromGlobalXml() {
// If no ddc exists, use config.xml
loadBrightnessDefaultFromConfigXml();
loadBrightnessConstraintsFromConfigXml();
loadBrightnessMapFromConfigXml();
loadBrightnessRampsFromConfigXml();
loadAmbientLightSensorFromConfigXml();
loadBrightnessChangeThresholdsFromXml();
useFallbackProxSensor();
loadAutoBrightnessConfigsFromConfigXml();
loadAutoBrightnessAvailableFromConfigXml();
loadRefreshRateSetting(null);
mLoadedFrom = "<config.xml>";
}
>loadBrightnessDefaultFromConfigXml
加载默认的亮度,可以看到,读取的是资源文件,先读取一个float,如果是无效的(默认是无效的),再去读取int值
csharp
private void loadBrightnessDefaultFromConfigXml() {
// Priority 1: Value in the config.xml (float)
// Priority 2: Value in the config.xml (int)
final float def = mContext.getResources().getFloat(com.android.internal.R.dimen
.config_screenBrightnessSettingDefaultFloat);
if (def == INVALID_BRIGHTNESS_IN_CONFIG) {
mBrightnessDefault = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
.config_screenBrightnessSettingDefault));
} else {
mBrightnessDefault = def;
}
}
看下默认值
xml
<!-- Note: This setting is deprecated, please use
config_screenBrightnessSettingDefaultFloat instead -->
<integer name="config_screenBrightnessSettingDefault">102</integer>
<!-- Default screen brightness setting set.
-2 is invalid so setting will resort to int value specified above.
Must be in the range specified by minimum and maximum. -->
<item name="config_screenBrightnessSettingDefaultFloat" format="float" type="dimen">-2</item>
>brightnessIntToFloat
- constrainedMap方法简单点就是(value - min) / (max - min),前两个参数就是对结果进行约束
- 你以为0.39763778就是屏幕亮度的百分比吗?其实不是的,你去看亮度条,会发现seekbar大概在80%的位置
- 具体的看 小节5 里的工具类如何转换
arduino
public static float brightnessIntToFloat(int brightnessInt) {
if (brightnessInt == PowerManager.BRIGHTNESS_OFF) { //0
return PowerManager.BRIGHTNESS_OFF_FLOAT; //-1
} else if (brightnessInt == PowerManager.BRIGHTNESS_INVALID) { //-1
return PowerManager.BRIGHTNESS_INVALID_FLOAT; //Float.NaN
} else {
final float minFloat = PowerManager.BRIGHTNESS_MIN; //0
final float maxFloat = PowerManager.BRIGHTNESS_MAX; //1
final float minInt = PowerManager.BRIGHTNESS_OFF + 1; //1
final float maxInt = PowerManager.BRIGHTNESS_ON; //255
return MathUtils.constrainedMap(minFloat, maxFloat, minInt, maxInt, brightnessInt);
}
}
3.LocalDisplayAdapter.java
3.1.registerLocked或者connected
调用的地方见 小节4
scss
public void registerLocked() {
super.registerLocked();
mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),
new LocalDisplayEventListener());
for (long physicalDisplayId : mSurfaceControlProxy.getPhysicalDisplayIds()) {
tryConnectDisplayLocked(physicalDisplayId);
}
}
或者
java
private final class LocalDisplayEventListener implements DisplayEventListener {
@Override
public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
synchronized (getSyncRoot()) {
if (connected) {
tryConnectDisplayLocked(physicalDisplayId);
} else {
tryDisconnectDisplayLocked(physicalDisplayId);
}
}
}
3.2.tryConnectDisplayLocked
显示器连接
scss
private void tryConnectDisplayLocked(long physicalDisplayId) {
final IBinder displayToken =
mSurfaceControlProxy.getPhysicalDisplayToken(physicalDisplayId);
if (displayToken != null) {
//...
LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device == null) {
// Display was added.
final boolean isFirstDisplay = mDevices.size() == 0;
//实例化DisplayDevice
device = new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,
dynamicInfo, modeSpecs, isFirstDisplay);
mDevices.put(physicalDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
} else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,
modeSpecs)) {
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
}
} else {
}
}
3.3.LocalDisplayDevice
scala
private final class LocalDisplayDevice extends DisplayDevice {
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
if (mInfo == null) {
mInfo = new DisplayDeviceInfo();
//...
mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
mInfo.brightnessDefault = getDisplayDeviceConfig().getBrightnessDefault();
}
return mInfo;
}
4.DisplayManagerService.java
在 SystemServer 里启动的
scala
public final class DisplayManagerService extends SystemService {
4.1.onStart
scss
public void onStart() {
synchronized (mSyncRoot) {
mPersistentDataStore.loadIfNeeded();
loadStableDisplayValuesLocked();
}
//注册默认的display
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
true /*allowIsolated*/);
publishLocalService(DisplayManagerInternal.class, new LocalService());
}
4.2.DisplayManagerHandler
scala
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
registerDefaultDisplayAdapters();
break;
4.3.registerDefaultDisplayAdapters
scss
private void registerDefaultDisplayAdapters() {
// Register default display adapters.
synchronized (mSyncRoot) {
//主要的显示适配器
registerDisplayAdapterLocked(new LocalDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayDeviceRepo));
//vr 虚拟设备
mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
mHandler, mDisplayDeviceRepo);
if (mVirtualDisplayAdapter != null) {
registerDisplayAdapterLocked(mVirtualDisplayAdapter);
}
}
}
>其他显示
scss
private void registerOverlayDisplayAdapterLocked() {
registerDisplayAdapterLocked(new OverlayDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler));
}
private void registerWifiDisplayAdapterLocked() {
if (mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableWifiDisplay)
|| SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
mWifiDisplayAdapter = new WifiDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,
mPersistentDataStore);
registerDisplayAdapterLocked(mWifiDisplayAdapter);
}
}
4.4.registerDisplayAdapterLocked
csharp
private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
mDisplayAdapters.add(adapter);
//回到小节3继续看
adapter.registerLocked();
}
5.BrightnessUtils.java
- 这个类里有2个方法,就是2种数据互相转化,当然了还有另外2个同名的方法,逻辑差不多
- min是0,max是1,
5.1.convertGammaToLinearFloat
这里是把int转化为float,int值是亮度设置seekbar的值,取值范围是0到65535
arduino
public static final float convertGammaToLinearFloat(int val, float min, float max) {
final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val);
final float ret;
if (normalizedVal <= R) {
ret = MathUtils.sq(normalizedVal / R);
} else {
ret = MathUtils.exp((normalizedVal - C) / A) + B;
}
// HLG is normalized to the range [0, 12], ensure that value is within that range,
// it shouldn't be out of bounds.
final float normalizedRet = MathUtils.constrain(ret, 0, 12);
// Re-normalize to the range [0, 1]
// in order to derive the correct setting value.
return MathUtils.lerp(min, max, normalizedRet / 12);
}
5.2.convertLinearToGammaFloat
这里是把float值转化为int值,从0到1
arduino
public static final int GAMMA_SPACE_MIN = 0;
public static final int GAMMA_SPACE_MAX = 65535;
public static final int convertLinearToGammaFloat(float val, float min, float max) {
// For some reason, HLG normalizes to the range [0, 12] rather than [0, 1]
final float normalizedVal = MathUtils.norm(min, max, val) * 12;
final float ret;
if (normalizedVal <= 1f) {
ret = MathUtils.sqrt(normalizedVal) * R;
} else {
ret = A * MathUtils.log(normalizedVal - B) + C;
}
return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
}
6.下拉状态栏的亮度调节拖动条
- 亮度调节有两个地方,一个是下拉状态栏,顶部可以看到一个seekbar,一个是在settings的display里
6.1.BrightnessSliderView.java
自定义的帧布局,里边包含一个seekbar,可以看到它的方法设置最终都是给到seekbar了
typescript
public class BrightnessSliderView extends FrameLayout {
public void setOnSeekBarChangeListener(OnSeekBarChangeListener seekListener) {
mSlider.setOnSeekBarChangeListener(seekListener);
}
//拦截器,是否拦截触摸事件
public void setOnInterceptListener(Gefingerpoken onInterceptListener) {
mOnInterceptListener = onInterceptListener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mOnInterceptListener != null) {
//6.2小节里可以看到,固定返回false,不拦截触摸事件
return mOnInterceptListener.onInterceptTouchEvent(ev);
}
return super.onInterceptTouchEvent(ev);
}
public void setMax(int max) {
mSlider.setMax(max);
}
public void setValue(int value) {
mSlider.setProgress(value);
}
6.2.BrightnessSliderController.java
就是上边的自定义view的控制器,其实主要就是控制它里边的seekbar
typescript
public class BrightnessSliderController extends ViewController<BrightnessSliderView> implements
ToggleSlider {
protected void onViewAttached() {
//进度改变监听
mView.setOnSeekBarChangeListener(mSeekListener);
//设置触摸拦截监听
mView.setOnInterceptListener(mOnInterceptListener);
}
//设置镜像控制器以及镜像seekbar
public void setMirrorControllerAndMirror(BrightnessMirrorController c) {
mMirrorController = c;
setMirror(c.getToggleSlider());
}
private void setMirror(ToggleSlider toggleSlider) {
mMirror = toggleSlider;
if (mMirror != null) {
mMirror.setMax(mView.getMax());
mMirror.setValue(mView.getValue());
//有镜像的话,触摸事件分发监听器换一个
mView.setOnDispatchTouchEventListener(this::mirrorTouchEvent);
} else {
//没有镜像,设置为null
mView.setOnDispatchTouchEventListener(null);
}
}
//设置监听器,监听进度的变化,下边的mSeekListener里用到
public void setOnChangedListener(Listener l) {
mListener = l;
}
>mSeekListener
- 基本都交给另外一个listener处理了
- 拖动开始会弹个镜像seekbar,拖动结束隐藏镜像seekbar,后边分析下controller
java
private final SeekBar.OnSeekBarChangeListener mSeekListener =
new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mListener != null) {
mListener.onChanged(mTracking, progress, false);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mTracking = true;
if (mListener != null) {
mListener.onChanged(mTracking, getValue(), false);
}
//开始拖动以后如果有镜像控制器的话就显示镜像
if (mMirrorController != null) {
//显示镜像
mMirrorController.showMirror();
//调整镜像位置和当前的view一样
mMirrorController.setLocationAndSize(mView);
}
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mTracking = false;
if (mListener != null) {
mListener.onChanged(mTracking, getValue(), true);
}
//停止拖动的时候隐藏镜像
if (mMirrorController != null) {
mMirrorController.hideMirror();
}
}
};
>mOnInterceptListener
java
private final Gefingerpoken mOnInterceptListener = new Gefingerpoken() {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
mFalsingManager.isFalseTouch(Classifier.BRIGHTNESS_SLIDER);
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return false;
}
};
>mirrorTouchEvent
其实就是把我们当前seekbar的触摸事件复制了一份,然后传递给镜像了
typescript
public boolean mirrorTouchEvent(MotionEvent ev) {
if (mMirror != null) {
return copyEventToMirror(ev);
} else {
// We are the mirror, so we have to dispatch the event
return mView.dispatchTouchEvent(ev);
}
}
private boolean copyEventToMirror(MotionEvent ev) {
MotionEvent copy = ev.copy();
boolean out = mMirror.mirrorTouchEvent(copy);
copy.recycle();
return out;
}
6.2.1.Factory
小节7里用到,Factory是注解实例化的,完事调用factory的create方法创建controller
java
public static class Factory {
private final FalsingManager mFalsingManager;
@Inject
public Factory(FalsingManager falsingManager) {
mFalsingManager = falsingManager;
}
public BrightnessSliderController create(Context context, @Nullable ViewGroup viewRoot) {
int layout = getLayout();
BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context)
.inflate(layout, viewRoot, false);
return new BrightnessSliderController(root, mFalsingManager);
}
private int getLayout() {
return R.layout.quick_settings_brightness_dialog;
}
}
6.3.BrightnessController.java
less
public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
public BrightnessController(
Context context,
ToggleSlider control,
UserTracker userTracker,
@Main Executor mainExecutor,
@Background Handler bgHandler) {
mContext = context;
mControl = control;
// 这个controller就是BrightnessSliderController
mControl.setMax(GAMMA_SPACE_MAX);//最大值65535
>mStartListeningRunnable
csharp
public void registerCallbacks() {
mBackgroundHandler.post(mStartListeningRunnable);
}
scss
private final Runnable mStartListeningRunnable = new Runnable() {
@Override
public void run() {
//..
//具体见下边,主要观察亮度模式的改变以及display的改变
mBrightnessObserver.startObserving();
//监听用户的改变,刷新数据
mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
//获取亮度模式,是否是自动模式
mUpdateModeRunnable.run();
//获取亮度最大最小值以及当前值,并设置给seekbar
mUpdateSliderRunnable.run();
//给BrightnessSliderController设置listener,具体见下边handler
mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
}
};
>mHandler
java
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mExternalChange = true;
try {
switch (msg.what) {
case MSG_UPDATE_SLIDER:
updateSlider(Float.intBitsToFloat(msg.arg1), msg.arg2 != 0);
break;
case MSG_ATTACH_LISTENER:
//设置listener,具体回调见下边
mControl.setOnChangedListener(BrightnessController.this);
break;
//..
default:
super.handleMessage(msg);
}
} finally {
mExternalChange = false;
}
}
};
>updateSlider
arduino
private void updateSlider(float brightnessValue, boolean inVrMode) {
//..
// convertGammaToLinearFloat returns 0-1
if (BrightnessSynchronizer.floatEquals(brightnessValue,
convertGammaToLinearFloat(mControl.getValue(), min, max))) {
//seekbar里的值和要修改的值一样,那就返回
return;
}
//把亮度值转化成seekbar用的值
final int sliderVal = convertLinearToGammaFloat(brightnessValue, min, max);
//给seekbar设置当前值
animateSliderTo(sliderVal);
}
>onChanged
这个就是6.2小节里seekbar的监听器里调用的listener
java
public void onChanged(boolean tracking, int value, boolean stopTracking) {
//..
if (mIsVrModeEnabled) {
} else {
minBacklight = mBrightnessMin;
maxBacklight = mBrightnessMax;
}
//这里是把seekbar的进度转化成亮度float
final float valFloat = MathUtils.min(
convertGammaToLinearFloat(value, minBacklight, maxBacklight),
maxBacklight);
//设置临时亮度
setBrightness(valFloat);
if (!tracking) {
//停止拖动,设置最终亮度
AsyncTask.execute(new Runnable() {
public void run() {
mDisplayManager.setBrightness(mDisplayId, valFloat);
}
});
}
}
//
arduino
private void setBrightness(float brightness) {
mDisplayManager.setTemporaryBrightness(mDisplayId, brightness);
}
>BrightnessObserver
java
private class BrightnessObserver extends ContentObserver {
BrightnessObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (selfChange) return;
if (BRIGHTNESS_MODE_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
} else if (BRIGHTNESS_FOR_VR_FLOAT_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateSliderRunnable);
} else {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
}
}
public void startObserving() {
final ContentResolver cr = mContext.getContentResolver();
cr.unregisterContentObserver(this);
//亮度模式的监听
cr.registerContentObserver(
BRIGHTNESS_MODE_URI,
false, this, UserHandle.USER_ALL);
cr.registerContentObserver(
BRIGHTNESS_FOR_VR_FLOAT_URI,
false, this, UserHandle.USER_ALL);
//监听display的改变,监听回调里执行的是下边的mUpdateSliderRunnable
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler,
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
public void stopObserving() {
final ContentResolver cr = mContext.getContentResolver();
cr.unregisterContentObserver(this);
mDisplayManager.unregisterDisplayListener(mDisplayListener);
}
}
>mUpdateSliderRunnable
ini
private final Runnable mUpdateSliderRunnable = new Runnable() {
@Override
public void run() {
final boolean inVrMode = mIsVrModeEnabled;
final BrightnessInfo info = mContext.getDisplay().getBrightnessInfo();
if (info == null) {
return;
}
mBrightnessMax = info.brightnessMaximum;
mBrightnessMin = info.brightnessMinimum;
//handler传递的是int值,所以这里把float变换为int值,之后在handler里再变换回来
final int valueAsIntBits = Float.floatToIntBits(info.brightness);
mHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
inVrMode ? 1 : 0).sendToTarget();
}
};
>setMirror
typescript
public void setMirror(BrightnessMirrorController controller) {
mControl.setMirrorControllerAndMirror(controller);
}
public void hideSlider() {
mControl.hideView();
}
public void showSlider() {
mControl.showView();
}
6.3.1.Factory
注解实例化,小节7用到
java
public static class Factory {
private final Context mContext;
private final UserTracker mUserTracker;
private final Executor mMainExecutor;
private final Handler mBackgroundHandler;
@Inject
public Factory(
Context context,
UserTracker userTracker,
@Main Executor mainExecutor,
@Background Handler bgHandler) {
mContext = context;
mUserTracker = userTracker;
mMainExecutor = mainExecutor;
mBackgroundHandler = bgHandler;
}
//从 7.1.可以看到,这里的slider就是mBrightnessSliderController
public BrightnessController create(ToggleSlider toggleSlider) {
return new BrightnessController(
mContext,
toggleSlider,
mUserTracker,
mMainExecutor,
mBackgroundHandler);
}
}
6.4.DisplayManager
6.3小节里,拖动亮度条修改亮度的最终代码有以下两种,一种临时的,一种最终的
ini
mDisplayManager.setTemporaryBrightness(mDisplayId, brightness);
mDisplayManager.setBrightness(mDisplayId, valFloat);
>DisplayManagerService.java
上边的两个方法,最终会走到这里
java
final class BinderService extends IDisplayManager.Stub {
public void setTemporaryBrightness(int displayId, float brightness) {
try {
synchronized (mSyncRoot) {
mDisplayPowerControllers.get(displayId)
.setTemporaryBrightness(brightness);
}
}
}
public void setBrightness(int displayId, float brightness) {
if (!isValidBrightness(brightness)) {
return;
}
try {
synchronized (mSyncRoot) {
DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
//这里会修改dataStore的数据,具体见下边
dpc.setBrightness(brightness);
}
//这个保存数据
mPersistentDataStore.saveIfNeeded();
}
}
}
>setBrightness
arduino
void setBrightness(float brightnessValue) {
mBrightnessSetting.setBrightness(brightnessValue);
}
//如果发生了变化,修改下dataStore的数据
ini
void setBrightness(float brightness) {
if (Float.isNaN(brightness)) {
return;
}
synchronized (mSyncRoot) {
if (brightness != mBrightness) {
mPersistentDataStore.setBrightness(mLogicalDisplay.getPrimaryDisplayDeviceLocked(),
brightness);
}
mBrightness = brightness;
int toSend = Float.floatToIntBits(mBrightness);
Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED, toSend, 0);
mHandler.sendMessage(msg);
}
}
>setTemporaryBrightness
java
public void setTemporaryBrightness(float brightness) {
Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
Float.floatToIntBits(brightness), 0 /*unused*/);
msg.sendToTarget();
}
最终就是更新power state
ini
case MSG_SET_TEMPORARY_BRIGHTNESS:
mTemporaryScreenBrightness = Float.intBitsToFloat(msg.arg1);
updatePowerState();
7.QSPanelController.java
7.1.构造方法
- 注解实例化的
- brightnessControllerFactory 也是注解实例话的
- brightnessSliderFactory 注解实例化的
less
@Inject
QSPanelController(QSPanel view, TunerService tunerService,
QSTileHost qstileHost, QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QS_PANEL) MediaHost mediaHost,
QSTileRevealController.Factory qsTileRevealControllerFactory,
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
FalsingManager falsingManager,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
FeatureFlags featureFlags) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
mFalsingManager = falsingManager;
//通过factory里的create方法生成
mBrightnessSliderController = brightnessSliderFactory.create(getContext(), mView);
//mView就是上边的QSPanel,可以看到,亮度条是动态添加到容器里的
mView.setBrightnessView(mBrightnessSliderController.getRootView());
//通过factory里的create方法生成
mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
//
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mView.setUsingCombinedHeaders(featureFlags.isEnabled(COMBINED_QS_HEADERS));
}
7.2.mBrightnessController相关
scss
public void setListening(boolean listening, boolean expanded) {
setListening(listening && expanded);
if (listening) {
mBrightnessController.registerCallbacks();
} else {
mBrightnessController.unregisterCallbacks();
}
}
scss
public void refreshAllTiles() {
//设置亮度是否可以调节,也就是seekbar是否可以拖动
mBrightnessController.checkRestrictionAndSetEnabled();
super.refreshAllTiles();
}
7.3.mBrightnessMirrorHandler相关
>onViewAttached
scss
protected void onViewAttached() {
super.onViewAttached();
updateMediaDisappearParameters();
mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
mView.updateResources();
if (mView.isListening()) {
refreshAllTiles();
}
switchTileLayout(true);
//
mBrightnessMirrorHandler.onQsPanelAttached();
PagedTileLayout pagedTileLayout= ((PagedTileLayout) mView.getOrCreateTileLayout());
pagedTileLayout.setOnTouchListener(mTileLayoutTouchListener);
}
>setBrightnessMirror
typescript
public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
mBrightnessMirrorHandler.setController(brightnessMirrorController);
}
7.4.BrightnessMirrorHandler.kt
构造方法里的参数就是 6.3小节里的 BrightnessController
kotlin
class BrightnessMirrorHandler(private val brightnessController: MirroredBrightnessController) {
private var mirrorController: BrightnessMirrorController? = null
private val brightnessMirrorListener = BrightnessMirrorListener { updateBrightnessMirror() }
//设置镜像控制器
fun setController(controller: BrightnessMirrorController) {
mirrorController?.removeCallback(brightnessMirrorListener)
mirrorController = controller
mirrorController?.addCallback(brightnessMirrorListener)
//把镜像控制器传递给亮度控制器
updateBrightnessMirror()
}
private fun updateBrightnessMirror() {
mirrorController?.let { brightnessController.setMirror(it) }
}
fun onQsPanelAttached() {
mirrorController?.addCallback(brightnessMirrorListener)
}
7.5.mirrorController来源
搜一下
>QSFragment.java
typescript
public void setBrightnessMirrorController(
BrightnessMirrorController brightnessMirrorController) {
mQSPanelController.setBrightnessMirror(brightnessMirrorController);
}
>CentralSurfacesImpl.java
在QSFragment创建成功以后设置的
scss
// Set up the quick settings tile panel
final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
if (container != null) {
FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
mExtensionController
.newExtension(QS.class)
.withPlugin(QS.class)
.withDefault(this::createDefaultQSFragment)
.build());
//初始化镜像控制器
mBrightnessMirrorController = new BrightnessMirrorController(
mNotificationShadeWindowView,
mNotificationPanelViewController,
mNotificationShadeDepthControllerLazy.get(),
mBrightnessSliderFactory,
//这个是镜像滑动条可见性改变的回调
(visible) -> {
mBrightnessMirrorVisible = visible;
//镜像滑动条可见的时候,整个下拉状态栏透明度改为0了
updateScrimController();
});
fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
QS qs = (QS) f;
if (qs instanceof QSFragment) {
mQSPanelController = ((QSFragment) qs).getQSPanelController();
//设置
((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);
}
});
}
8.BrightnessMirrorController
镜像亮度条的控制器
8.1.构造方法
ini
public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
NotificationPanelViewController notificationPanelViewController,
NotificationShadeDepthController notificationShadeDepthController,
BrightnessSliderController.Factory factory,
@NonNull Consumer<Boolean> visibilityCallback) {
mStatusBarWindow = statusBarWindow;
mToggleSliderFactory = factory;
//镜像亮度条的容器,帧布局
mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror_container);
mToggleSliderController = setMirrorLayout();
mNotificationPanel = notificationPanelViewController;
mDepthController = notificationShadeDepthController;
mNotificationPanel.setPanelAlphaEndAction(() -> {
//透明度变为255的时候,动画结束会调用
mBrightnessMirror.setVisibility(View.INVISIBLE);
});
mVisibilityCallback = visibilityCallback;
updateResources();
}
8.2.setMirrorLayout
ini
private BrightnessSliderController setMirrorLayout() {
Context context = mBrightnessMirror.getContext();
//创建一个亮度滑动条控制器
BrightnessSliderController controller = mToggleSliderFactory.create(context,
mBrightnessMirror);
controller.init();
//把控制器里的亮度条加载到容器里
mBrightnessMirror.addView(controller.getRootView(), ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
return controller;
}
8.3.showMirror&hideMirror
qs面板里拖动亮度seebar的时候,会调用下边的方法显示隐藏镜像拖动条
csharp
public void showMirror() {
//容器可见
mBrightnessMirror.setVisibility(View.VISIBLE);
//回调返回true,表示镜像可见
mVisibilityCallback.accept(true);
//下拉面板透明度设置为0,不可见
mNotificationPanel.setPanelAlpha(0, true /* animate */);
mDepthController.setBrightnessMirrorVisible(true);
}
public void hideMirror() {
//和show方法相比少个setVisibility,其实在构造方法里有设置,监听的是透明度改变动画结束
//回调返回false,表示镜像不可见
mVisibilityCallback.accept(false);
//下拉面板透明度恢复255,可见
mNotificationPanel.setPanelAlpha(255, true /* animate */);
mDepthController.setBrightnessMirrorVisible(false);
}
8.4.setLocationAndSize
- 亮度拖动条开始拖动的时候调用的,和showMirror方法一起的,见 6.2
- 根据原始的滑动条和镜像的位置,进行平移,保证两者在同一位置
ini
public void setLocationAndSize(View original) {
//先获取原本的滑动条在窗口的为主
original.getLocationInWindow(mInt2Cache);
// Original is slightly larger than the mirror, so make sure to use the center for the
// positioning.
int originalX = mInt2Cache[0] - mBrightnessMirrorBackgroundPadding;
int originalY = mInt2Cache[1] - mBrightnessMirrorBackgroundPadding;
mBrightnessMirror.setTranslationX(0);
mBrightnessMirror.setTranslationY(0);
mBrightnessMirror.getLocationInWindow(mInt2Cache);
int mirrorX = mInt2Cache[0];
int mirrorY = mInt2Cache[1];
mBrightnessMirror.setTranslationX(originalX - mirrorX);
mBrightnessMirror.setTranslationY(originalY - mirrorY);
// Set the brightness mirror container to be the width of the mirror + 2 times the padding
int newWidth = original.getMeasuredWidth() + 2 * mBrightnessMirrorBackgroundPadding;
if (newWidth != mLastBrightnessSliderWidth) {
ViewGroup.LayoutParams lp = mBrightnessMirror.getLayoutParams();
lp.width = newWidth;
mBrightnessMirror.setLayoutParams(lp);
}
}
9.DisplaySettings.java
我们主要看下,这边的亮度调节逻辑
arduino
private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
//控制器
controllers.add(new BrightnessLevelPreferenceController(context, lifecycle));
return controllers;
}
9.1.display_settings.xml
ini
<PreferenceCategory
android:title="@string/category_name_brightness">
<com.android.settingslib.RestrictedPreference
android:key="brightness"
android:title="@string/brightness"
settings:keywords="@string/keywords_display_brightness_level"
settings:useAdminDisabledSummary="true"
settings:userRestriction="no_config_brightness"/>
<!--自动调节亮度的,默认不可见,具体见controller-->
<com.android.settingslib.PrimarySwitchPreference
android:key="auto_brightness_entry"
android:title="@string/auto_brightness_title"
android:fragment="com.android.settings.display.AutoBrightnessSettings"
settings:controller="com.android.settings.display.AutoBrightnessPreferenceController"/>
</PreferenceCategory>
9.2.BrightnessLevelPreferenceController
>onStart
注册监听器,最终都是修改summary的值
scss
public void onStart() {
mContentResolver.registerContentObserver(BRIGHTNESS_FOR_VR_URI, false, mBrightnessObserver);
mContentResolver.registerContentObserver(BRIGHTNESS_ADJ_URI, false, mBrightnessObserver);
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler,
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
updatedSummary(mPreference);
}
scss
private void updatedSummary(Preference preference) {
if (preference != null) {
//格式化成百分比
preference.setSummary(NumberFormat.getPercentInstance().format(getCurrentBrightness()));
}
}
>getCurrentBrightness
scss
private double getCurrentBrightness() {
int value = 0;
if (isInVrMode()) {
} else {
final BrightnessInfo info = mContext.getDisplay().getBrightnessInfo();
if (info != null) {
//先转化为Gamma值,0到65535之间的值
value = convertLinearToGammaFloat(info.brightness, info.brightnessMinimum,
info.brightnessMaximum);
}
}
//算百分比,0到65535之间
return getPercentage(value, GAMMA_SPACE_MIN, GAMMA_SPACE_MAX);
}
>handlePreferenceTreeClick
可以看到,点击以后是跳转了一个页面去了
less
public boolean handlePreferenceTreeClick(@androidx.annotation.NonNull Preference preference) {
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
final Intent intent = new Intent(ACTION_SHOW_BRIGHTNESS_DIALOG);
intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
SettingsTransitionHelper.TransitionType.TRANSITION_NONE);
// Start activity in the same task and pass fade animations
final ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext,
android.R.anim.fade_in, android.R.anim.fade_out);
mContext.startActivityForResult(preference.getKey(), intent, 0, options.toBundle());
return true;
}
Intent里的隐藏action,搜一下
arduino
public static final String ACTION_SHOW_BRIGHTNESS_DIALOG =
"com.android.intent.action.SHOW_BRIGHTNESS_DIALOG";
9.3.BrightnessDialog
SystemUI里的
>清单文件
看下主题,dialog样式的
ini
<activity
android:name=".settings.brightness.BrightnessDialog"
android:label="@string/quick_settings_brightness_dialog_title"
android:theme="@style/Theme.SystemUI.QuickSettings.BrightnessDialog"
android:finishOnCloseSystemDialogs="true"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:exported="true">
<intent-filter>
<action android:name="com.android.intent.action.SHOW_BRIGHTNESS_DIALOG" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
>构造方法
注解实例化的,又看到BrightnessSliderController.Factory了
less
@Inject
public BrightnessDialog(
UserTracker userTracker,
BrightnessSliderController.Factory factory,
@Main Executor mainExecutor,
@Background Handler bgHandler) {
mUserTracker = userTracker;
mToggleSliderFactory = factory;
mMainExecutor = mainExecutor;
mBackgroundHandler = bgHandler;
}
>brightness_mirror_container.xml
ini
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@style/Theme.SystemUI.QuickSettings"
android:id="@+id/brightness_mirror_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/brightness_mirror_background"
android:layout_gravity="center_vertical"
android:layout_margin="8dp"
android:gravity="center"
android:visibility="invisible">
</FrameLayout>
>onCreate
ini
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Window window = getWindow();
//顶部居中,无标题
window.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.requestFeature(Window.FEATURE_NO_TITLE);
window.getDecorView();
window.setLayout(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
setContentView(R.layout.brightness_mirror_container);
//容器就一个帧布局
FrameLayout frame = findViewById(R.id.brightness_mirror_container);
//布局里默认不可见,这里修改为可见
frame.setVisibility(View.VISIBLE);
//设置顶部,左右的margin
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) frame.getLayoutParams();
int horizontalMargin =
getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
lp.leftMargin = horizontalMargin;
lp.rightMargin = horizontalMargin;
frame.setLayoutParams(lp);
Rect bounds = new Rect();
frame.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
bounds.set(-horizontalMargin, 0, right - left + horizontalMargin, bottom - top);
v.setSystemGestureExclusionRects(List.of(bounds));
});
//创建controller
BrightnessSliderController controller = mToggleSliderFactory.create(this, frame);
controller.init();
//把控制器里的滑动条添加进来
frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
mBrightnessController = new BrightnessController(
this, controller, mUserTracker, mMainExecutor, mBackgroundHandler);
}
10.app里亮度修改
上边分析的都是设备的亮度,最后我们看下app里咋修改亮度
10.1.setAttributes
>修改亮度
ini
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.screenBrightness = f;
getWindow().setAttributes(layoutParams);
>setAttributes
scss
public void setAttributes(WindowManager.LayoutParams a) {
mWindowAttributes.copyFrom(a);
dispatchWindowAttributesChanged(mWindowAttributes);
}
>dispatchWindowAttributesChanged
callback就是Activity
typescript
protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
if (mCallback != null) {
mCallback.onWindowAttributesChanged(attrs);
}
}
10.2.getWindow
Activity.java
>attach方法
scss
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
//..
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
//..
mWindowManager = mWindow.getWindowManager();
>onWindowAttributesChanged
csharp
public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
if (mParent == null) {
View decor = mDecor;
if (decor != null && decor.getParent() != null) {
getWindowManager().updateViewLayout(decor, params);
if (mContentCaptureManager != null) {
mContentCaptureManager.updateWindowAttributes(params);
}
}
}
}
10.3.PhoneWindow
scala
public class PhoneWindow extends Window implements MenuBuilder.Callback {
>setWindowManager
父类Window里的方法,可以看到mWindowManager是WindowManagerImpl对象
ini
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated;
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
10.4.WindowManagerImpl
java
public final class WindowManagerImpl implements WindowManager {
>createLocalWindowManager
typescript
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);
}
>构造方法
less
private WindowManagerImpl(Context context, Window parentWindow,
@Nullable IBinder windowContextToken) {
mContext = context;
mParentWindow = parentWindow;
mWindowContextToken = windowContextToken;
}
>updateViewLayout
less
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyTokens(params);
mGlobal.updateViewLayout(view, params);
}
10.5.WindowManagerGlobal.java
ini
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
//.
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
view.setLayoutParams(wparams);
synchronized (mLock) {
int index = findViewLocked(view, true);
ViewRootImpl root = mRoots.get(index);
mParams.remove(index);
mParams.add(index, wparams);
root.setLayoutParams(wparams, false);
}
}
10.6.ViewRootImpl.java
kotlin
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks,
AttachedSurfaceControl {
>setLayoutParams
看了半天,没找到和亮度有关的,那应该不是这里控制的,这里负责刷新ui
ini
public void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
synchronized (this) {
final int oldInsetLeft = mWindowAttributes.surfaceInsets.left;
final int oldInsetTop = mWindowAttributes.surfaceInsets.top;
final int oldInsetRight = mWindowAttributes.surfaceInsets.right;
final int oldInsetBottom = mWindowAttributes.surfaceInsets.bottom;
final int oldSoftInputMode = mWindowAttributes.softInputMode;
final boolean oldHasManualSurfaceInsets = mWindowAttributes.hasManualSurfaceInsets;
// Keep track of the actual window flags supplied by the client.
mClientWindowLayoutFlags = attrs.flags;
// Preserve compatible window flag if exists.
final int compatibleWindowFlag = mWindowAttributes.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
// Preserve system UI visibility.
final int systemUiVisibility = mWindowAttributes.systemUiVisibility;
final int subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
// Preserve appearance and behavior.
final int appearance = mWindowAttributes.insetsFlags.appearance;
final int behavior = mWindowAttributes.insetsFlags.behavior;
final int appearanceAndBehaviorPrivateFlags = mWindowAttributes.privateFlags
& (PRIVATE_FLAG_APPEARANCE_CONTROLLED | PRIVATE_FLAG_BEHAVIOR_CONTROLLED);
final int changes = mWindowAttributes.copyFrom(attrs);
if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
// Recompute system ui visibility.
mAttachInfo.mRecomputeGlobalAttributes = true;
}
if ((changes & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) {
// Request to update light center.
mAttachInfo.mNeedsUpdateLightCenter = true;
}
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
// Restore preserved flags.
mWindowAttributes.systemUiVisibility = systemUiVisibility;
mWindowAttributes.subtreeSystemUiVisibility = subtreeSystemUiVisibility;
mWindowAttributes.insetsFlags.appearance = appearance;
mWindowAttributes.insetsFlags.behavior = behavior;
mWindowAttributes.privateFlags |= compatibleWindowFlag
| appearanceAndBehaviorPrivateFlags
| WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
if (mWindowAttributes.preservePreviousSurfaceInsets) {
// Restore old surface insets.
mWindowAttributes.surfaceInsets.set(
oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
} else if (mWindowAttributes.surfaceInsets.left != oldInsetLeft
|| mWindowAttributes.surfaceInsets.top != oldInsetTop
|| mWindowAttributes.surfaceInsets.right != oldInsetRight
|| mWindowAttributes.surfaceInsets.bottom != oldInsetBottom) {
mNeedsRendererSetup = true;
}
applyKeepScreenOnFlag(mWindowAttributes);
if (newView) {
mSoftInputMode = attrs.softInputMode;
requestLayout();
}
// Don't lose the mode we last auto-computed.
if ((attrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
& ~SOFT_INPUT_MASK_ADJUST) | (oldSoftInputMode & SOFT_INPUT_MASK_ADJUST);
}
if (mWindowAttributes.softInputMode != oldSoftInputMode) {
requestFitSystemWindows();
}
mWindowAttributesChanged = true;
scheduleTraversals();
}
}
10.7.RootWindowContainer.java
ini
class RootWindowContainer extends WindowContainer<DisplayContent>
implements DisplayManager.DisplayListener {
//这个值和亮度有关,所以看下相关的方法
private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
RootWindowContainer(WindowManagerService service) {
super(service);
mHandler = new MyHandler(service.mH.getLooper());
mService = service.mAtmService;
mTaskSupervisor = mService.mTaskSupervisor;
mTaskSupervisor.mRootWindowContainer = this;
mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG);
}
>performSurfacePlacement
- 正常应该只有被WindowSurfacePlacer调用,当然也有非正常的
ini
/**
* This method should only be called from {@link WindowSurfacePlacer}. Otherwise the recursion
* check and {@link WindowSurfacePlacer#isInLayout()} won't take effect.
*/
void performSurfacePlacement() {
try {
performSurfacePlacementNoTrace();
}
}
void performSurfacePlacementNoTrace() {
int i;
//..
//屏幕亮度覆写值,默认是NaN
mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mUserActivityTimeout = -1;
mObscureApplicationContentOnSecondaryDisplays = false;
mSustainedPerformanceModeCurrent = false;
mWmService.mTransactionSequence++;
final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
mWmService.openSurfaceTransaction();
try {
//开启transaction
applySurfaceChangesTransaction();
} finally {
mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
}
// Send any pending task-info changes that were queued-up during a layout deferment
mWmService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
mWmService.mAtmService.mTaskFragmentOrganizerController.dispatchPendingEvents();
mWmService.mSyncEngine.onSurfacePlacement();
mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();
checkAppTransitionReady(surfacePlacer);
// Defer starting the recents animation until the wallpaper has drawn
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
if (recentsAnimationController != null) {
recentsAnimationController.checkAnimationReady(defaultDisplay.mWallpaperController);
}
final BackNaviAnimationController bnac = mWmService.getBackNaviAnimationController();
if (bnac != null) {
bnac.checkAnimationReady(defaultDisplay.mWallpaperController);
}
for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
final DisplayContent displayContent = mChildren.get(displayNdx);
if (displayContent.mWallpaperMayChange) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
}
if (mWmService.mFocusMayChange) {
mWmService.mFocusMayChange = false;
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
false /*updateInputWindows*/);
}
if (isLayoutNeeded()) {
defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
}
handleResizingWindows();
if (mOrientationChangeComplete) {
if (mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
mWmService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
mWmService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
}
mWmService.stopFreezingDisplayLocked();
}
//销毁所有不可见的窗口纹理
i = mWmService.mDestroySurface.size();
if (i > 0) {
do {
i--;
WindowState win = mWmService.mDestroySurface.get(i);
win.mDestroying = false;
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent.mInputMethodWindow == win) {
displayContent.setInputMethodWindowLocked(null);
}
if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
win.destroySurfaceUnchecked();
} while (i > 0);
mWmService.mDestroySurface.clear();
}
for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
final DisplayContent displayContent = mChildren.get(displayNdx);
if (displayContent.pendingLayoutChanges != 0) {
displayContent.setLayoutNeeded();
}
}
if (!mWmService.mDisplayFrozen) {
//获取亮度覆写值,mScreenBrightnessOverride值的修改看后边的handle方法
final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN
|| mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX
? PowerManager.BRIGHTNESS_INVALID_FLOAT : mScreenBrightnessOverride;
int brightnessFloatAsIntBits = Float.floatToIntBits(brightnessOverride);
//交给powerManager去处理了
mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightnessFloatAsIntBits,
0).sendToTarget();
mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
}
if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
mWmService.mPowerManagerInternal.setPowerMode(
Mode.SUSTAINED_PERFORMANCE,
mSustainedPerformanceModeEnabled);
}
if (mUpdateRotation) {
//旋转角度更新
mUpdateRotation = updateRotationUnchecked();
}
if (!mWmService.mWaitingForDrawnCallbacks.isEmpty()
|| (mOrientationChangeComplete && !isLayoutNeeded()
&& !mUpdateRotation)) {
mWmService.checkDrawnWindowsLocked();
}
forAllDisplays(dc -> {
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
dc.updateSystemGestureExclusion();
dc.updateKeepClearAreas();
dc.updateTouchExcludeRegion();
});
mWmService.enableScreenIfNeededLocked();
mWmService.scheduleAnimationLocked();
}
//SET_SCREEN_BRIGHTNESS_OVERRIDE
typescript
public void handleMessage(Message msg) {
switch (msg.what) {
case SET_SCREEN_BRIGHTNESS_OVERRIDE:
mWmService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
Float.intBitsToFloat(msg.arg1));
break;
>applySurfaceChangesTransaction
ini
private void applySurfaceChangesTransaction() {
final DisplayContent defaultDc = mDefaultDisplay;
final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
final int defaultDw = defaultInfo.logicalWidth;
final int defaultDh = defaultInfo.logicalHeight;
final SurfaceControl.Transaction t = defaultDc.getSyncTransaction();
if (mWmService.mWatermark != null) {
mWmService.mWatermark.positionSurface(defaultDw, defaultDh, t);
}
if (mWmService.mStrictModeFlash != null) {
mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, t);
}
if (mWmService.mEmulatorDisplayOverlay != null) {
mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
defaultDc.getRotation(), t);
}
final int count = mChildren.size();
for (int j = 0; j < count; ++j) {
final DisplayContent dc = mChildren.get(j);
//这个方法里有个地方会调用到下边的handleNotObscuredLocked方法
dc.applySurfaceChangesTransaction();
}
mWmService.mDisplayManagerInternal.performTraversal(t);
if (t != defaultDc.mSyncTransaction) {
SurfaceControl.mergeToGlobalTransaction(t);
}
}
>handleNotObscuredLocked
- 在这个方法里,mScreenBrightnessOverride的值被修改了
- 调用的地方在DisplayContent.java里的applySurfaceChangesTransaction方法
ini
boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
final WindowManager.LayoutParams attrs = w.mAttrs;
final int attrFlags = attrs.flags;
final boolean onScreen = w.isOnScreen();
final boolean canBeSeen = w.isDisplayed();
final int privateflags = attrs.privateFlags;
boolean displayHasContent = false;
//..
if (w.mHasSurface && canBeSeen) {
if (!syswin && w.mAttrs.screenBrightness >= 0
&& Float.isNaN(mScreenBrightnessOverride)) {
//获取app里通过window设置的屏幕亮度
mScreenBrightnessOverride = w.mAttrs.screenBrightness;
}
final int type = attrs.type;
//...
}
return displayHasContent;
}
10.8.WindowSurfacePlacer.java
>requestTraversal
请求遍历
ini
void requestTraversal() {
if (mTraversalScheduled) {
return;
}
mTraversalScheduled = true;
if (mDeferDepth > 0) {
mDeferredRequests++;
return;
}
//交给一个runnable处理
mService.mAnimationHandler.post(mPerformSurfacePlacement);
}
>mPerformSurfacePlacement
这个对象就是个runnable
java
private final Traverser mPerformSurfacePlacement = new Traverser();
private class Traverser implements Runnable {
@Override
public void run() {
synchronized (mService.mGlobalLock) {
performSurfacePlacement();
}
}
}
>performSurfacePlacement
ini
final void performSurfacePlacement() {
performSurfacePlacement(false /* force */);
}
final void performSurfacePlacement(boolean force) {
if (mDeferDepth > 0 && !force) {
mDeferredRequests++;
return;
}
int loopCount = 6;
do {
mTraversalScheduled = false;
performSurfacePlacementLoop();
mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
loopCount--;
} while (mTraversalScheduled && loopCount > 0);
mService.mRoot.mWallpaperActionPending = false;
}
>performSurfacePlacementLoop
ini
private void performSurfacePlacementLoop() {
if (mInLayout) {
return;
}
final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
if (defaultDisplay.mWaitingForConfig) {
//配置发生了改变,返回
return;
}
if (!mService.mDisplayReady) {
//服务还没初始化完整,返回.
return;
}
mInLayout = true;
if (!mService.mForceRemoves.isEmpty()) {
// Wait a little bit for things to settle down, and off we go.
while (!mService.mForceRemoves.isEmpty()) {
final WindowState ws = mService.mForceRemoves.remove(0);
//手动立马移除
ws.removeImmediately();
}
Object tmp = new Object();
synchronized (tmp) {
try {
tmp.wait(250);
} catch (InterruptedException e) {
}
}
}
try {
//这个mRoot就是10.7小节的对象
mService.mRoot.performSurfacePlacement();
mInLayout = false;
if (mService.mRoot.isLayoutNeeded()) {
if (++mLayoutRepeatCount < 6) {
requestTraversal();
} else {
mLayoutRepeatCount = 0;
}
} else {
mLayoutRepeatCount = 0;
}
if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
}
}
}
10.9.PowerManagerService.java
>setScreenBrightnessOverrideFromWindowManager
scala
final class LocalService extends PowerManagerInternal {
@Override
public void setScreenBrightnessOverrideFromWindowManager(float screenBrightness) {
if (screenBrightness < PowerManager.BRIGHTNESS_MIN
|| screenBrightness > PowerManager.BRIGHTNESS_MAX) {
screenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
}
>setScreenBrightnessOverrideFromWindowManagerInternal
scss
private void setScreenBrightnessOverrideFromWindowManagerInternal(float brightness) {
synchronized (mLock) {
if (!BrightnessSynchronizer.floatEquals(mScreenBrightnessOverrideFromWindowManager,
brightness)) {
mScreenBrightnessOverrideFromWindowManager = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
>updatePowerStateLocked
scss
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
return;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
mUpdatePowerStateInProgress = true;
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
updateScreenBrightnessBoostLocked(mDirty);
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = mClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Lock profiles that became inactive/not kept awake.
updateProfilesLocked(now);
// Phase 3: Update power state of all PowerGroups.
//这个方法里会调用修改后的亮度值
final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);
// Phase 4: Update dream state (depends on power group ready signal).
updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);
// Phase 5: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 6: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
mUpdatePowerStateInProgress = false;
}
}
>updatePowerGroupsLocked
ini
private boolean updatePowerGroupsLocked(int dirty) {
final boolean oldPowerGroupsReady = areAllPowerGroupsReadyLocked();
//先判断下dirty是否有下边一堆标志里某一个,有的话表示有变化,才会进行操作
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_WAKEFULNESS)) != 0) {
//..
for (int idx = 0; idx < mPowerGroups.size(); idx++) {
final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
final int groupId = powerGroup.getGroupId();
// Determine appropriate screen brightness.
final float screenBrightnessOverride;
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
screenBrightnessOverride = mScreenBrightnessDefault;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
//判断下有效性,0到1之间
screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
} else {
//无效的话,就改为默认的NaN
screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
//后边再看就是这个powerGroup里的方法了
boolean ready = powerGroup.updateLocked(screenBrightnessOverride,//..;
int wakefulness = powerGroup.getWakefulnessLocked();
final boolean displayReadyStateChanged = powerGroup.setReadyLocked(ready);
final boolean poweringOn = powerGroup.isPoweringOnLocked();
if (ready && displayReadyStateChanged && poweringOn
&& wakefulness == WAKEFULNESS_AWAKE) {
powerGroup.setIsPoweringOnLocked(false);
LatencyTracker.getInstance(mContext).onActionEnd(ACTION_TURN_ON_SCREEN);
}
}
mRequestWaitForNegativeProximity = false;
}
return areAllPowerGroupsReadyLocked() && !oldPowerGroupsReady;
}
10.10.DisplayPowerController.java
>updatePowerState
这个方法里,有对亮度的各种判断
10.11.BrightnessSynchronizer.java
- 拖动亮度条不会走这里,结束的时候才会走这里,应该和onDisplayChanged的回调有关
- 有如下的观察者,监听BRIGHTNESS_URI的变化,以及display变化的监听mListener
ini
void startObserving(Handler handler) {
final ContentResolver cr = mContext.getContentResolver();
cr.registerContentObserver(BRIGHTNESS_URI, false,
createBrightnessContentObserver(handler), UserHandle.USER_ALL);
mDisplayManager.registerDisplayListener(mListener, handler,
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
mIsObserving = true;
}
监听到变化,会走到runUpdate方法,里边会执行BrightnessUpdate对象的update方法,里边会保存 Settings.System.SCREEN_BRIGHTNESS的值
ini
void update() {
if (mState == STATE_NOT_STARTED) {
mState = STATE_RUNNING;
// check if we need to update int
int brightnessInt = getBrightnessAsInt();
if (mLatestIntBrightness != brightnessInt) {
Settings.System.putIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, brightnessInt,
UserHandle.USER_CURRENT);
mLatestIntBrightness = brightnessInt;
mUpdatedTypes |= TYPE_INT;
}
blog.csdn.net/weixin_4508... blog.csdn.net/Sunxiaolin2...
11.日志反推
11.1.测试代码和日志
ini
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.screenBrightness = f;
getWindow().setAttributes(layoutParams);
日志如下,可以看到,这边的brigthness override是从0到1变化的
csharp
Line 13504: 08-11 14:14:55.910 1875 2010 D Brightness-Debug: setScreenBrightnessOverrideFromWindowManagerInternal: brightness is 0.99607843
Line 13523: 08-11 14:15:03.001 1875 2010 D Brightness-Debug: setScreenBrightnessOverrideFromWindowManager: screenBrightness is 1.0
可另外一个日志,如下,到了0.725后边就没日志了,按道理也应该到1
ini
Line 12093: 08-11 14:06:39.041 1875 2681 D Brightness-Debug: Updating screen state: id=0, state=ON, backlight=0.72156864, sdrBacklight=0.72156864
Line 12122: 08-11 14:06:46.141 1875 2681 D Brightness-Debug: Updating screen state: id=0, state=ON, backlight=0.7254903, sdrBacklight=0.7254903
11.2.DisplayPowerState.java
>PhotonicModulator
上边有问题的日志就在下边这个线程里
ini
//在线程里异步更新屏幕状态以及背光
private final class PhotonicModulator extends Thread {
//更新状态
public boolean setState(int state, float brightnessState, float sdrBrightnessState) {
synchronized (mLock) {
boolean stateChanged = state != mPendingState;
boolean backlightChanged = brightnessState != mPendingBacklight
|| sdrBrightnessState != mPendingSdrBacklight;
if (stateChanged || backlightChanged) {
mPendingState = state;
mPendingBacklight = brightnessState;
mPendingSdrBacklight = sdrBrightnessState;
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged || mStateChangeInProgress;
mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
if (!changeInProgress) {
//空闲的话释放锁
mLock.notifyAll();
}
}
return !mStateChangeInProgress;
}
}
public void run() {
//可以看到是个死循环
for (;;) {
// Get pending change.
final int state;
final boolean stateChanged;
final float brightnessState;
final float sdrBrightnessState;
final boolean backlightChanged;
synchronized (mLock) {
state = mPendingState;
stateChanged = (state != mActualState);
brightnessState = mPendingBacklight;
sdrBrightnessState = mPendingSdrBacklight;
backlightChanged = brightnessState != mActualBacklight
|| sdrBrightnessState != mActualSdrBacklight;
if (!stateChanged) {
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;
}
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
boolean valid = state != Display.STATE_UNKNOWN && !Float.isNaN(brightnessState);
boolean changed = stateChanged || backlightChanged;
if (!valid || !changed) {
mStateChangeInProgress = false;
mBacklightChangeInProgress = false;
try {
//数据没有变化或者状态无效的话,等待锁
mLock.wait();
} catch (InterruptedException ex) {
//只有外部把stop参数改为true的时候,才可能跳出循环。
if (mStopped) {
return;
}
}
continue;
}
mActualState = state;
mActualBacklight = brightnessState;
mActualSdrBacklight = sdrBrightnessState;
}
// 这就是我们看到的日志
if (DEBUG) {
Slog.d(TAG, "Updating screen state: id=" + mDisplayId + ", state="
+ Display.stateToString(state) + ", backlight=" + brightnessState
+ ", sdrBacklight=" + sdrBrightnessState);
}
mBlanker.requestDisplayState(mDisplayId, state, brightnessState,
sdrBrightnessState);
}
}
>线程开启
构造方法里实例化并启动
ini
DisplayPowerState(
DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState) {
mHandler = new Handler(true /*async*/);
mChoreographer = Choreographer.getInstance();
mBlanker = blanker;
mColorFade = colorFade;
//实例化并启动线程
mPhotonicModulator = new PhotonicModulator();
mPhotonicModulator.start();
>stop
中断所有正在运行的线程;停止未来的工作。这个方法应该在DisplayPowerState不再使用时调用;也就是说,当显示器被移除时
ini
public void stop() {
//停止标志
mStopped = true;
//中断线程
mPhotonicModulator.interrupt();
dismissColorFade();
mCleanListener = null;
mHandler.removeCallbacksAndMessages(null);
}
>mScreenUpdateRunnable
可以看到是在下边的线程里修改状态的
ini
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
float brightnessState = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
float sdrBrightnessState = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f
? mSdrScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
//修改状态
if (mPhotonicModulator.setState(mScreenState, brightnessState, sdrBrightnessState)) {
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
}
}
};
这里调用
csharp
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
11.3.DisplayPowerController.java
- 反推stop的调用逻辑
- 从上边的分析知道,日志出问题说明那个线程被中断了,那就看看stop哪里调用的
>cleanupHandlerThreadAfterStop
csharp
private void cleanupHandlerThreadAfterStop() {
//..
final float brightness = mPowerState != null
? mPowerState.getScreenBrightness()
: PowerManager.BRIGHTNESS_MIN;
reportStats(brightness);
if (mPowerState != null) {
//这里stop了
mPowerState.stop();
mPowerState = null;
}
}
>stop
arduino
case MSG_STOP:
cleanupHandlerThreadAfterStop();
break;
ini
public void stop() {
synchronized (mLock) {
mStopped = true;
Message msg = mHandler.obtainMessage(MSG_STOP);
mHandler.sendMessage(msg);
11.4.DisplayManagerService.java
>handleLogicalDisplayRemovedLocked
less
private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
final int displayId = display.getDisplayIdLocked();
final DisplayPowerController dpc = mDisplayPowerControllers.removeReturnOld(displayId);
if (dpc != null) {
dpc.stop();
}
mDisplayStates.delete(displayId);
mDisplayBrightnesses.delete(displayId);
>updateLogicalDisplaysLocked
arduino
case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED:
handleLogicalDisplayRemovedLocked(display);
break;
11.5.LogicalDisplayMapper.java
>updateLogicalDisplaysLocked
scss
private void updateLogicalDisplaysLocked() {
//...
//这里发送的event
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED);
>>onDisplayDeviceEventLocked
csharp
public void onDisplayDeviceEventLocked(DisplayDevice device, int event) {
switch (event) {
case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_ADDED:
handleDisplayDeviceAddedLocked(device);
break;
case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_CHANGED:
finishStateTransitionLocked(false /*force*/);
updateLogicalDisplaysLocked(); //111
break;
case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_REMOVED:
handleDisplayDeviceRemovedLocked(device);
updateLogicalDisplaysLocked(); //2222
break;
}
}
>>setDeviceStateLocked
scss
void setDeviceStateLocked(int state, boolean isOverrideActive) {
resetLayoutLocked(mDeviceState, state, /* isStateChangeStarting= */ true);
mPendingDeviceState = state;
final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState,
mInteractive, mBootCompleted);
final boolean sleepDevice = shouldDeviceBePutToSleep(mPendingDeviceState, mDeviceState,
isOverrideActive, mInteractive, mBootCompleted);
// If all displays are off already, we can just transition here, unless we are trying to
// wake or sleep the device as part of this transition. In that case defer the final
// transition until later once the device is awake/asleep.
if (areAllTransitioningDisplaysOffLocked() && !wakeDevice && !sleepDevice) {
transitionToPendingStateLocked();
return;
}
// Send the transitioning phase updates to DisplayManager so that the displays can
// start turning OFF in preparation for the new layout.
updateLogicalDisplaysLocked(); //3333
>>transitionToPendingStateLocked
ini
private void transitionToPendingStateLocked() {
resetLayoutLocked(mDeviceState, mPendingDeviceState, /* isStateChangeStarting= */ false);
mDeviceState = mPendingDeviceState;
mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
applyLayoutLocked();
updateLogicalDisplaysLocked();//44444
}
>>handleDisplayDeviceAddedLocked
scss
private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
// The default Display needs to have additional initialization.
// This initializes a default dynamic display layout for the default
// device, which is used as a fallback in case no static layout definitions
// exist or cannot be loaded.
if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0) {
initializeDefaultDisplayDeviceLocked(device);
}
// Create a logical display for the new display device
LogicalDisplay display = createNewLogicalDisplayLocked(
device, Layout.assignDisplayIdLocked(false /*isDefault*/));
applyLayoutLocked();
updateLogicalDisplaysLocked();//55555
}
12.总结
- 学习下系统首次启动,默认的屏幕亮度哪里配置的
- 学习下下拉状态栏那个亮度条的操作逻辑
- 学习下settings,display下的亮度设置
- 最后简单学习下app里修改页面亮度的逻辑,比较乱,只知道WindowManager.LayoutParams修改以后,最终判定页面需要刷新,