Light

note: Android O

1 LightsService启动

/frameworks/base/services/java/com/android/server/SystemServer.java
[SystemServer.java::run()]

 private void run() {......// Start services.try {traceBeginAndSlog("StartServices");startBootstrapServices();startCoreServices();startOtherServices();SystemServerInitThreadPool.shutdown();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {traceEnd();}......}

/frameworks/base/services/java/com/android/server/SystemServer.java
[SystemServer.java::startBootstrapServices()]

    private void startBootstrapServices() {Slog.i(TAG, "Reading configuration...");final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";......// Manages LEDs and display backlight so we need it to bring up the display.traceBeginAndSlog("StartLightsService");mSystemServiceManager.startService(LightsService.class);traceEnd();.....}

/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
[SystemServiceManager.java::startService(Class serviceClass)]

    public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();Slog.i(TAG, "Starting " + name);Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);// Create the service.if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name+ ": service must extend " + SystemService.class.getName());}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {throw new RuntimeException("Failed to create service " + name+ ": service could not be instantiated", ex);} catch (IllegalAccessException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (NoSuchMethodException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (InvocationTargetException ex) {throw new RuntimeException("Failed to create service " + name+ ": service constructor threw an exception", ex);}startService(service);return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}}

/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
[SystemServiceManager.java::startService(@NonNull final SystemService service)]

    public void startService(@NonNull final SystemService service) {// Register it./**// Services that should receive lifecycle events.private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();*/mServices.add(service);// Start it.long time = System.currentTimeMillis();try {service.onStart();} catch (RuntimeException ex) {throw new RuntimeException("Failed to start service " + service.getClass().getName()+ ": onStart threw an exception", ex);}warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");}

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

[LightsService.java::onStart()]

    @Overridepublic void onStart() {publishLocalService(LightsManager.class, mService);}

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

[LightsService.java::mService]

    private final LightsManager mService = new LightsManager() {@Overridepublic Light getLight(int id) {if (0 <= id && id < LIGHT_ID_COUNT) {return mLights[id];} else {return null;}}};

/frameworks/base/services/core/java/com/android/server/lights/LightsManager.java
[LightsManager.java]

package com.android.server.lights;import android.hardware.light.V2_0.Type;public abstract class LightsManager {public static final int LIGHT_ID_BACKLIGHT = Type.BACKLIGHT;public static final int LIGHT_ID_KEYBOARD = Type.KEYBOARD;public static final int LIGHT_ID_BUTTONS = Type.BUTTONS;public static final int LIGHT_ID_BATTERY = Type.BATTERY;public static final int LIGHT_ID_NOTIFICATIONS = Type.NOTIFICATIONS;public static final int LIGHT_ID_ATTENTION = Type.ATTENTION;public static final int LIGHT_ID_BLUETOOTH = Type.BLUETOOTH;public static final int LIGHT_ID_WIFI = Type.WIFI;public static final int LIGHT_ID_COUNT = Type.COUNT;public abstract Light getLight(int id);
}

/frameworks/base/services/core/java/com/android/server/SystemService.java
[SystemService.java::publishLocalService(Class type, T service)]

    /*** Publish the service so it is only accessible to the system process.*/protected final <T> void publishLocalService(Class<T> type, T service) {LocalServices.addService(type, service);}

2 LightsService构造方法

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java
[LightsService.java]

public class LightsService extends SystemService {......final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];......public LightsService(Context context) {super(context);for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {mLights[i] = new LightImpl(i);}}
}

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java
[LightsService.java::LightImpl()]

    private final class LightImpl extends Light {private LightImpl(int id) {mId = id;}@Overridepublic void setBrightness(int brightness) {setBrightness(brightness, BRIGHTNESS_MODE_USER);}@Overridepublic void setBrightness(int brightness, int brightnessMode) {synchronized (this) {// LOW_PERSISTENCE cannot be manually setif (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mId +": brightness=0x" + Integer.toHexString(brightness));return;}int color = brightness & 0x000000ff;color = 0xff000000 | (color << 16) | (color << 8) | color;setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);}}@Overridepublic void setColor(int color) {synchronized (this) {setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);}}@Overridepublic void setFlashing(int color, int mode, int onMS, int offMS) {synchronized (this) {setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);}}@Overridepublic void pulse() {pulse(0x00ffffff, 7);}@Overridepublic void pulse(int color, int onMS) {synchronized (this) {if (mColor == 0 && !mFlashing) {setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000,BRIGHTNESS_MODE_USER);mColor = 0;mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);}}}@Overridepublic void turnOff() {synchronized (this) {setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);}}@Overridepublic void setVrMode(boolean enabled) {synchronized (this) {if (mVrModeEnabled != enabled) {mVrModeEnabled = enabled;mUseLowPersistenceForVR =(getVrDisplayMode() == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE);if (shouldBeInLowPersistenceMode()) {mLastBrightnessMode = mBrightnessMode;}// NOTE: We do not trigger a call to setLightLocked here.  We do not know the// current brightness or other values when leaving VR so we avoid any incorrect// jumps. The code that calls this method will immediately issue a brightness// update which is when the change will occur.}}}private void stopFlashing() {synchronized (this) {setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);}}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 {setLight_native(mId, color, mode, onMS, offMS, brightnessMode);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}}}private boolean shouldBeInLowPersistenceMode() {return mVrModeEnabled && mUseLowPersistenceForVR;}private int mId;private int mColor;private int mMode;private int mOnMS;private int mOffMS;private boolean mFlashing;private int mBrightnessMode;private int mLastBrightnessMode;private int mLastColor;private boolean mVrModeEnabled;private boolean mUseLowPersistenceForVR;private boolean mInitialized;}

/frameworks/base/services/core/java/com/android/server/lights/Light.java
[Light.java]


package com.android.server.lights;import android.hardware.light.V2_0.Flash;
import android.hardware.light.V2_0.Brightness;public abstract class Light {public static final int LIGHT_FLASH_NONE = Flash.NONE;public static final int LIGHT_FLASH_TIMED = Flash.TIMED;public static final int LIGHT_FLASH_HARDWARE = Flash.HARDWARE;/*** Light brightness is managed by a user setting.*/public static final int BRIGHTNESS_MODE_USER = Brightness.USER;/*** Light brightness is managed by a light sensor.*/public static final int BRIGHTNESS_MODE_SENSOR = Brightness.SENSOR;/*** Low-persistence light mode.*/public static final int BRIGHTNESS_MODE_LOW_PERSISTENCE = Brightness.LOW_PERSISTENCE;public abstract void setBrightness(int brightness);public abstract void setBrightness(int brightness, int brightnessMode);public abstract void setColor(int color);public abstract void setFlashing(int color, int mode, int onMS, int offMS);public abstract void pulse();public abstract void pulse(int color, int onMS);public abstract void turnOff();public abstract void setVrMode(boolean enabled);
}

3 LightsService使用

1 电量指示灯

/frameworks/base/services/core/java/com/android/server/BatteryService.java

[BatteryService.java::updateLightsLocked()]

        /*** Synchronize on BatteryService.*/public void updateLightsLocked() {final int level = mBatteryProps.batteryLevel;final int status = mBatteryProps.batteryStatus;if (level < mLowBatteryWarningLevel) {if (status == BatteryManager.BATTERY_STATUS_CHARGING) {// Solid red when battery is charging/**设置指示灯颜色*/mBatteryLight.setColor(mBatteryLowARGB);} else {// Flash red when battery is low and not charging/**设置指示灯*/mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,mBatteryLedOn, mBatteryLedOff);}} ......}

/frameworks/base/services/core/java/com/android/server/BatteryService.java
[BatteryService.java::Led ]


import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;private final class Led {private final Light mBatteryLight;public Led(Context context, LightsManager lights) {mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);......}
}

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java
[LightsService.java::mService ]

    private final LightsManager mService = new LightsManager() {@Overridepublic Light getLight(int id) {if (0 <= id && id < LIGHT_ID_COUNT) {return mLights[id];} else {return null;}}};

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java
[LightsService.java::LightImpl::setFlashing(int color, int mode, int onMS, int offMS) ]

        @Overridepublic void setFlashing(int color, int mode, int onMS, int offMS) {synchronized (this) {setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);}}

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java
[LightsService.java::LightImpl::setLightLocked(int color, int mode, int onMS, int offMS, int 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 {setLight_native(mId, color, mode, onMS, offMS, brightnessMode);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}}}

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java
[LightsService.java::setLight_native]

   static native void setLight_native(int light, int color, int mode,int onMS, int offMS, int brightnessMode);

/frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
[com_android_server_lights_LightsService.cpp::setLight_native]

static void setLight_native(JNIEnv* /* env */,jobject /* clazz */,jint light,jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode) {if (!validate(light, flashMode, brightnessMode)) {return;}/**1. 获取ILight服务*/sp<ILight> hal = LightHal::associate();if (hal == nullptr) {return;}Type type = static_cast<Type>(light);/**2. 构建lightState*/LightState state = constructState(colorARGB, flashMode, onMS, offMS, brightnessMode);{ALOGD_IF_SLOW(50, "Excessive delay setting light");/**3. 调用ILight服务的setLight()函数*/Return<Status> ret = hal->setLight(type, state);processReturn(ret, type, state);}
}

ILight.hal

/hardware/interfaces/light/2.0/ILight.hal
[ILight.hal]

package android.hardware.light@2.0;interface ILight {/*** Set the provided lights to the provided values.** @param type logical light to set* @param state describes what the light should look like.* @return status result of applying state transformation.*/setLight(Type type, LightState state) generates (Status status);/*** Discover what indicator lights are available.** @return types list of available lights*/getSupportedTypes() generates (vec<Type> types);};

/hardware/interfaces/light/2.0/default/Light.h
[Light.h]

struct Light : public ILight {Light(std::map<Type, light_device_t*> &&lights);// Methods from ::android::hardware::light::V2_0::ILight follow.Return<Status> setLight(Type type, const LightState& state)  override;Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb)  override;private:std::map<Type, light_device_t*> mLights;
};

1 获取ILight服务

/frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
[com_android_server_lights_LightsService.cpp::LightHal::associate()]


class LightHal {
private:static sp<ILight> sLight;static bool sLightInit;LightHal() {}public:static void disassociate() {sLightInit = false;sLight = nullptr;}static sp<ILight> associate() {if ((sLight == nullptr && !sLightInit) ||(sLight != nullptr && !sLight->ping().isOk())) {// will return the hal if it exists the first time.sLight = ILight::getService();sLightInit = true;if (sLight == nullptr) {ALOGE("Unable to get ILight interface.");}}return sLight;}
};

2 构建lightState

/frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
[com_android_server_lights_LightsService.cpp::constructState()]

static LightState constructState(jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode){Flash flash = static_cast<Flash>(flashMode);Brightness brightness = static_cast<Brightness>(brightnessMode);LightState state{};if (brightness == Brightness::LOW_PERSISTENCE) {state.flashMode = Flash::NONE;} else {// Only set non-brightness settings when not in low-persistence modestate.flashMode = flash;state.flashOnMs = onMS;state.flashOffMs = offMS;}state.color = colorARGB;state.brightnessMode = brightness;return state;
}

3 调用ILight服务的setLight()函数

/hardware/interfaces/light/2.0/default/Light.cpp
[Light.cpp]

// Methods from ::android::hardware::light::V2_0::ILight follow.
Return<Status> Light::setLight(Type type, const LightState& state)  {auto it = mLights.find(type);if (it == mLights.end()) {return Status::LIGHT_NOT_SUPPORTED;}light_device_t* hwLight = it->second;light_state_t legacyState {.color = state.color,.flashMode = static_cast<int>(state.flashMode),.flashOnMS = state.flashOnMs,.flashOffMS = state.flashOffMs,.brightnessMode = static_cast<int>(state.brightnessMode),};/**调用hwLight->set_light()*/int ret = hwLight->set_light(hwLight, &legacyState);switch (ret) {case -ENOSYS:return Status::BRIGHTNESS_NOT_SUPPORTED;case 0:return Status::SUCCESS;default:return Status::UNKNOWN;}
}

/hardware/libhardware/include/hardware/lights.h
[lights.h::light_device_t]

struct light_device_t {struct hw_device_t common;/*** Set the provided lights to the provided values.** Returns: 0 on succes, error code on failure.*/int (*set_light)(struct light_device_t* dev,struct light_state_t const* state);
};

/hardware/qcom/display/liblight/lights.c
[lights.c::open_lights]


/*** module methods*//** Open a new instance of a lights device using name */
static int open_lights(const struct hw_module_t* module, char const* name,struct hw_device_t** device)
{int (*set_light)(struct light_device_t* dev,struct light_state_t const* state);if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {char property[PROPERTY_VALUE_MAX];property_get("persist.extend.brightness", property, "0");if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||!(strncmp(property, "true", PROPERTY_VALUE_MAX))) {property_get("persist.display.max_brightness", property, "255");g_brightness_max = atoi(property);set_brightness_ext_init();set_light = set_light_backlight_ext;} elseset_light = set_light_backlight;} else if (0 == strcmp(LIGHT_ID_BATTERY, name))/**根据调用参数为电量指示灯,因此set_light对应set_light_battery*/set_light = set_light_battery;else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))set_light = set_light_notifications;else if (0 == strcmp(LIGHT_ID_BUTTONS, name))set_light = set_light_buttons;else if (0 == strcmp(LIGHT_ID_ATTENTION, name))set_light = set_light_attention;elsereturn -EINVAL;pthread_once(&g_init, init_globals);struct light_device_t *dev = malloc(sizeof(struct light_device_t));if(!dev)return -ENOMEM;memset(dev, 0, sizeof(*dev));dev->common.tag = HARDWARE_DEVICE_TAG;dev->common.version = LIGHTS_DEVICE_API_VERSION_2_0;dev->common.module = (struct hw_module_t*)module;dev->common.close = (int (*)(struct hw_device_t*))close_lights;dev->set_light = set_light;*device = (struct hw_device_t*)dev;return 0;
}

/hardware/qcom/display/liblight/lights.c
[lights.c::set_light_battery()]

static int
set_light_battery(struct light_device_t* dev,struct light_state_t const* state)
{pthread_mutex_lock(&g_lock);g_battery = *state;handle_speaker_battery_locked(dev);pthread_mutex_unlock(&g_lock);return 0;
}

/hardware/qcom/display/liblight/lights.c
[lights.c::handle_speaker_battery_locked()]

static void
handle_speaker_battery_locked(struct light_device_t* dev)
{if (is_lit(&g_battery)) {set_speaker_light_locked(dev, &g_battery);} else {set_speaker_light_locked(dev, &g_notification);}
}

/hardware/qcom/display/liblight/lights.c
[lights.c::set_speaker_light_locked()]

static int
set_speaker_light_locked(struct light_device_t* dev,struct light_state_t const* state)
{int red, green, blue;int blink;int onMS, offMS;unsigned int colorRGB;if(!dev) {return -1;}switch (state->flashMode) {case LIGHT_FLASH_TIMED:onMS = state->flashOnMS;offMS = state->flashOffMS;break;case LIGHT_FLASH_NONE:default:onMS = 0;offMS = 0;break;}colorRGB = state->color;#if 0ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",state->flashMode, colorRGB, onMS, offMS);
#endifred = (colorRGB >> 16) & 0xFF;green = (colorRGB >> 8) & 0xFF;blue = colorRGB & 0xFF;if (onMS > 0 && offMS > 0) {/** if ON time == OFF time*   use blink mode 2* else*   use blink mode 1*/if (onMS == offMS)blink = 2;elseblink = 1;} else {blink = 0;}if (blink) {if (red) {if (write_int(RED_BLINK_FILE, blink))write_int(RED_LED_FILE, 0);}if (green) {if (write_int(GREEN_BLINK_FILE, blink))write_int(GREEN_LED_FILE, 0);}if (blue) {if (write_int(BLUE_BLINK_FILE, blink))write_int(BLUE_LED_FILE, 0);}} else {write_int(RED_LED_FILE, red);write_int(GREEN_LED_FILE, green);write_int(BLUE_LED_FILE, blue);}return 0;
}

/hardware/qcom/display/liblight/lights.c
[lights.c::write_int()]

static int
write_int(char const* path, int value)
{int fd;static int already_warned = 0;fd = open(path, O_RDWR);if (fd >= 0) {char buffer[20];int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);ssize_t amt = write(fd, buffer, (size_t)bytes);close(fd);return amt == -1 ? -errno : 0;} else {if (already_warned == 0) {ALOGE("write_int failed to open %s\n", path);already_warned = 1;}return -errno;}
}

/hardware/qcom/display/liblight/lights.c
[lights.c]

static pthread_once_t g_init = PTHREAD_ONCE_INIT;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
static struct light_state_t g_notification;
static struct light_state_t g_battery;
static int g_last_backlight_mode = BRIGHTNESS_MODE_USER;
static int g_attention = 0;
static int g_brightness_max = 0;char const*const RED_LED_FILE= "/sys/class/leds/red/brightness";char const*const GREEN_LED_FILE= "/sys/class/leds/green/brightness";char const*const BLUE_LED_FILE= "/sys/class/leds/blue/brightness";char const*const LCD_FILE= "/sys/class/leds/lcd-backlight/brightness";char const*const LCD_FILE2= "/sys/class/backlight/panel0-backlight/brightness";char const*const BUTTON_FILE= "/sys/class/leds/button-backlight/brightness";char const*const RED_BLINK_FILE= "/sys/class/leds/red/blink";char const*const GREEN_BLINK_FILE= "/sys/class/leds/green/blink";char const*const BLUE_BLINK_FILE= "/sys/class/leds/blue/blink";char const*const PERSISTENCE_FILE= "/sys/class/graphics/fb0/msm_fb_persist_mode";

2 通知指示灯

/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
[NotificationManagerService.java::updateLightsLocked()]

  @GuardedBy("mNotificationLock")void updateLightsLocked(){// handle notification lightsNotificationRecord ledNotification = null;while (ledNotification == null && !mLights.isEmpty()) {final String owner = mLights.get(mLights.size() - 1);ledNotification = mNotificationsByKey.get(owner);if (ledNotification == null) {Slog.wtfStack(TAG, "LED Notification does not exist: " + owner);mLights.remove(owner);}}// Don't flash while we are in a call or screen is onif (ledNotification == null || mInCall || mScreenOn) {mNotificationLight.turnOff();} else {NotificationRecord.Light light = ledNotification.getLight();if (light != null && mNotificationPulseEnabled) {// pulse repeatedlymNotificationLight.setFlashing(light.color, Light.LIGHT_FLASH_TIMED,light.onMs, light.offMs);}}}

/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
[NotificationManagerService.java::init()]

   // TODO: Tests should call onStart instead once the methods above are removed.@VisibleForTestingvoid init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,LightsManager lightsManager, NotificationListeners notificationListeners,ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,NotificationUsageStats usageStats) {......mNotificationLight = lightsManager.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);mAttentionLight = lightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);......}

/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
[NotificationManagerService.java::onStart()]

public class NotificationManagerService extends SystemService {......@Overridepublic void onStart() {SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {@Overridepublic void repost(int userId, NotificationRecord r) {try {if (DBG) {Slog.d(TAG, "Reposting " + r.getKey());}enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),r.sbn.getNotification(), userId);} catch (Exception e) {Slog.e(TAG, "Cannot un-snooze notification", e);}}}, mUserProfiles);init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),getLocalService(LightsManager.class), new NotificationListeners(),null, snoozeHelper, new NotificationUsageStats(getContext()));publishBinderService(Context.NOTIFICATION_SERVICE, mService);publishLocalService(NotificationManagerInternal.class, mInternalService);}......
}

mNotificationLight.setFlashing(light.color, Light.LIGHT_FLASH_TIMED,
light.onMs, light.offMs);调用流程和电源指示灯调用流程类似,区别在于使用LightsManager.getLight()传入的Id不同。

通知中指示灯的初始化在NotificationRecord中

/frameworks/base/services/core/java/com/android/server/notification/NotificationRecord.java
[NotificationRecord.java]

public final class NotificationRecord {......
private Light mLight;......@VisibleForTestingpublic NotificationRecord(Context context, StatusBarNotification sbn,NotificationChannel channel){this.sbn = sbn;mOriginalFlags = sbn.getNotification().flags;mRankingTimeMs = calculateRankingTimeMs(0L);mCreationTimeMs = sbn.getPostTime();mUpdateTimeMs = mCreationTimeMs;mContext = context;stats = new NotificationUsageStats.SingleNotificationStats();mChannel = channel;mPreChannelsNotification = isPreChannelsNotification();mSound = calculateSound();mVibration = calculateVibration();mAttributes = calculateAttributes();mImportance = calculateImportance();mLight = calculateLights();}
......
}

/frameworks/base/services/core/java/com/android/server/notification/NotificationRecord.java
[NotificationRecord.java::calculateLights()]

    private Light calculateLights() {int defaultLightColor = mContext.getResources().getColor(com.android.internal.R.color.config_defaultNotificationColor);int defaultLightOn = mContext.getResources().getInteger(com.android.internal.R.integer.config_defaultNotificationLedOn);int defaultLightOff = mContext.getResources().getInteger(com.android.internal.R.integer.config_defaultNotificationLedOff);int channelLightColor = getChannel().getLightColor() != 0 ? getChannel().getLightColor(): defaultLightColor;/**判断通知是否需要指示灯*/Light light = getChannel().shouldShowLights() ? new Light(channelLightColor,defaultLightOn, defaultLightOff) : null;if (mPreChannelsNotification&& (getChannel().getUserLockedFields()& NotificationChannel.USER_LOCKED_LIGHTS) == 0) {final Notification notification = sbn.getNotification();if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0) {light = new Light(notification.ledARGB, notification.ledOnMS,notification.ledOffMS);if ((notification.defaults & Notification.DEFAULT_LIGHTS) != 0) {light = new Light(defaultLightColor, defaultLightOn,defaultLightOff);}} else {light = null;}}return light;}

/frameworks/base/services/core/java/com/android/server/notification/NotificationRecord.java
[NotificationRecord.java::Light]

    @VisibleForTestingstatic final class Light {public final int color;public final int onMs;public final int offMs;public Light(int color, int onMs, int offMs) {this.color = color;this.onMs = onMs;this.offMs = offMs;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Light light = (Light) o;if (color != light.color) return false;if (onMs != light.onMs) return false;return offMs == light.offMs;}@Overridepublic int hashCode() {int result = color;result = 31 * result + onMs;result = 31 * result + offMs;return result;}@Overridepublic String toString() {return "Light{" +"color=" + color +", onMs=" + onMs +", offMs=" + offMs +'}';}}

Android Light相关推荐

  1. Android Light开发(二) 通知灯调用过程

    Android中有各种灯,背光灯,按键灯,指示灯,等等:前几天修改了这部分代码,整理下思路,其实都不难: 首先,来说说指示灯(提示灯),即未接电话,未接短信的时候,会闪灯,这个其实就是Notifica ...

  2. 【C++】Android (Light)RefBase-sp-wp引用计数-智能指针源码分析

    文章目录 1.RefBase简介 2.RefBase源码分析 3.RefBase使用注意事项 4.总结 1.RefBase简介 什么是RefBase?RefBase是Android中的一个C++类,用 ...

  3. vs code主题_VS Code的10个Pretty Light主题

    vs code主题 The number of options you have when it comes to selecting a theme for VS Code is almost in ...

  4. Android模拟器学framework和driver之传感器篇3(Android HAL)

    Android模拟器学framework和driver之传感器篇3(Android HAL) 前面,带着大家一起写了一个temperature sensor的驱动,已经一个测试tool来测试这个驱动, ...

  5. MTK9612方案电视STR开机后屏黑有声的问题分析

    问题描述 客户反馈问题: 机顶盒连接tv: tv str 关机,机顶盒一直开着: 过了几个小时(一次),或者第二天过来(一次),str开机,出现tv 黑屏. 抓取分析log 考虑到开了ac logle ...

  6. android:theme.holo.light.,Android: Theme.Holo.Light.NoActionBar vs Theme.Light.NoTitleBar

    问题 In res/values-v11/styles.xml, I can't use Theme.Holo.Light.NoActionBar because it was added in AP ...

  7. 无法为新的Android ActionBar支持找到Theme.AppCompat.Light

    本文翻译自:Can't Find Theme.AppCompat.Light for New Android ActionBar Support I am trying to implement th ...

  8. Android安卓开发-'Theme.AppCompat.Light'无法找到的解决方案

    error: Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCom ...

  9. [android] No resource found that matches the given name 'Theme.AppCompat.Light'

    在整合android过程中导入别人的项目出现下面的错误:         <style name="AppBaseTheme" parent="Theme.AppC ...

  10. 【Android】Theme.AppCompat.Light 问题

    Android 开发的 styles.xml 文件中遇到了这个问题: <style name="AppBaseTheme" parent="Theme.AppCom ...

最新文章

  1. HDU 4321 Contest 3
  2. Solrj实现增删改查
  3. nginx 配置笔记
  4. 【leetcode】910. Smallest Range II
  5. Java当中编码和解码(以及出现乱编码的原因)
  6. java---数组常用的方法:
  7. 高性能迷你React框架anujs1.0.8发布
  8. 程序员删库后发同学群问如何恢复,同学:跑路吧,记得跑快点
  9. Error 4 opening dom ASM/Self in 0x8283c00
  10. kaggle 入门:逻辑回归应用之Kaggle泰坦尼克之灾
  11. jquery如何根据id获取标签内的值,以及如何通过id赋值
  12. 拓端tecdat|R语言用LOESS(局部加权回归)季节趋势分解(STL)进行时间序列异常检测
  13. 使用javascript通过className来获取元素
  14. 关于标准盒子模型的(border、 margin和padding)属性的讲解
  15. Buuctf Knife
  16. Linux查看隐藏进程pid脚本
  17. 茅山煤矿轶事(二)狼来了
  18. 信息论基本概念-自信息、互信息、信息熵、信道容量
  19. 如何将记事本中的.txt文件转为.csv文件
  20. 新特性解读 | MySQL 8.0 新密码策略(上)

热门文章

  1. Ugly Windows UVA - 1419
  2. 入门级带你实现一个安卓智能家居APP(1)java版本
  3. SOAP实例入门(转)
  4. 做个jmeter登陆百度网盘的实例
  5. iphoneX适配-客户端H5页面
  6. VScode+latex+Sumatra PDF环境配置(步步到位)
  7. 139邮箱注册收费吗,什么VIP的邮箱安全又好用呢
  8. android-更新UI的几种方式
  9. 《弗洛伊德及其后继者》读书笔记(part3)--沙利文与人际精神分析
  10. 三种近场通信的特点,以及未来近场通信技术的应用场景的分析和预测