前言
Android设备与用户进行交互往往通过屏幕进行,目前市场手机设备对于屏幕越来月看重,oled、高刷、大尺寸、全色域等都是各大厂商的pk项,目的都是为了提高设备的交互体验,同时现在大多数设备都已支持屏幕亮度自适应动态调节,自动根据环境亮度调节屏幕显示亮度。那么设备开机时屏幕是如何亮起来的呢?待机时屏幕是如何熄灭的呢?以及由室外走进室内屏幕亮度如何自适应调节呢?
本文基于Android 10从开机亮屏、关机熄屏和自动亮度调节三个方面介绍系统屏幕亮度控制实现。


一、开机亮屏流程

屏幕的控制主要涉及PowerManagerService(PMS)、DisplayManagerService(DMS)、DisplayPowerController(DPC)几个类,先讲讲这几个类的主要作用:

  • PowerManagerService:负责管理,协调设备电源以及设备常用功能如亮灭屏、亮度调节、低电量模式、保持CPU唤醒等。
  • DisplayManagerService:管理显示设备生命周期,添加,移除,状态更新,在状态更新时向系统和其他应用发送通知等。
  • DisplayPowerController:用于控制显示电源状态,处理屏亮灭及其动画,背光调节等。
    开机亮屏的时序图如下:

    上述流程涉及的代码及路径如下:
    frameworks\base\core\java\android\os\PowerManager.java
    frameworks\base\core\java\android\view\SurfaceControl.java
    frameworks\base\core\jni\android_view_SurfaceControl.cpp
    frameworks\base\core\res\res\values\config.xml
    frameworks\base\packages\SettingsProvider\res\values\defaults.xml
    frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
    frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java
    frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java
    frameworks\base\services\core\java\com\android\server\display\RampAnimator.java
    frameworks\base\services\core\java\com\android\server\lights\LightsService.java
    frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
    frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
    frameworks\base\services\java\com\android\server\SystemServer.java
    frameworks\native\libs\gui\SurfaceComposerClient.cpp
    frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
    frameworks\native\services\surfaceflinger\DisplayHardware\ComposerHal.cpp
    hardware\qcom\display\sdm\libs\core\display_builtin.cpp
    hardware\qcom\display\sdm\libs\core\drm\hw_peripheral_drm.cpp
    hardware\qcom\display\sdm\libs\hwc2\hwc_session_services.cpp
    hardware\qcom\display\sdm\libs\hwc2\hwc_session.cpp
    hardware\qcom\display\sdm\libs\hwc2\hwc_display_builtin.cpp

1.1、DMS的启动

frameworks\base\services\java\com\android\server\SystemServer.java
DMS服务是在开机时由SystemServer启动的

private void startBootstrapServices() {
	// Display manager is needed to provide display metrics before package manager
	// starts up.
	traceBeginAndSlog("StartDisplayManager");
	mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);//启动DMS服务,调用DMS onStart()
	traceEnd();
	// We need the default display before we can initialize the package manager.
 	traceBeginAndSlog("WaitForDisplay");
	mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);//等待DMS启动完成后调用DMS onBootPhase()
	traceEnd();
}

接着进入DMS构造方法
frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

@VisibleForTesting
    DisplayManagerService(Context context, Injector injector) {//启动DMS进入构造方法
        super(context);
        mInjector = injector;
        mContext = context;
        mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
        mUiHandler = UiThread.getHandler();
        //创建mDisplayAdapterListener对象,继承自DisplayAdapter.Listener,负责给DMS传递各个DisplayAdapter中发出的事件
        mDisplayAdapterListener = new DisplayAdapterListener();
        //创建DisplayModeDirector对象,负责监听并选择系统中各类Display配置组合
        mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
        ...
        PowerManager pm = mContext.getSystemService(PowerManager.class);
        mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();//获取系统默认亮度值
        ...
        mSystemReady = false;
    }

frameworks\base\core\java\android\os\PowerManager.java

@UnsupportedAppUsage
    public int getDefaultScreenBrightnessSetting() {
        return mContext.getResources().getInteger(
                com.android.internal.R.integer.config_screenBrightnessSettingDefault);//从config.xml配置文件中获取默认系统亮度
    }

frameworks\base\core\res\res\values\config.xml

<!-- Default screen brightness setting.
         Must be in the range specified by minimum and maximum. -->
    <integer name="config_screenBrightnessSettingDefault">102</integer>//默认亮度为102

另外SettingsProvider中也有默认值,存入android数据库,两者应当一致
frameworks\base\packages\SettingsProvider\res\values\defaults.xml

<!-- Default screen brightness, from 0 to 255.  102 is 40%. -->
    <integer name="def_screen_brightness">102</integer>//默认亮度102
    <bool name="def_screen_brightness_automatic_mode">false</bool>//默认自动亮度调节

1.2、添加显示设备

继续回到DMS,走完DMS构造方法,接着进入onStart()
frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

@Override
    public void onStart() {
        ...
        synchronized (mSyncRoot) {
        	//1、加载本地持久化数据
            mPersistentDataStore.loadIfNeeded();
            loadStableDisplayValuesLocked();
        }
        //2、发送MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS 消息,注册默认display_adapters
        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
		//3、对外公布Binder、Local服务
        publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
                true /*allowIsolated*/);
        publishLocalService(DisplayManagerInternal.class, new LocalService());
    }
	...
	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();//接收onStart()发来的消息,并注册默认适配器
                    break;
                case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
                    registerAdditionalDisplayAdapters();//注册额外适配器
                    break;
                case MSG_DELIVER_DISPLAY_EVENT:
                    deliverDisplayEvent(msg.arg1, msg.arg2);//分发Display事件
                    break;
                ...
                case MSG_LOAD_BRIGHTNESS_CONFIGURATION:
                    loadBrightnessConfiguration();//加载并设置亮度配置数据
                    break;
            }
        }
    }

	private void registerDefaultDisplayAdapters() {
        // Register default display adapters.
        synchronized (mSyncRoot) {
            // main display adapter
            registerDisplayAdapterLocked(new LocalDisplayAdapter(
                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
            mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
                    mHandler, mDisplayAdapterListener);
            if (mVirtualDisplayAdapter != null) {
                registerDisplayAdapterLocked(mVirtualDisplayAdapter);
            }
        }
    }

	private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
        mDisplayAdapters.add(adapter);
        adapter.registerLocked();
    }

LocalDisplayAdapter 继承 DisplayAdapter ,主要为本地显示设备提供的适配器
frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java

@Override
    public void registerLocked() {
        super.registerLocked();
        mPhysicalDisplayEventReceiver = new PhysicalDisplayEventReceiver(getHandler().getLooper());
        for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
            tryConnectDisplayLocked(physicalDisplayId);//连接显示设备,传入物理设备id
       }
    }

	private void tryConnectDisplayLocked(long physicalDisplayId) {
       		...
            int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
            int[] allowedConfigs = SurfaceControl.getAllowedDisplayConfigs(displayToken);
            LocalDisplayDevice device = mDevices.get(physicalDisplayId);
            if (device == null) {
                // Display was added.
                final boolean isInternal = mDevices.size() == 0;
                device = new LocalDisplayDevice(displayToken, physicalDisplayId,
                        configs, activeConfig, allowedConfigs, colorModes, activeColorMode,
                        isInternal);
                mDevices.put(physicalDisplayId, device);
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);//通知本地设备连接成功
            } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
                        allowedConfigs, colorModes, activeColorMode)) {
                // Display properties changed.
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
            }
        } 
        ...
    }

frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

private final class DisplayAdapterListener implements DisplayAdapter.Listener {
        @Override
        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
            switch (event) {
                case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED://添加显示设备
                    handleDisplayDeviceAdded(device);
                    break;
                case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED://更改显示设备
                    handleDisplayDeviceChanged(device);
                    break;
                case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED://异常显示设备
                    handleDisplayDeviceRemoved(device);
                    break;
            }
        }

	private void handleDisplayDeviceAdded(DisplayDevice device) {
        synchronized (mSyncRoot) {
            handleDisplayDeviceAddedLocked(device);
        }
    }
    private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
        DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
        if (mDisplayDevices.contains(device)) {
            Slog.w(TAG, "Attempted to add already added display device: " + info);
            return;
        }
        device.mDebugLastLoggedDeviceInfo = info;
        mDisplayDevices.add(device);
        LogicalDisplay display = addLogicalDisplayLocked(device);
        Runnable work = updateDisplayStateLocked(device);//更新本地显示设备状态
        if (work != null) {
            work.run();
        }
        scheduleTraversalLocked(false);
    }

	private Runnable updateDisplayStateLocked(DisplayDevice device) {
        DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
        if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
        	//设置display全局状态和亮度值,mGlobalDisplayBrightness在上面构造函数中完成初始化
            return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
        }
        return null;
    }

frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java

private final class LocalDisplayDevice extends DisplayDevice {
		...
		@Override
        public Runnable requestDisplayStateLocked(final int state, final int brightness) {
            // Assume that the brightness is off if the display is being turned off.
            assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
            final boolean stateChanged = (mState != state);
            final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
            if (stateChanged || brightnessChanged) {
                final long physicalDisplayId = mPhysicalDisplayId;
                final IBinder token = getDisplayTokenLocked();
                final int oldState = mState;
                if (stateChanged) {
                    mState = state;
                    updateDeviceInfoLocked();//发送显示器状态改变消息
                }
                if (brightnessChanged) {
                    mBrightness = brightness;
                }
                // Defer actually setting the display state until after we have exited
                // the critical section since it can take hundreds of milliseconds
                // to complete.
                return new Runnable() {
                    @Override
                    public void run() {
                        // Exit a suspended state before making any changes.
                        int currentState = oldState;
                        if (Display.isSuspendedState(oldState)
                                || oldState == Display.STATE_UNKNOWN) {
                            if (!Display.isSuspendedState(state)) {
                                setDisplayState(state);
                                currentState = state;
                            } else if (state == Display.STATE_DOZE_SUSPEND
                                    || oldState == Display.STATE_DOZE_SUSPEND) {
                                setDisplayState(Display.STATE_DOZE);
                                currentState = Display.STATE_DOZE;
                            } else if (state == Display.STATE_ON_SUSPEND
                                    || oldState == Display.STATE_ON_SUSPEND) {
                                setDisplayState(Display.STATE_ON);
                                currentState = Display.STATE_ON;
                            } else {
                                return; // old state and new state is off
                            }
                        }
                        // If the state change was from or to VR, then we need to tell the light
                        // so that it can apply appropriate VR brightness settings. Also, update the
                        // brightness so the state is propogated to light.
                        boolean vrModeChange = false;
                        if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
                                currentState != state) {
                            setVrMode(state == Display.STATE_VR);
                            vrModeChange = true;
                        }
                        // Apply brightness changes given that we are in a non-suspended state.
                        if (brightnessChanged || vrModeChange) {
                            setDisplayBrightness(brightness);//设置显示亮度
                        }
                        // Enter the final desired state, possibly suspended.
                        if (state != currentState) {
                            setDisplayState(state);
                        }
                    }
                    private void setVrMode(boolean isVrEnabled) {
                        mBacklight.setVrMode(isVrEnabled);
                    }
                    private void setDisplayState(int state) {
                    	...
                    }

                    private void setDisplayBrightness(int brightness) {
                        Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
                                + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
                        try {
                            mBacklight.setBrightness(brightness);
                            Trace.traceCounter(Trace.TRACE_TAG_POWER,
                                    "ScreenBrightness", brightness);
                        } finally {
                            Trace.traceEnd(Trace.TRACE_TAG_POWER);
                        }
                    }
                };
            }
            return null;
        }
        ...
}

1.3、设置屏亮度数据

frameworks\base\services\core\java\com\android\server\lights\LightsService.java

@Override
        public void setBrightness(int brightness) {
            setBrightness(brightness, BRIGHTNESS_MODE_USER);
        }

        @Override
        public void setBrightness(int brightness, int brightnessMode) {
            synchronized (this) {
                // LOW_PERSISTENCE cannot be manually set
                if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
                    Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mId +
                            ": brightness=0x" + Integer.toHexString(brightness));
                    return;
                }
                // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
                // right now we just fall back to the old path through Lights brightessMode is
                // anything but USER or the device shouldBeInLowPersistenceMode().
                if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
                        && mSurfaceControlMaximumBrightness == 255) {
                    // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
                    // reason we enforce 255 right now is to stay consistent with the old path. In
                    // the future, the framework should be refactored so that brightness is a float
                    // between 0.0f and 1.0f, and the actual number of supported brightness levels
                    // is determined in the device-specific implementation.

					//通过SF(Surface)来设置显示亮度
                    SurfaceControl.setDisplayBrightness(mDisplayToken,
                            (float) brightness / mSurfaceControlMaximumBrightness);
                } else {
                    int color = brightness & 0x000000ff;
                    color = 0xff000000 | (color << 16) | (color << 8) | color;
                    //最终调用Light HAL来设置显示亮度
                    setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
                }
            }
        }

        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
            if (shouldBeInLowPersistenceMode()) {
                brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE;
            } else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
                brightnessMode = mLastBrightnessMode;
            }
            if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
                    offMS != mOffMS || mBrightnessMode != brightnessMode) {
                if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                        + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
                mInitialized = true;
                mLastColor = mColor;
                mColor = color;
                mMode = mode;
                mOnMS = onMS;
                mOffMS = offMS;
                mBrightnessMode = brightnessMode;
                Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
                        + Integer.toHexString(color) + ")");
                try {
                //调用native方法,通过jni往HAL调用
                    setLight_native(mId, color, mode, onMS, offMS, brightnessMode);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
                }
            }
        }

到这里可以看到,Android 10有两种设置屏幕亮度的方式

方式1:LightsService->SF->HWL HAL->设备节点->背光驱动

方式2:LightsService->Light HAL->设备节点->背光驱动

Android 11自动灭屏逻辑 安卓手机自动亮屏_java


Android 10 走方式1;Android 9 走方式2

frameworks\base\core\java\android\view\SurfaceControl.java

public static boolean setDisplayBrightness(IBinder displayToken, float brightness) {
        ...
        return nativeSetDisplayBrightness(displayToken, brightness);//调用本地方法
    }

frameworks\base\core\jni\android_view_SurfaceControl.cpp

static jboolean nativeSetDisplayBrightness(JNIEnv* env, jclass clazz, jobject displayTokenObject,
        jfloat brightness) {
    ...
    status_t error = SurfaceComposerClient::setDisplayBrightness(displayToken, brightness);
    return error == OK ? JNI_TRUE : JNI_FALSE;
}

frameworks\native\libs\gui\SurfaceComposerClient.cpp

status_t SurfaceComposerClient::setDisplayBrightness(const sp<IBinder>& displayToken,
                                                     float brightness) {
    return ComposerService::getComposerService()->setDisplayBrightness(displayToken, brightness);
}

frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken,
                                              float brightness) const {
    ...
    return getHwComposer().setDisplayBrightness(*displayId, brightness);
}

frameworks\native\services\surfaceflinger\DisplayHardware\ComposerHal.cpp

Error Composer::setDisplayBrightness(Display display, float brightness) {
    if (!mClient_2_3) {
        return Error::UNSUPPORTED;
    }
    return mClient_2_3->setDisplayBrightness(display, brightness);
}

hardware\qcom\display\sdm\libs\hwc2\hwc_session_services.cpp

int32_t HWCSession::setDisplayBrightness(uint32_t display, float brightness) {
  return SetDisplayBrightness(static_cast<hwc2_device_t *>(this),
                              static_cast<hwc2_display_t>(display), brightness);
}

hardware\qcom\display\sdm\libs\hwc2\hwc_session.cpp

int32_t HWCSession::SetDisplayBrightness(hwc2_device_t *device, hwc2_display_t display,
                                         float brightness) {
  ...
  HWCSession *hwc_session = static_cast<HWCSession *>(device);
  HWCDisplay *hwc_display = hwc_session->hwc_display_[display];
  if (!hwc_display) {
    return HWC2_ERROR_BAD_PARAMETER;
  }
  return INT32(hwc_display->SetPanelBrightness(brightness));
}

hardware\qcom\display\sdm\libs\hwc2\hwc_display_builtin.cpp

HWC2::Error HWCDisplayBuiltIn::SetPanelBrightness(float brightness) {
  DisplayError ret = display_intf_->SetPanelBrightness(brightness);
  ...
}

DisplayInterface接口SetPanelBrightness()最终在display_builtin.cpp中实现
hardware\qcom\display\sdm\libs\core\display_builtin.cpp

DisplayError DisplayBuiltIn::SetPanelBrightness(float brightness) {
  ...
  DisplayError err = kErrorNone;
  if ((err = hw_intf_->SetPanelBrightness(level)) == kErrorNone) {
    DLOGI_IF(kTagDisplay, "Setting brightness to level %d (%f percent)", level,
             brightness * 100);
  }
  return err;
}

hardware\qcom\display\sdm\libs\core\drm\hw_peripheral_drm.cpp

DisplayError HWPeripheralDRM::SetPanelBrightness(int level) {
  char buffer[kMaxSysfsCommandLength] = {0};
  if (brightness_base_path_.empty()) {
    return kErrorHardware;
  }
  std::string brightness_node(brightness_base_path_ + "brightness");
  int fd = Sys::open_(brightness_node.c_str(), O_RDWR);
  ...
  int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
  ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);//向背光文件节点brightness_base_path_ 写入数据,brightness_base_path_ 是在GetHWPanelMaxBrightness()获取最大屏亮度值设置的
  ...
}

void HWPeripheralDRM::GetHWPanelMaxBrightness() {
  char value[kMaxStringLength] = {0};
  hw_panel_info_.panel_max_brightness = 255.0f;
  char s[kMaxStringLength] = {};
  snprintf(s, sizeof(s), "/sys/class/backlight/panel%d-backlight/",
           static_cast<int>(connector_info_.type_id - 1));
  brightness_base_path_.assign(s);//设置亮度文件节点
  std::string brightness_node(brightness_base_path_ + "max_brightness");
  int fd = Sys::open_(brightness_node.c_str(), O_RDONLY);
  ...
}

后续流程则是驱动读写设备节点,到这里我们可以通过adb查看display的设备节点,并读取亮度值

#查看backlight设备节点
> adb shell ls -al sys/class/backlight
total 0
drwxr-xr-x  2 root root 0 1970-01-07 07:53 .
drwxr-xr-x 92 root root 0 1970-01-07 07:53 ..
lrwxrwxrwx  1 root root 0 1970-01-07 07:53 panel0-backlight -> ../../devices/platform/soc/5e00000.qcom,mdss_mdp/backlight/panel0-backlight

#查看屏背光节点文件
> adb shell ls -al sys/class/backlight/panel0-backlight/
total 0
drwxr-xr-x 3 root   root      0 1970-01-07 07:53 .
drwxr-xr-x 3 root   root      0 1970-01-07 07:53 ..
-r--r--r-- 1 root   root   4096 1970-01-07 07:53 actual_brightness
-rw-r--r-- 1 root   root   4096 1970-01-07 07:53 bl_power
-rw-r--r-- 1 system system 4096 1970-01-07 07:53 brightness
lrwxrwxrwx 1 root   root      0 1970-01-07 07:53 device -> ../../../5e00000.qcom,mdss_mdp
-r--r--r-- 1 system system 4096 1970-01-07 07:53 max_brightness
drwxr-xr-x 2 root   root      0 1970-01-07 07:53 power
lrwxrwxrwx 1 root   root      0 1970-01-07 07:53 subsystem -> ../../../../../../class/backlight
-r--r--r-- 1 root   root   4096 1970-01-07 07:53 type
-rw-r--r-- 1 root   root   4096 1970-01-07 07:53 uevent

#读取屏亮度
> adb shell cat sys/class/backlight/panel0-backlight/brightness
102

1.4、点亮屏幕

到这里屏幕默认亮度数据从framework经过hal写入了设备节点文件中,但亮屏还未亮起。具体流程如下:
PowerManagerService(PMS)在执行完构造方法、onStart()、OnBootPhase()后由SystemServer调用的systemReady()。
frameworks\base\services\java\com\android\server\SystemServer.java

traceBeginAndSlog("MakePowerManagerServiceReady");
        try {
            // TODO: use boot phase
            mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
        } catch (Throwable e) {
            reportWtf("making Power Manager Service ready", e);
        }
        traceEnd();

frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java

public void systemReady(IAppOpsService appOps) {
        synchronized (mLock) {
            mSystemReady = true;
            mAppOps = appOps;
            //获取各类本地和远程服务用于交互,如屏保DreamManager、电源BatteryStatsService、传感器SensorManager等。
            mDreamManager = getLocalService(DreamManagerInternal.class);
            mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
            mPolicy = getLocalService(WindowManagerPolicy.class);
            mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
            mAttentionDetector.systemReady(mContext);

            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
            mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();

            SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());

            // The notifier runs on the system server's main looper so as not to interfere
            // with the animations and other critical functions of the power manager.
            mBatteryStats = BatteryStatsService.getService();
            mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
                    mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
                    mPolicy);

            mWirelessChargerDetector = mInjector.createWirelessChargerDetector(sensorManager,
                    mInjector.createSuspendBlocker(
                            this, "PowerManagerService.WirelessChargerDetector"),
                    mHandler);
            mSettingsObserver = new SettingsObserver(mHandler);

            mLightsManager = getLocalService(LightsManager.class);
            mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);

			//初始化显示器电源管理,initPowerManagement()中实例化DPC(DisplayPowerController)
            // Initialize display power management.
            mDisplayManagerInternal.initPowerManagement(
                    mDisplayPowerCallbacks, mHandler, sensorManager);
            try {
                final ForegroundProfileObserver observer = new ForegroundProfileObserver();
                ActivityManager.getService().registerUserSwitchObserver(observer, TAG);
            } catch (RemoteException e) {
                // Shouldn't happen since in-process.
            }
            // Go.
            readConfigurationLocked();//读取配置文件默认值
            updateSettingsLocked();//更新Settings值
            mDirty |= DIRTY_BATTERY_STATE;
            updatePowerStateLocked();//更新电源状态
        }
        final ContentResolver resolver = mContext.getContentResolver();
        mConstants.start(resolver);
        mBatterySaverController.systemReady();
        mBatterySaverPolicy.systemReady();
		//注册SettingsObserver监听
        // Register for settings changes.
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                Settings.Secure.SCREENSAVER_ENABLED),
                false, mSettingsObserver, UserHandle.USER_ALL);
       			...
        
		//注册用于和其他System交互的广播
        // Register for broadcasts from other components of the system.
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
		...
    }

	private void updatePowerStateLocked() {
        	...
            // Phase 3: Update display power state.更显显示器电源状态,确认显示器是否准备好
            final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
			...
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    }

	private boolean updateDisplayPowerStateLocked(int dirty) {
        	...
            mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                    mRequestWaitForNegativeProximity);
            mRequestWaitForNegativeProximity = false;
            if ((dirty & DIRTY_QUIESCENT) != 0) {
                sQuiescent = false;
            }
            ...
    }

frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

@Override
        public boolean requestPowerState(DisplayPowerRequest request,
                boolean waitForNegativeProximity) {
            synchronized (mSyncRoot) {
                return mDisplayPowerController.requestPowerState(request,
                        waitForNegativeProximity);
            }
        }

frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java

public boolean requestPowerState(DisplayPowerRequest request,
            boolean waitForNegativeProximity) {
        synchronized (mLock) {
            ...
            if (changed && !mPendingRequestChangedLocked) {
                mPendingRequestChangedLocked = true;
                sendUpdatePowerStateLocked();//发送消息更新电源状态
            }
            return mDisplayReadyLocked;
        }
    }

	private void sendUpdatePowerStateLocked() {
        if (!mPendingUpdatePowerStateLocked) {
            mPendingUpdatePowerStateLocked = true;
            Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);//发送MSG_UPDATE_POWER_STATE消息
            mHandler.sendMessage(msg);
        }
    }

	private final class DisplayControllerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_POWER_STATE:
                    updatePowerState();
                    break;
        ...
	}

private void updatePowerState() {
    //当DisplayPowerController中更新屏幕状态成功后是否必须通知PMS
    final boolean mustNotify;
    boolean mustInitialize = false;
    //是否自动调节亮度调节值改变
    boolean autoBrightnessAdjustmentChanged = false;
    synchronized (mLock) {
        mPendingUpdatePowerStateLocked = false;
        if (mPendingRequestLocked == null) {
            return; // wait until first actual power request
        }
        if (mPowerRequest == null) {
            mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
            mWaitingForNegativeProximity = 
                  mPendingWaitForNegativeProximityLocked;
            mPendingWaitForNegativeProximityLocked = false;
            mPendingRequestChangedLocked = false;
            mustInitialize = true;
        } else if (mPendingRequestChangedLocked) {
            //自动调节亮度值是否改变,由"当前电源的请求状态"和"将要请求的电源请求状态"比较
            autoBrightnessAdjustmentChanged = 
                    (mPowerRequest.screenAutoBrightnessAdjustment
                    != mPendingRequestLocked.screenAutoBrightnessAdjustment);
            ...
        }
        mustNotify = !mDisplayReadyLocked;
    }
    if (mustInitialize) {
        //初始化亮灭屏动画、mPowerState等
        initialize();
    }
    int state;
    int brightness = PowerManager.BRIGHTNESS_DEFAULT;
    boolean performScreenOffTransition = false;
    //根据PMS中的请求参数决定屏幕状态和屏幕亮度值
    switch (mPowerRequest.policy) {
        //灭屏
        case DisplayPowerRequest.POLICY_OFF:
            ...
            //Doze模式
        case DisplayPowerRequest.POLICY_DOZE:
            ...
        //VR模式
        case DisplayPowerRequest.POLICY_VR:
            ...
        //DIM和亮屏
        case DisplayPowerRequest.POLICY_DIM:
        case DisplayPowerRequest.POLICY_BRIGHT:
        default:
            state = Display.STATE_ON;
            break;
    }
    assert(state != Display.STATE_UNKNOWN);
    ...
    //获取屏幕状态,此时还未设置新的屏幕状态,因此是”旧”的
    final int oldState = mPowerState.getScreenState();
    //在这个方法中会进行屏幕状态、亮度的设置和处理亮灭屏动画
    animateScreenStateChange(state, performScreenOffTransition);
    state = mPowerState.getScreenState();

    // Use zero brightness when screen is off.
    //如果屏幕状态为灭屏,设置亮度为0
    if (state == Display.STATE_OFF) {
        brightness = PowerManager.BRIGHTNESS_OFF;
    }
    ...
    //亮度调节值计算 BEG
    //brightnessboost相关
    if (mPowerRequest.boostScreenBrightness
            && brightness != PowerManager.BRIGHTNESS_OFF) {
        brightness = PowerManager.BRIGHTNESS_ON;
    }
    // Apply auto-brightness.
    boolean slowChange = false;
    //如果brightness=PowerManager.BRIGHTNESS_DEFAULT=-1,说明请求屏幕状态非Off
    if (brightness < 0) {//default = -1
        //如果自动调节亮度可用
        if (autoBrightnessEnabled) {
            //从AutomaticBrightnessController中获取自动调节亮度值
            brightness = 
                 mAutomaticBrightnessController.getAutomaticScreenBrightness();
        }
        if (brightness >= 0) {//说明使用了自动亮度
            // Use current auto-brightness value and slowly adjust to changes.
            //调整brightness保持在最小值和最大值之间
            //即mScreenBrightnessRangeMinimum <= brightness <= mScreenBrightnessRangeMaximum
            brightness = clampScreenBrightness(brightness);
            if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
                slowChange = true; // slowly adapt to auto-brightness
            }
            mAppliedAutoBrightness = true;//表示使用自动亮度

        } else {
            mAppliedAutoBrightness = false;
        }
    } else {
        mAppliedAutoBrightness = false;
    }
    //如果PMS中请求的屏幕状态为Doze,则将亮度设置为Doze状态的亮度
    if (brightness < 0 && (state == Display.STATE_DOZE
            || state == Display.STATE_DOZE_SUSPEND)) {
        brightness = mScreenBrightnessDozeConfig;
    }
    //如果此时brightness还为-1,说明没有使用自动调节亮度和doze状态亮度,则使用手动设置亮度
    if (brightness < 0) {
        //获取screenBrightness并在取值区间进行判断
        brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
    }
    // Apply dimming by at least some minimum amount when user activity
    // timeout is about to expire.
    //如果PMS中请求屏幕状态为Dim状态,则使用dim状态时的亮度,基于手动调节值
    if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
        if (brightness > mScreenBrightnessRangeMinimum) {
            brightness = Math.max(Math.min(brightness - 
            SCREEN_DIM_MINIMUM_REDUCTION,
                    mScreenBrightnessDimConfig), 
            mScreenBrightnessRangeMinimum);
        }
        if (!mAppliedDimming) {
            slowChange = false;
        }
        mAppliedDimming = true;//表示采用Dim状态brightness
    } else if (mAppliedDimming) {
        slowChange = false;
        mAppliedDimming = false;
    }
    ...
    //亮度动画
    if (!mPendingScreenOff) {
        //是否在亮屏时跳过亮度坡度调节,默认false
        if (mSkipScreenOnBrightnessRamp) {
            //如果屏幕状态为亮屏状态
            if (state == Display.STATE_ON) {
                if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
                    mInitialAutoBrightness = brightness;
                    mSkipRampState = RAMP_STATE_SKIP_INITIAL;
                } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
                        && mUseSoftwareAutoBrightnessConfig
                        && brightness != mInitialAutoBrightness) {
                    mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
                } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
                    mSkipRampState = RAMP_STATE_SKIP_NONE;
                }
            } else {
                mSkipRampState = RAMP_STATE_SKIP_NONE;
            }
        }
        //是否处于或将要进入VR状态
        boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
        //如果当前屏幕状态或请求屏幕状态为亮屏
        if ((state == Display.STATE_ON
                && mSkipRampState == RAMP_STATE_SKIP_NONE
                || state == Display.STATE_DOZE 
                && !mBrightnessBucketsInDozeConfig)
                && !wasOrWillBeInVr) {
            //设置亮度,slowChange=true应用于自动调节亮度
            animateScreenBrightness(brightness,
                    slowChange ? mBrightnessRampRateSlow : 
            mBrightnessRampRateFast);
        } else {
            //其他情况下不适用亮度动画,直接设置亮度
            animateScreenBrightness(brightness, 0);
        }
    }
   	...
}

总结一下,在updatePowerState()中:

  • 初始化相关变量
  • 调用animateScreenState()方法设置屏幕状态
  • 更新显示设备状态
  • 计算屏幕亮度值
  • 调用animateScreenBrightness()设置亮度动画
//1、initialize()初始化亮度调节动画
	private void initialize() {
        // Initialize the power state object for the default display.
        // In the future, we might manage multiple displays independently.
        mPowerState = new DisplayPowerState(mBlanker,
                mColorFadeEnabled ? new ColorFade(Display.DEFAULT_DISPLAY) : null);

        if (mColorFadeEnabled) {
        	//设置亮屏亮度动画
            mColorFadeOnAnimator = ObjectAnimator.ofFloat(
                    mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
            mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
            mColorFadeOnAnimator.addListener(mAnimatorListener);
			//设置熄屏亮度动画
            mColorFadeOffAnimator = ObjectAnimator.ofFloat(
                    mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
            mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
            mColorFadeOffAnimator.addListener(mAnimatorListener);
        }
        ...
        // Initialize all of the brightness tracking state
        final float brightness = convertToNits(mPowerState.getScreenBrightness());
        if (brightness >= 0.0f) {
            mBrightnessTracker.start(brightness);
        }
		...
    }

	//2、
	private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
        // If there is already an animation in progress, don't interfere with it.
        //亮度调节动画还未结束
        if (mColorFadeEnabled &&
                (mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
            if (target != Display.STATE_ON) {
                return;
            }
            // If display state changed to on, proceed and stop the color fade and turn screen on.
            mPendingScreenOff = false;
        }
		...
			//执行亮屏动画
            if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
                // Perform screen on animation.
                if (mPowerState.getColorFadeLevel() == 1.0f) {
                    mPowerState.dismissColorFade();
                } else if (mPowerState.prepareColorFade(mContext,
                        mColorFadeFadesConfig ?
                                ColorFade.MODE_FADE :
                                        ColorFade.MODE_WARM_UP)) {
                    mColorFadeOnAnimator.start();
                } else {
                    mColorFadeOnAnimator.end();
                }
            } else {
                // Skip screen on animation.
                //跳过亮屏动画
                mPowerState.setColorFadeLevel(1.0f);
                mPowerState.dismissColorFade();
            }
        } else if (target == Display.STATE_VR) {
            // Wait for brightness animation to complete beforehand when entering VR
            // from screen on to prevent a perceptible jump because brightness may operate
            // differently when the display is configured for dozing.
            if (mScreenBrightnessRampAnimator.isAnimating()
                    && mPowerState.getScreenState() == Display.STATE_ON) {
                return;
            }
            ...
            if (mPowerState.getColorFadeLevel() == 0.0f) {
                // Turn the screen off.
                // A black surface is already hiding the contents of the screen.
                setScreenState(Display.STATE_OFF);
                mPendingScreenOff = false;
                mPowerState.dismissColorFadeResources();
            } else if (performScreenOffTransition
                    && mPowerState.prepareColorFade(mContext,
                            mColorFadeFadesConfig ?
                                    ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
                    && mPowerState.getScreenState() != Display.STATE_OFF) {
                // Perform the screen off animation.执行熄屏动画
                mColorFadeOffAnimator.start();
            } else {
                // Skip the screen off animation and add a black surface to hide the
                // contents of the screen.
                //跳过熄屏动画,直接灭屏
                mColorFadeOffAnimator.end();
            }
        }
    }

	//设置亮度动画目标值
	private void animateScreenBrightness(int target, int rate) {
        if (DEBUG) {
            Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
        }
        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
            Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
            try {
                mBatteryStats.noteScreenBrightness(target);
            } catch (RemoteException ex) {
                // same process
            }
        }
    }

二、关机熄屏流程

从开机流程图中可以一瞥熄屏流程
同亮屏一样,在DPC updatePowerState()中设置熄屏亮度动画、更新熄屏状态和设置亮度值。
frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java

private boolean setScreenState(int state) {
        return setScreenState(state, false /*reportOnly*/);
    }

    private boolean setScreenState(int state, boolean reportOnly) {
        final boolean isOff = (state == Display.STATE_OFF);
        if (mPowerState.getScreenState() != state) {
            // If we are trying to turn screen off, give policy a chance to do something before we
            // actually turn the screen off.
            if (isOff && !mScreenOffBecauseOfProximity) {
                if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
                    setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
                    blockScreenOff();
                    mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);//PMS进行关机流程
                    unblockScreenOff();
                } else if (mPendingScreenOffUnblocker != null) {
                    // Abort doing the state change until screen off is unblocked.
                    return false;
                }
            }
        ...
        // Return true if the screen isn't blocked.
        return mPendingScreenOnUnblocker == null;
    }

frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java

@Override
    public void screenTurningOff(ScreenOffListener screenOffListener) {
        mWindowManagerFuncs.screenTurningOff(screenOffListener);
        synchronized (mLock) {
            if (mKeyguardDelegate != null) {
                mKeyguardDelegate.onScreenTurningOff();
            }
        }
    }

三、自动亮度调节

设计代码及其路径如下:

frameworks\base\core\res\res\values\config.xml

frameworks\base\core\java\android\os\PowerManager.java

frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessDialog.java

frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessController.java

frameworks\base\services\core\java\com\android\server\display\BrightnessMappingStrategy.java

frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

frameworks\base\services\core\java\com\android\server\display\AutomaticBrightnessController.java

在本小节通过调节系统设置亮度,分析系统是如何进行亮度自动调节的,代码时序图如下:

Android 11自动灭屏逻辑 安卓手机自动亮屏_android_02


在梳理亮度自动调节流程之前有必要先介绍点基本概念:

  • 环境光:表示真实环境的光亮度值,即照度,单位为lux。
  • Nit值:即尼特,表示人肉眼感知的光强度的单位。
  • 屏幕背光:即灰阶,范围0~255,由上层设置到驱动,并最终音效屏幕亮度的值。
  • 屏幕亮度:即屏幕的真实亮度。

从系统设置中调节亮度出发
frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessDialog.java

//在系统设置中点击亮度调节选项后,启用SystemUI的BrightnessDialog.java
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        final ToggleSliderView slider = findViewById(R.id.brightness_slider);
        mBrightnessController = new BrightnessController(this, slider);//实例化亮度控制器BrightnessController
    }

frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessController.java

public BrightnessController(Context context, ToggleSlider control) {
        mContext = context;
        mControl = control;
        mControl.setMax(GAMMA_SPACE_MAX);
        mBackgroundHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
        mUserTracker = new CurrentUserTracker(mContext) {
            @Override
            public void onUserSwitched(int newUserId) {
                mBackgroundHandler.post(mUpdateModeRunnable);
                mBackgroundHandler.post(mUpdateSliderRunnable);
            }
        };
        mBrightnessObserver = new BrightnessObserver(mHandler);//实例化mBrightnessObserver 
        PowerManager pm = context.getSystemService(PowerManager.class);
        //从配置文件中获取亮度最大255、最小0、默认值102、自动亮度开关等数据
        mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
        mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
        mDefaultBacklight = pm.getDefaultScreenBrightnessSetting();
        mMinimumBacklightForVr = pm.getMinimumScreenBrightnessForVrSetting();
        mMaximumBacklightForVr = pm.getMaximumScreenBrightnessForVrSetting();
        mDefaultBacklightForVr = pm.getDefaultScreenBrightnessForVrSetting();
        mAutomaticAvailable = context.getResources().getBoolean(
                com.android.internal.R.bool.config_automatic_brightness_available);
        mDisplayManager = context.getSystemService(DisplayManager.class);
        mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
                Context.VR_SERVICE));
    }
	//通过线程异步更新滑动UI
	private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mExternalChange = true;
            try {
                switch (msg.what) {
                    case MSG_UPDATE_SLIDER:
                        updateSlider(msg.arg1, msg.arg2 != 0);
                        break;
                    ...
        }
    };

	private void updateSlider(int val, boolean inVrMode) {
        final int min;
        final int max;
        if (inVrMode) {
            min = mMinimumBacklightForVr;
            max = mMaximumBacklightForVr;
        } else {
            min = mMinimumBacklight;
            max = mMaximumBacklight;
        }
        if (val == convertGammaToLinear(mControl.getValue(), min, max)) {
            // If we have more resolution on the slider than we do in the actual setting, then
            // multiple slider positions will map to the same setting value. Thus, if we see a
            // setting value here that maps to the current slider position, we don't bother to
            // calculate the new slider position since it may differ and look like a brightness
            // change to the user even though it isn't one.
            return;
        }
        final int sliderVal = convertLinearToGamma(val, min, max);//Gamma线性变化为亮度百分比值
        animateSliderTo(sliderVal);//动画更新UI亮度值
    }

	private void animateSliderTo(int target) {
        ...
        mSliderAnimator = ValueAnimator.ofInt(mControl.getValue(), target);
        mSliderAnimator.addUpdateListener((ValueAnimator animation) -> {
            mExternalChange = true;
            mControl.setValue((int) animation.getAnimatedValue());
            mExternalChange = false;
        });
        final long animationDuration = SLIDER_ANIMATION_DURATION * Math.abs(
                mControl.getValue() - target) / GAMMA_SPACE_MAX;
        mSliderAnimator.setDuration(animationDuration);
        mSliderAnimator.start();
    }

@Override
    public void onChanged(ToggleSlider toggleSlider, boolean tracking, boolean automatic,
            int value, boolean stopTracking) {
        ...
        final int val = convertGammaToLinear(value, min, max);//将百分比电量值Gamma线性转换
        ...
        setBrightness(val);
		...
    }

	private void setBrightness(int brightness) {
        mDisplayManager.setTemporaryBrightness(brightness);
    }

frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

@Override // Binder call
        public void setTemporaryBrightness(int brightness) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
                    "Permission required to set the display's brightness");
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mSyncRoot) {
                    mDisplayPowerController.setTemporaryBrightness(brightness);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java

public void setTemporaryBrightness(int brightness) {
        Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
                brightness, 0 /*unused*/);
        msg.sendToTarget();
    }

	private final class DisplayControllerHandler extends Handler {
        public DisplayControllerHandler(Looper looper) {
            super(looper, null, true /*async*/);
        }
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                ...
                case MSG_SET_TEMPORARY_BRIGHTNESS:
                    // TODO: Should we have a a timeout for the temporary brightness?
                    mTemporaryScreenBrightness = msg.arg1;//保存临时亮度值
                    updatePowerState();
                    break;

	private void updatePowerState() {
    	...
    	// Configure auto-brightness.
        if (mAutomaticBrightnessController != null) {
            hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
            //1、对自动亮度调节控制器进行配置
            mAutomaticBrightnessController.configure(autoBrightnessEnabled,
                    mBrightnessConfiguration,
                    mLastUserSetScreenBrightness / (float) PowerManager.BRIGHTNESS_ON,
                    userSetBrightnessChanged, autoBrightnessAdjustment,
                    autoBrightnessAdjustmentChanged, mPowerRequest.policy);
        }
    	if (brightness < 0) {//default = -1
        //如果自动调节亮度可用
        if (autoBrightnessEnabled) {
            //2、从AutomaticBrightnessController中获取自动调节亮度值
            brightness = 
                 mAutomaticBrightnessController.getAutomaticScreenBrightness();
        }
        if (brightness >= 0) {//说明使用了自动亮度
            brightness = clampScreenBrightness(brightness);
            if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
                slowChange = true; // slowly adapt to auto-brightness
            }
            mAppliedAutoBrightness = true;//表示使用自动亮度
        } else {
            mAppliedAutoBrightness = false;
        }
    } else {
        mAppliedAutoBrightness = false;
    }
    if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
        if (brightness > mScreenBrightnessRangeMinimum) {
            brightness = Math.max(Math.min(brightness - 
            SCREEN_DIM_MINIMUM_REDUCTION,
                    mScreenBrightnessDimConfig), 
            mScreenBrightnessRangeMinimum);
        }
        if (!mAppliedDimming) {
            slowChange = false;
        }
        mAppliedDimming = true;//表示采用Dim状态brightness
    } else if (mAppliedDimming) {
        slowChange = false;
        mAppliedDimming = false;
    }
    ...
            //设置亮度,slowChange=true应用于自动调节亮度
            animateScreenBrightness(brightness,
                    slowChange ? mBrightnessRampRateSlow : 
            mBrightnessRampRateFast);
        } else {
            //其他情况下不适用亮度动画,直接设置亮度
            animateScreenBrightness(brightness, 0);
        }
    }
   	...
}

frameworks\base\services\core\java\com\android\server\display\AutomaticBrightnessController.java

//1、配置AutomaticBrightnessController自动亮度调节控制器
	public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
            float brightness, boolean userChangedBrightness, float adjustment,
            boolean userChangedAutoBrightnessAdjustment, int displayPolicy) {
        ...
        //自动亮度值发生变化
        if (userInitiatedChange && enable && !dozing) {
            prepareBrightnessAdjustmentSample();
        }
        //注册/解除注册LightSensor,即开启自动调节亮度且非Doze状态下才可用
        changed |= setLightSensorEnabled(enable && !dozing);
        //调整自动亮度值
        if (changed) {
            updateAutoBrightness(false /*sendUpdate*/, userInitiatedChange);
        }
    }

	//更新自动亮度
	private void updateAutoBrightness(boolean sendUpdate, boolean isManuallySet) {
        if (!mAmbientLuxValid) {//光照强度值是否有效
            return;
        }
        //根据当前环境光照值从曲线中获取亮度值,并转成0~255内int值newScreenAutoBrightness
        //mAmbientLux由光照传感器监听光照发送变化时更新
        float value = mBrightnessMapper.getBrightness(mAmbientLux, mForegroundAppPackageName,
                mForegroundAppCategory);
        int newScreenAutoBrightness = Math.round(clampScreenBrightness(
                value * PowerManager.BRIGHTNESS_ON));
        ...
        if (mScreenAutoBrightness != newScreenAutoBrightness) {
            if (mLoggingEnabled) {
                Slog.d(TAG, "updateAutoBrightness: " +
                        "mScreenAutoBrightness=" + mScreenAutoBrightness + ", " +
                        "newScreenAutoBrightness=" + newScreenAutoBrightness);
            }

            mScreenAutoBrightness = newScreenAutoBrightness;//将最新的亮度值保存至mScreenAutoBrightness 
            mScreenBrighteningThreshold = clampScreenBrightness(
                    mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness));
            mScreenDarkeningThreshold = clampScreenBrightness(
                    mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness));
            if (sendUpdate) {
                mCallbacks.updateBrightness();
            }
        }
    }

	//2、获取处理后的自动亮度值
	public int getAutomaticScreenBrightness() {
        if (!mAmbientLuxValid) {//光照强度值是否有效
            return -1;
        }
        if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {
            return (int) (mScreenAutoBrightness * mDozeScaleFactor);
        }
        return mScreenAutoBrightness;//返回自动亮度值,而它则是在上面
    }

自此,通过LightSensor获取的光照数据–>最终计算出屏幕亮度。,结合config.xml默认的光照-亮度数组进行计算得到新的亮度值,从而实现自动调节屏幕亮度。
上述代码中未展开介绍调光相关的曲线配置:
frameworks\base\core\res\res\values\config.xml

...
    <integer-array name="config_autoBrightnessLevels"> //光感[Lux]数组,定义检测到的光照亮度
    </integer-array>

	<array name="config_autoBrightnessDisplayValuesNits">  // Lux值对应的Nits值数组[DisplayNits]
    </array>
    
	<integer-array name="config_screenBrightnessBacklight">  //与发光强度Nits值对应的背光值数组[BL]
    </integer-array>

	<array name="config_screenBrightnessNits">  //描述屏幕发光强度的[Nit]值数组
    </array>

上述数组Android源码默认没有配置,需要根据厂商的实际需要进行定制化配置。
Android系统提供的上述Lux、DisplayNit、BL、Nit四个数组配置曲线,两两分组得到两条曲线:

  • Lux - DisplayNit
  • Nit -BL
    其中DisplayNit与Nit是同一个值,这样光感强度Lux与屏幕背光亮度通过这两条曲线就连接起来了,整体大致过程如下:
    1、真实环境光照到设备光传感器
    2、光传感器上报感光Lux数据
    3、通过Lux - DisplayNit曲线,将Lux转化为了Nit值
    4、通过Nit - BL曲线将,Nit转化为背光值
    5、为了防止亮度设置过程中闪屏,调用animateScreenBrightness设置亮度动画

Android9.0之前直接是Lux - BL,只有config_autoBrightnessLevels数组,直接将sensor获取的lux转为BL,从9.0 开始引入其他三个配置,这是因为从光学角度而言,人肉眼感知的亮度是从屏幕反射到眼球中的光强度,而这个强度与光亮度Nit有一定关系,Nit又与Lux有关,所以严格考虑到光照度,光亮度,入射光、反射光等调节,相比通过Lux决定BL而言,通过Lux决定Nit,再由Nit决定BL使得亮度更加精准。

四、亮屏、熄屏广播

亮屏和熄屏时Notifier会发送相应的广播
frameworks\base\services\core\java\com\android\server\power\Notifier.java

mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
        mScreenOnIntent.addFlags(
                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
                | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
        mScreenOffIntent.addFlags(
                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
                | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
	...
    private void sendWakeUpBroadcast() {
		...
        if (mActivityManagerInternal.isSystemReady()) {
        	//亮屏广播发送完成后最后被mWakeUpBroadcastDone接收
            mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
                    mWakeUpBroadcastDone, mHandler, 0, null, null);
        } else {
            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
            sendNextBroadcast();
        }
    }

    private void sendGoToSleepBroadcast() {
        ...
        if (mActivityManagerInternal.isSystemReady()) {
        	//熄屏广播发送完成后最后被mWakeUpBroadcastDone接收
            mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
                    mGoToSleepBroadcastDone, mHandler, 0, null, null);
        } else {
            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
            sendNextBroadcast();
        }
    }

五、总结

在本文中,梳理了开机亮屏流程,熄屏流程,以及在AutoBrightness开启时,亮度调节流程。总结如下:

  • 亮屏和熄屏过程并不一定是直接亮的,而是存在亮度动画,逐渐亮屏和熄屏,可能是为了改善使用体验,例如晚上解锁手机屏幕过亮。
  • 亮度可以通过abd查看、修改数据库和屏亮度设备节点文件
$ adb shell settings get system screen_brightness
$ adb shell settings put system screen_brightness

$ adb shell cat sys/class/backlight/panelxxx/brightness
$ adb shell echo 255 > sys/class/backlight/panelxxx/brightness
  • 亮屏和熄屏系统都会发送对应的广播,可用于在亮屏或熄屏时执行某些动作
Intent.ACTION_SCREEN_ON //亮屏广播
Intent.ACTION_SCREEN_OFF//熄屏广播
  • 自动亮度调节原理是通过监听光传感器亮度发送变化时,根据环境的光亮结合可定制的亮度-光亮数组设置屏亮度,从而达到亮度自适应。