Android(安卓)6.0(M) BatteryService浅析及充电呼吸灯流程浅析 MTK
16lz
2021-01-26
参考博文:
http://www.cnblogs.com/flyme/archive/2011/07/27/2118541.html
http://blog.csdn.net/kc58236582/article/details/45647181
- 启动BatteryService
电池的信息,电压,温度,充电状态等等,都是由BatteryService来提供的。BatteryService是跑在system_process当中,在系统初始化的时候启动,如下
在SystemServer.java (frameworks/base/services/java/com/android/server/SystemServer.java)中可以看到启动BatteryService的代码:
/** * Starts some essential services that are not tangled up in the bootstrap process. */ private void startCoreServices() { // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class);//启动BatteryService // Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Update after UsageStatsService is available, needed before performBootDexOpt. mPackageManagerService.getUsageStatsIfNoPackageUsageInfo(); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mSystemServiceManager.startService(WebViewUpdateService.class); }
- BattryService (frameworks/base/services/core/java/com/android/server/BatteryService.java)
构造函数做初始化
public BatteryService(Context context) { super(context); mContext = context; mHandler = new Handler(true /*async*/); mLed = new Led(context, getLocalService(LightsManager.class));//初始化Ligths mBatteryStats = BatteryStatsService.getService(); mCriticalBatteryLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); mLowBatteryWarningLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryCloseWarningBump); mShutdownBatteryTemperature = mContext.getResources().getInteger( com.android.internal.R.integer.config_shutdownBatteryTemperature); // watch for invalid charger messages if the invalid_charger switch exists if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) { mInvalidChargerObserver.startObserving( "DEVPATH=/devices/virtual/switch/invalid_charger"); } }
- onstart函数将电池监听注册到底层去。
/** * 将电池监听注册到底层去 */ @Override public void onStart() { IBinder b = ServiceManager.getService("batteryproperties"); final IBatteryPropertiesRegistrar batteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b); try { //电池监听,注册到底层。当底层电量改变会调用此监听。然后执行update batteryPropertiesRegistrar.registerListener(new BatteryListener()); } catch (RemoteException e) { // Should never happen. } publishBinderService("battery", new BinderService()); publishLocalService(BatteryManagerInternal.class, new LocalService());//将本地接口publish出去。 } private final class BatteryListener extends IBatteryPropertiesListener.Stub { @Override public void batteryPropertiesChanged(BatteryProperties props) { final long identity = Binder.clearCallingIdentity(); try { BatteryService.this.update(props);//调用 update()方法,来更新电池的信息数据 } finally { Binder.restoreCallingIdentity(identity); } } } //将本地接口publish出去。 private final class LocalService extends BatteryManagerInternal { @Override public boolean isPowered(int plugTypeSet) { synchronized (mLock) { return isPoweredLocked(plugTypeSet); } } @Override public int getPlugType() { synchronized (mLock) { return mPlugType; } } @Override public int getBatteryLevel() { synchronized (mLock) { return mBatteryProps.batteryLevel; } } @Override public boolean getBatteryLevelLow() { synchronized (mLock) { return mBatteryLevelLow; } } @Override public int getInvalidCharger() { synchronized (mLock) { return mInvalidCharger; } } } //当底层有信息上来,会调用update函数更新BatteryService中的状态值. private void update(BatteryProperties props) { synchronized (mLock) { if (!mUpdatesStopped) { mBatteryProps = props; if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) { if (mIPOShutdown) return; } // Process the new values. if (mBootCompleted) processValuesLocked(false); } else { mLastBatteryProps.set(props); } } }
接下来分析主函数processValuesLocked:
private void processValuesLocked(boolean force) { boolean logOutlier = false; long dischargeDuration = 0; mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel); //判断充电类型 if (mBatteryProps.chargerAcOnline) {// AC mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mBatteryProps.chargerUsbOnline) {//USB mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else if (mBatteryProps.chargerWirelessOnline) {//无线 mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; } else { mPlugType = BATTERY_PLUGGED_NONE; } /// M: Add for DUAL_INPUT_CHARGER_SUPPORT @{ if (SystemProperties.get("ro.mtk_diso_support").equals("true")) { if (mBatteryProps.chargerAcOnline && mBatteryProps.chargerUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB; } } /// M: @} if (mLastBatteryVoltage != mBatteryProps.batteryVoltage) { Log.d(TAG, "mBatteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryLevel=" + mBatteryProps.batteryLevel_smb); } // Update the battery LED mLed.updateLightsLocked();//更新电池的LED(BreathLights) // Let the battery stats keep track of the current level. try { mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature, mBatteryProps.batteryVoltage); } catch (RemoteException e) { // Should never happen. } //没电了 shutdownIfNoPowerLocked(); // 温度过高 shutdownIfOverTempLocked(); if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryStatus_smb != mLastBatteryStatus_smb || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mBatteryProps.batteryPresent_smb != mLastBatteryPresent_smb || mBatteryProps.batteryLevel != mLastBatteryLevel || mBatteryProps.batteryLevel_smb != mLastBatteryLevel_smb || mPlugType != mLastPlugType || mBatteryProps.batteryVoltage != mLastBatteryVoltage || mBatteryProps.batteryTemperature != mLastBatteryTemperature || mInvalidCharger != mLastInvalidCharger)) { if (mPlugType != mLastPlugType) { if (mLastPlugType == BATTERY_PLUGGED_NONE) { // discharging -> charging // There's no value in this data unless we've discharged at least once and the // battery level has changed; so don't log until it does. //不充电到充电 if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) { dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; logOutlier = true; EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration, mDischargeStartLevel, mBatteryProps.batteryLevel); // make sure we see a discharge event before logging again mDischargeStartTime = 0; } } else if (mPlugType == BATTERY_PLUGGED_NONE) { // 刚开始充电 // charging -> discharging or we just powered up mDischargeStartTime = SystemClock.elapsedRealtime(); mDischargeStartLevel = mBatteryProps.batteryLevel; } } if (mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mPlugType != mLastPlugType) { EventLog.writeEvent(EventLogTags.BATTERY_STATUS, mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0, mPlugType, mBatteryProps.batteryTechnology); } if (mBatteryProps.batteryLevel != mLastBatteryLevel) { // Don't do this just from voltage or temperature changes, that is // too noisy. EventLog.writeEvent(EventLogTags.BATTERY_LEVEL, mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature); } if (mBatteryLevelCritical && !mLastBatteryLevelCritical && mPlugType == BATTERY_PLUGGED_NONE) { // We want to make sure we log discharge cycle outliers // if the battery is about to die. dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; logOutlier = true; } if (!mBatteryLevelLow) { // Should we now switch in to low battery mode? if (mPlugType == BATTERY_PLUGGED_NONE && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) { mBatteryLevelLow = true; } } else { // Should we now switch out of low battery mode? if (mPlugType != BATTERY_PLUGGED_NONE) { mBatteryLevelLow = false; } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) { mBatteryLevelLow = false; } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) { // If being forced, the previous state doesn't matter, we will just // absolutely check to see if we are now above the warning level. mBatteryLevelLow = false; } } sendIntentLocked();//发送电池状态改变的广播 // Separate broadcast is sent for power connected / not connected // since the standard intent will not wake any applications and some // applications may want to have smart behavior based on this. if (mPlugType != 0 && mLastPlugType == 0) { mHandler.post(new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } else if (mPlugType == 0 && mLastPlugType != 0) { mHandler.post(new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } if (shouldSendBatteryLowLocked()) { mSentLowBatteryBroadcast = true; mHandler.post(new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) { mSentLowBatteryBroadcast = false; mHandler.post(new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } if (mBatteryProps.batteryStatus != mLastBatteryStatus && mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CMD_DISCHARGING) { mHandler.post(new Runnable() { @Override public void run() { final String ACTION_IGNORE_DATA_USAGE_ALERT = "android.intent.action.IGNORE_DATA_USAGE_ALERT"; Log.d(TAG, "sendBroadcast ACTION_IGNORE_DATA_USAGE_ALERT"); Intent statusIntent = new Intent(ACTION_IGNORE_DATA_USAGE_ALERT); statusIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } // Update the battery LED/* * bugfix #134486 low battery not charging led keep red // mLed.updateLightsLocked(); */ mLed.updateLightsLocked();//更新电池的LED(BreathLights) // This needs to be done after sendIntent() so that we get the lastest battery stats. if (logOutlier && dischargeDuration != 0) { logOutlierLocked(dischargeDuration); } mLastBatteryStatus = mBatteryProps.batteryStatus; mLastBatteryStatus_smb = mBatteryProps.batteryStatus_smb; mLastBatteryHealth = mBatteryProps.batteryHealth; mLastBatteryPresent = mBatteryProps.batteryPresent; mLastBatteryPresent_smb = mBatteryProps.batteryPresent_smb; mLastBatteryLevel = mBatteryProps.batteryLevel; mLastBatteryLevel_smb = mBatteryProps.batteryLevel_smb; mLastPlugType = mPlugType; mLastBatteryVoltage = mBatteryProps.batteryVoltage; mLastBatteryTemperature = mBatteryProps.batteryTemperature; mLastBatteryLevelCritical = mBatteryLevelCritical; mLastInvalidCharger = mInvalidCharger; } }
电池的这些信息是通过何种方式,被其他应用所获得的。可以想到的有两种方式,第一种,应用主动从BatteryService获得数据;第二种,BatteryService主动把数据传送给所关心的应用程序。
BatteryService采用的是第二种方式,所有的电池的信息数据是通过Intent传送出去的。在BatteryService.java中,Code如下:
private void sendIntentLocked() { // Pack up the values and broadcast them to everyone final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING); int icon = getIconLocked(mBatteryProps.batteryLevel); intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus); intent.putExtra(BatteryManager.EXTRA_STATUS_SMARTBOOK, mBatteryProps.batteryStatus_smb); intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth); intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent); intent.putExtra(BatteryManager.EXTRA_PRESENT_SMARTBOOK, mBatteryProps.batteryPresent_smb); intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel); intent.putExtra(BatteryManager.EXTRA_LEVEL_SMARTBOOK, mBatteryProps.batteryLevel_smb); intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE); intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon); intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType); intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage); intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature); intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology); intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger); mHandler.post(new Runnable() { @Override public void run() { ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); } }); }
====================================================
充电呼吸灯实现的流程
在上边的processValuesLocked()方法里边,通过调用mLed.updateLightsLocked()来处理呼吸灯的各个状态
/** *通过Led来调用LightsService.java对应的方法(frameworks/base/services/core/java/com/android/server/lights/LightsService.java) */ private final class Led { private final Light mBatteryLight; private final int mBatteryLowARGB; private final int mBatteryMediumARGB; private final int mBatteryFullARGB; private final int mBatteryLedOn; private final int mBatteryLedOff; public Led(Context context, LightsManager lights) {//构造函数做初始化 mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY); mBatteryLowARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLowARGB); mBatteryMediumARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryMediumARGB); mBatteryFullARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryFullARGB); mBatteryLedOn = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOn); mBatteryLedOff = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOff); } /** * Synchronize on BatteryService. */ public void updateLightsLocked() { final int level = mBatteryProps.batteryLevel; final int status = mBatteryProps.batteryStatus; if (mIPOBoot) { //Get led status in IPO mode getIpoLedStatus(); } if (level < mLowBatteryWarningLevel) {//判断是否低电量 if (status == BatteryManager.BATTERY_STATUS_CHARGING) {//低电量充电状态 updateLedStatus(); // Solid red when battery is charging mBatteryLight.setColor(mBatteryLowARGB);//调用LightsService里边的setColor } else {//低电量 mBatteryLight.turnOff(); LowLevelFlag = true; updateLedStatus(); // Flash red when battery is low and not charging mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff);//调用LightsService里边的setFlashing } } else if (status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL) {//充电状态 if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {//电量满或者大于百分之90 updateLedStatus(); // Solid green when full or charging and nearly full mBatteryLight.setColor(mBatteryFullARGB);//调用LightsService里边的setColor } else {//小于百分之90 updateLedStatus(); // Solid orange when charging and halfway full mBatteryLight.setColor(mBatteryMediumARGB);//调用LightsService里边的setColor } } else { if (ipo_led_on && mIPOBoot) { if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) { mBatteryLight.setColor(mBatteryFullARGB); } else { mBatteryLight.setColor(mBatteryMediumARGB); } mIPOBoot = false; ipo_led_on = false; } // No lights if not charging and not low mBatteryLight.turnOff(); } } private void getIpoLedStatus() { if ("1".equals(SystemProperties.get("sys.ipo.ledon"))) { ipo_led_on = true; } else if ("0".equals(SystemProperties.get("sys.ipo.ledon"))) { ipo_led_off = true; } if (DEBUG) { Slog.d(TAG, ">>>>>>>getIpoLedStatus ipo_led_on = " + ipo_led_on + ", ipo_led_off = " + ipo_led_off + "<<<<<<<"); } } private void updateLedStatus() { // if LowBatteryWarning happened, we refresh the led state no matter ipo_led is on or off. if ((ipo_led_off && mIPOBoot) || (LowLevelFlag && mIPOBoot)) { mBatteryLight.turnOff(); mIPOBoot = false; ipo_led_off = false; ipo_led_on = false; if (DEBUG) { Slog.d(TAG, ">>>>>>>updateLedStatus LowLevelFlag = " + LowLevelFlag + "<<<<<<<"); } } } }
接下来分析LightsService.java
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.android.server.lights;import com.android.server.SystemService;import android.content.Context;import android.os.Handler;import android.os.Message;import android.os.Trace;import android.util.Slog;/* wj@Revo:add status light setup menu, 20160624 */import android.os.SystemProperties;/* End of wj@Revo */public class LightsService extends SystemService { static final String TAG = "LightsService"; static final boolean DEBUG = false;/* wj@Revo:add status light setup menu, 20160624 */ private Context mContext;/* End of wj@Revo */ final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT]; private final class LightImpl extends Light { private LightImpl(int id) { mId = id; } @Override public void setBrightness(int brightness) { setBrightness(brightness, BRIGHTNESS_MODE_USER); } @Override public void setBrightness(int brightness, int brightnessMode) { synchronized (this) { int color = brightness & 0x000000ff; color = 0xff000000 | (color << 16) | (color << 8) | color; setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode); } } @Override public void setColor(int color) { synchronized (this) { setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0); } } @Override public void setFlashing(int color, int mode, int onMS, int offMS) { synchronized (this) { setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER); } } @Override public void pulse() { pulse(0x00ffffff, 7); } @Override public 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); } } } @Override public void turnOff() { synchronized (this) { setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0); } } 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(mContext != null && mContext.getResources().getBoolean( com.android.internal.R.bool.config_settings_status_light_support)){ if (SystemProperties.getBoolean("persist.sys.status_light", true) == false) { if (mId == LightsManager.LIGHT_ID_BATTERY || mId == LightsManager.LIGHT_ID_NOTIFICATIONS || mId == LightsManager.LIGHT_ID_ATTENTION) { setLight_native(mNativePointer, mId, 0, LIGHT_FLASH_NONE, 0, 0, 0); return; } } if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS || SystemProperties.getBoolean("persist.sys.status_light", true)) { if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#" + Integer.toHexString(color)); mColor = color; mMode = mode; mOnMS = onMS; mOffMS = offMS; Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x" + Integer.toHexString(color) + ")"); try { setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);//通过JNI调用底层驱动 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } } else if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) { if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#" + Integer.toHexString(color)); mColor = color; mMode = mode; mOnMS = onMS; mOffMS = offMS; Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x" + Integer.toHexString(color) + ")"); try { setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);//通过JNI调用底层驱动 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } } private int mId; private int mColor; private int mMode; private int mOnMS; private int mOffMS; private boolean mFlashing; } public LightsService(Context context) { super(context); mContext = context; mNativePointer = init_native(); for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) { mLights[i] = new LightImpl(i); } } @Override public void onStart() { publishLocalService(LightsManager.class, mService); } private final LightsManager mService = new LightsManager() { @Override public Light getLight(int id) { if (id < LIGHT_ID_COUNT) { return mLights[id]; } else { return null; } } }; @Override protected void finalize() throws Throwable { finalize_native(mNativePointer); super.finalize(); } private Handler mH = new Handler() { @Override public void handleMessage(Message msg) { LightImpl light = (LightImpl)msg.obj; light.stopFlashing(); } }; private static native long init_native(); private static native void finalize_native(long ptr); static native void setLight_native(long ptr, int light, int color, int mode, int onMS, int offMS, int brightnessMode);//上层接口掉底层驱动 private long mNativePointer;}
欢迎关注我的微信公众号
更多相关文章
- 关于android下audioflinger+alsa+a2dp+pcm+bluez+sbc编码理解
- Android(安卓)学习记录-零散知识点
- Android完全退出App的一些问题
- android Window和ViewRootImpl
- ActivityManagerService启动学习
- Android9.0 Activity启动流程分析(一)
- [android] Activity 的生命周期 以及 横屏竖屏切换时 Activity
- Android(安卓)display架构分析四-msm_fb.c 函数和数据结构介绍
- android不公开的面试题偶!!!