Android中所有系统的定义:lights.h
--------------------------
#define LIGHT_ID_BACKLIGHT          "backlight"


JNI: com_android_server_lights_LightsService.cpp
---------------------------
setLight_native:调用HAL去控制背光


Service:LightsService.java
-------------------------------
1.它是各种灯光和背光的Service,提供了对背光灯操作的所有方法
2.setLightLocked():是实际调用JNI操作背光灯的函数,所有向应用程序公开的LCD操作接口都使用synchronized (this){... setLightLocked() ...}
确保互斥访问硬件。
3.onStart()中:publishLocalService(LightsManager.class, mService);

DisplayPowerController.java
----------------------------------
1.获取LightsService中注册的LightsManager:mLights = LocalServices.getService(LightsManager.class);
2.然后在构造函数中只获取了背光灯:new DisplayPowerState(mBlanker, mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT), new ColorFade(Display.DEFAULT_DISPLAY)); 整个系统中也只有这里获取了背光灯。

DisplayPowerState.java
-----------------------------------
DisplayPowerState(DisplayBlanker blanker, Light backlight, ColorFade electronBeam)
    --> mPhotonicModulator = new PhotonicModulator();
    --> mPhotonicModulator.start();
        --> run() //无限循环执行这个线程
            --> mLock.wait(); //睡眠
            --> setBrightness(backlight);

在setState()中notifyAll(); //唤醒

在mScreenUpdateRunnable中调用了setState()
private final Runnable mScreenUpdateRunnable = new Runnable() {
    mPhotonicModulator.setState(mScreenState, brightness);
}

mScreenUpdateRunnable作为一个处理消息的响应线程
postScreenUpdateThreadSafe中mHandler.post(mScreenUpdateRunnable);

scheduleScreenUpdate()
    --> postScreenUpdateThreadSafe();

由上,也就是调用scheduleScreenUpdate()来触发向消息队列中存放一个消息,消息处理函数中notifyAll()然后在上面无限循环的
run()中设置背光亮度。

DisplayPowerState
    --> scheduleScreenUpdate
setScreenState
    --> scheduleScreenUpdate
setScreenBrightness
    --> scheduleScreenUpdate
setColorFadeLevel
    --> scheduleScreenUpdate


DisplayPowerController.java
-------------------------
    --> new DisplayPowerState()
    --> animateScreenStateChange //在updatePowerState中被调用

处理消息:
Handler的handleMessage中调用updatePowerState
updatePowerState()
    animateScreenStateChange //这里面设置背光亮度

发送消息:
requestPowerState
    sendUpdatePowerStateLocked //基本上所有操作都是通过它执行的,也就是这个函数对上层做基础支持。
        mHandler.sendMessage(msg); //它通过发送消息在Handler的handleMessage中处理

updateDisplayPowerStateLocked
    requestPowerState

什么时候发消息:
PowerManagerService.java
----------------------------
updatePowerStateLocked
    updateDisplayPowerStateLocked

systemReady方法中:
(1)注册了4个Receiver
eg:
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
当数据库中的Intent.ACTION_BATTERY_CHANGED变化的时候,BatteryReceiver的onReceive()就会被调用。

(2)对于背光灯还注册了1个ContentObserver
resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.SCREENSAVER_ENABLED),
                    false, mSettingsObserver, UserHandle.USER_ALL);
当数据库中Settings.Secure.SCREENSAVER_ENABLED变化的时候,mSettingsObserver中的onChange()方法就会被调用。

Receiver                监听的事件
BatteryReceiver            ACTION_BATTERY_CHANGED
DreamReceiver            ACTION_DREAMING_STARTED
UserSwitchedReceiver    ACTION_USER_SWITCHED
DockReceiver            ACTION_DOCK_EVENT


mSettingsObserver
SCREENSAVER_ENABLED                    屏保功能开启
SCREENSAVER_ACTIVATE_ON_SLEEP        在睡眠时屏保启动
SCREENSAVER_ACTIVATE_ON_DOCK        连接底座并且屏保启动
SCREEN_OFF_TIMEOUT                    进入dream状态前未活动时间
SLEEP_TIMEOUT                        进入sleep状态前未活动时间
STAY_ON_WHILE_PLUGGED_IN            有插入并且屏幕开启
SCREEN_BRIGHTNESS                    屏幕亮度
SCREEN_BRIGHTNESS_MODE                屏幕亮度模式
SCREEN_AUTO_BRIGHTNESS_ADJ
LOW_POWER_MODE
LOW_POWER_MODE_TRIGGER_LEVEL

 

2.使用到内容观察者模式

使用方法:
1.创建一个 ContentObserver 的子类,实现 onChange() 方法。
private final class SettingsObserver extends ContentObserver {
    public SettingsObserver(Handler handler) {
        super(handler);
    }

    /*目的是复写这个onChange方法*/
    @Override
    public void onChange(boolean selfChange, Uri uri) {
        synchronized (mLock) {
            /*它里面也是去调用updatePowerStateLocked*/
            handleSettingsChangedLocked();
        }
    }
}

2.注册 ContentObserver
/*
arg1:需要监听的 uri。
arg2:为 false 表示精确匹配,即只匹配该 Uri。为 true 表示可以同时匹配其派生的 Uri,如:
    content://com.qin.cb/student(精确匹配)
    content://com.qin.cb/student/# (派生,false 才能匹配到)
    content://com.qin.cb/student/schoolchild(派生,false 才能匹配到)
arg3:ContentObserver 的实例。
*/
registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED),
    false, mSettingsObserver, UserHandle.USER_ALL);

3.用完后记得取消注册 ContentObserver
unregisterContentObserver(myContentObserver)

参考:
ContentObserver:https://www.jianshu.com/p/3bc164010b5f

 

3.App测试Demo MainActivity.java

package com.example.mm.lcd_brightness;

import android.os.Bundle;
import android.provider.Settings;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SeekBar;

public class MainActivity extends AppCompatActivity {
    final private int LED_NOTIFICATION_ID = 123;
    private SeekBar mBacklightSeekBar = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mBacklightSeekBar = (SeekBar)findViewById(R.id.seekBar);

        try {
            /*将背光调节模式改为手动,无为自动的话手动调节无效*/
            Settings.System.putInt(getContentResolver(),
                    Settings.System.SCREEN_BRIGHTNESS_MODE,
                    Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);

            /*让滚动条的初始状态显示在正确的位置*/
            int brightness = android.provider.Settings.System.getInt(getContentResolver(),
                    android.provider.Settings.System.SCREEN_BRIGHTNESS);
            mBacklightSeekBar.setProgress(brightness*100/255);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }

        /*设置滚动条的监听函数*/
        mBacklightSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener (){
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                int brightness = mBacklightSeekBar.getProgress();
                /*应用程序传入的是0--100,而底层是0--255*/
                brightness = brightness * 255 / 100;

                /*设置到数据库中,会导致内容观察者对应的设置屏幕亮度的方法被调用*/
                android.provider.Settings.System.putInt(getContentResolver(),
                        android.provider.Settings.System.SCREEN_BRIGHTNESS, brightness);

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                Log.d("App_Brightness: ","==============onStartTrackingTouch===============");
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Log.d("App_Brightness: ","==============onStartTrackingTouch===============");
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
View Code

相关文章: