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修改以后,最终判定页面需要刷新,
相关推荐
花生糖@1 小时前
Android XR 应用程序开发 | 从 Unity 6 开发准备到应用程序构建的步骤
android·unity·xr·android xr
是程序喵呀1 小时前
MySQL备份
android·mysql·adb
casual_clover1 小时前
Android 之 List 简述
android·list
锋风Fengfeng2 小时前
安卓15预置第三方apk时签名报错问题解决
android
User_undefined3 小时前
uniapp Native.js原生arr插件服务发送广播到uniapp页面中
android·javascript·uni-app
程序员厉飞雨4 小时前
Android R8 耗时优化
android·java·前端
丘狸尾5 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~7 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads11 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu12 小时前
Android4.4 在系统中添加自己的System Service
android