android framework13-brightness01

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修改以后,最终判定页面需要刷新,
相关推荐
雨白7 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹9 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空10 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭11 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日12 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安12 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑12 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟16 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡17 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0018 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体