Android Battery 开发(三) BatteryService
android 4.4 电池电量管理底层分析(C\C++层)(http://blog.csdn.net/daweibalang717/article/details/41446993)
先贴一张类与类之间的关系图:
android开机过程中会加载系统BatteryService ,说一下电池电量相关的,本文主要讲述关于JAVA 层代码。文件路径:\frameworks\base\services\java\com\android\server\BatteryService.java 下面贴出源码。我把注释加上。个人理解,仅参考。
[java] view plain copy- /*
- *Copyright(C)2006TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packagecom.android.server;
- importandroid.os.BatteryStats;
- importcom.android.internal.app.IBatteryStats;
- importcom.android.server.am.BatteryStatsService;
- importandroid.app.ActivityManagerNative;
- importandroid.content.ContentResolver;
- importandroid.content.Context;
- importandroid.content.Intent;
- importandroid.content.pm.PackageManager;
- importandroid.os.BatteryManager;
- importandroid.os.BatteryProperties;
- importandroid.os.Binder;
- importandroid.os.FileUtils;
- importandroid.os.Handler;
- importandroid.os.IBatteryPropertiesListener;
- importandroid.os.IBatteryPropertiesRegistrar;
- importandroid.os.IBinder;
- importandroid.os.DropBoxManager;
- importandroid.os.RemoteException;
- importandroid.os.ServiceManager;
- importandroid.os.SystemClock;
- importandroid.os.UEventObserver;
- importandroid.os.UserHandle;
- importandroid.provider.Settings;
- importandroid.util.EventLog;
- importandroid.util.Slog;
- importjava.io.File;
- importjava.io.FileDescriptor;
- importjava.io.FileOutputStream;
- importjava.io.IOException;
- importjava.io.PrintWriter;
- /**
- *<p>BatteryServicemonitorsthechargingstatus,andchargelevelofthedevice
- *battery.Whenthesevalueschangethisservicebroadcaststhenewvalues
- *toall{@linkandroid.content.BroadcastReceiverIntentReceivers}thatare
- *watchingthe{@linkandroid.content.Intent#ACTION_BATTERY_CHANGED
- *BATTERY_CHANGED}action.</p>
- *<p>ThenewvaluesarestoredintheIntentdataandcanberetrievedby
- *calling{@linkandroid.content.Intent#getExtraIntent.getExtra}withthe
- *followingkeys:</p>
- *<p>"scale"-int,themaximumvalueforthechargelevel</p>
- *<p>"level"-int,chargelevel,from0through"scale"inclusive</p>
- *<p>"status"-String,thecurrentchargingstatus.<br/>
- *<p>"health"-String,thecurrentbatteryhealth.<br/>
- *<p>"present"-boolean,trueifthebatteryispresent<br/>
- *<p>"icon-small"-int,suggestedsmallicontouseforthisstate</p>
- *<p>"plugged"-int,0ifthedeviceisnotpluggedin;1ifplugged
- *intoanACpoweradapter;2ifpluggedinviaUSB.</p>
- *<p>"voltage"-int,currentbatteryvoltageinmillivolts</p>
- *<p>"temperature"-int,currentbatterytemperatureintenthsof
- *adegreeCentigrade</p>
- *<p>"technology"-String,thetypeofbatteryinstalled,e.g."Li-ion"</p>
- *
- *<p>
- *Thebatteryservicemaybecalledbythepowermanagerwhileholdingitslocksso
- *wetakecaretopostalloutcallsintotheactivitymanagertoahandler.
- *
- *FIXME:Ideallythepowermanagerwouldperformallofitscallsintothebattery
- *serviceasynchronouslyitself.
- *</p>
- */
- publicfinalclassBatteryServiceextendsBinder{
- privatestaticfinalStringTAG=BatteryService.class.getSimpleName();
- privatestaticfinalbooleanDEBUG=false;
- privatestaticfinalintBATTERY_SCALE=100;//batterycapacityisapercentage
- //Usedlocallyfordeterminingwhentomakealastditchefforttolog
- //dischargestatsbeforethedevicedies.
- privateintmCriticalBatteryLevel;
- privatestaticfinalintDUMP_MAX_LENGTH=24*1024;
- privatestaticfinalString[]DUMPSYS_ARGS=newString[]{"--checkin","--unplugged"};
- privatestaticfinalStringDUMPSYS_DATA_PATH="/data/system/";
- //ThisshouldprobablybeexposedintheAPI,thoughit'snotcritical
- privatestaticfinalintBATTERY_PLUGGED_NONE=0;
- privatefinalContextmContext;
- privatefinalIBatteryStatsmBatteryStats;
- privatefinalHandlermHandler;
- privatefinalObjectmLock=newObject();
- privateBatteryPropertiesmBatteryProps;
- privatebooleanmBatteryLevelCritical;
- privateintmLastBatteryStatus;
- privateintmLastBatteryHealth;
- privatebooleanmLastBatteryPresent;
- privateintmLastBatteryLevel;
- privateintmLastBatteryVoltage;
- privateintmLastBatteryTemperature;
- privatebooleanmLastBatteryLevelCritical;
- privateintmInvalidCharger;
- privateintmLastInvalidCharger;
- privateintmLowBatteryWarningLevel;
- privateintmLowBatteryCloseWarningLevel;
- privateintmShutdownBatteryTemperature;
- privateintmPlugType;
- privateintmLastPlugType=-1;//Extrastatesowecandetectfirstrun
- privatelongmDischargeStartTime;
- privateintmDischargeStartLevel;
- privatebooleanmUpdatesStopped;
- privateLedmLed;
- privatebooleanmSentLowBatteryBroadcast=false;
- privateBatteryListenermBatteryPropertiesListener;
- privateIBatteryPropertiesRegistrarmBatteryPropertiesRegistrar;
- //构造函数
- publicBatteryService(Contextcontext,LightsServicelights){
- mContext=context;
- mHandler=newHandler(true/*async*/);
- mLed=newLed(context,lights);//这个应该是指示灯,没实验
- mBatteryStats=BatteryStatsService.getService();
- //低电量临界值,这个数我看的源码版本值是4(在这个类里只是用来写日志)
- mCriticalBatteryLevel=mContext.getResources().getInteger(
- com.android.internal.R.integer.config_criticalBatteryWarningLevel);
- //低电量告警值,值15,下面会根据这个变量发送低电量的广播Intent.ACTION_BATTERY_LOW(这个跟系统低电量提醒没关系,只是发出去了)
- mLowBatteryWarningLevel=mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
- //电量告警取消值,值20,就是手机电量大于等于20的话发送Intent.ACTION_BATTERY_OKAY
- mLowBatteryCloseWarningLevel=mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
- //值是680,温度过高,超过这个值就发送广播,跳转到将要关机提醒。
- mShutdownBatteryTemperature=mContext.getResources().getInteger(
- com.android.internal.R.integer.config_shutdownBatteryTemperature);
- //watchforinvalidchargermessagesiftheinvalid_chargerswitchexists
- if(newFile("/sys/devices/virtual/switch/invalid_charger/state").exists()){
- mInvalidChargerObserver.startObserving(
- "DEVPATH=/devices/virtual/switch/invalid_charger");
- }
- //电池监听,这个应该是注册到底层去了。当底层电量改变会调用此监听。然后执行update(BatteryPropertiesprops);
- mBatteryPropertiesListener=newBatteryListener();
- IBinderb=ServiceManager.getService("batterypropreg");
- mBatteryPropertiesRegistrar=IBatteryPropertiesRegistrar.Stub.asInterface(b);
- try{
- //这里注册
- mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
- }catch(RemoteExceptione){
- //Shouldneverhappen.
- }
- }
- //开机后先去看看是否没电了或者温度太高了。如果是,就关机提示(关机提示我等会介绍)。
- voidsystemReady(){
- //checkourpowersituationnowthatitissafetodisplaytheshutdowndialog.
- synchronized(mLock){
- shutdownIfNoPowerLocked();
- shutdownIfOverTempLocked();
- }
- }
- //返回是否在充电,这个函数在PowerManagerService.java中调用
- /**
- *Returnstrueifthedeviceispluggedintoanyofthespecifiedplugtypes.
- */
- publicbooleanisPowered(intplugTypeSet){
- synchronized(mLock){
- returnisPoweredLocked(plugTypeSet);
- }
- }
- //就是这里,通过充电器类型判断是否充电
- privatebooleanisPoweredLocked(intplugTypeSet){
- //我这英语小白猜着翻译下:就是开机后,电池状态不明了,那我们就认为就在充电,以便设备正常工作。
- //assumewearepoweredifbatterystateisunknownso
- //the"stayonwhilepluggedin"optionwillwork.
- if(mBatteryProps.batteryStatus==BatteryManager.BATTERY_STATUS_UNKNOWN){
- returntrue;
- }
- //充电器
- if((plugTypeSet&BatteryManager.BATTERY_PLUGGED_AC)!=0&&mBatteryProps.chargerAcOnline){
- returntrue;
- }
- //USB,插电脑上充电
- if((plugTypeSet&BatteryManager.BATTERY_PLUGGED_USB)!=0&&mBatteryProps.chargerUsbOnline){
- returntrue;
- }
- //电源是无线的。(我没见过...)
- if((plugTypeSet&BatteryManager.BATTERY_PLUGGED_WIRELESS)!=0&&mBatteryProps.chargerWirelessOnline){
- returntrue;
- }
- returnfalse;
- }
- /**
- *Returnsthecurrentplugtype.
- */
- //充电器类型
- publicintgetPlugType(){
- synchronized(mLock){
- returnmPlugType;
- }
- }
- /**
- *Returnsbatterylevelasapercentage.
- */
- //电池属性:电量等级(0-100)
- publicintgetBatteryLevel(){
- synchronized(mLock){
- returnmBatteryProps.batteryLevel;
- }
- }
- /**
- *Returnstrueifbatterylevelisbelowthefirstwarningthreshold.
- */
- //低电量
- publicbooleanisBatteryLow(){
- synchronized(mLock){
- returnmBatteryProps.batteryPresent&&mBatteryProps.batteryLevel<=mLowBatteryWarningLevel;
- }
- }
- /**
- *Returnsanon-zerovalueifanunsupportedchargerisattached.
- */
- //不支持的充电器类型
- publicintgetInvalidCharger(){
- synchronized(mLock){
- returnmInvalidCharger;
- }
- }
- //这里就是没电了,要关机的提示。
- privatevoidshutdownIfNoPowerLocked(){
- //shutdowngracefullyifourbatteryiscriticallylowandwearenotpowered.
- //waituntilthesystemhasbootedbeforeattemptingtodisplaytheshutdowndialog.
- if(mBatteryProps.batteryLevel==0&&(mBatteryProps.batteryStatus==BatteryManager.BATTERY_STATUS_DISCHARGING)){
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- if(ActivityManagerNative.isSystemReady()){
- Intentintent=newIntent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");//ACTION_REQUEST_SHUTDOWN
- intent.putExtra(Intent.EXTRA_KEY_CONFIRM,false);
- intent.putExtra("cant_be_cancel_by_button",true);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent,UserHandle.CURRENT);
- }
- }
- });
- }
- }
- //温度过高,关机提示(个人感觉这里有问题,温度过高为啥子跳转到没电关机提示界面)
- privatevoidshutdownIfOverTempLocked(){
- //shutdowngracefullyiftemperatureistoohigh(>68.0Cbydefault)
- //waituntilthesystemhasbootedbeforeattemptingtodisplaythe
- //shutdowndialog.
- if(mBatteryProps.batteryTemperature>mShutdownBatteryTemperature){
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- if(ActivityManagerNative.isSystemReady()){
- Intentintent=newIntent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");//ACTION_REQUEST_SHUTDOWN
- intent.putExtra(Intent.EXTRA_KEY_CONFIRM,false);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent,UserHandle.CURRENT);
- }
- }
- });
- }
- }
- //这个方法就是被JNI回调的。用来更新上层状态的方法。
- privatevoidupdate(BatteryPropertiesprops){
- synchronized(mLock){
- if(!mUpdatesStopped){
- mBatteryProps=props;
- //Processthenewvalues.
- processValuesLocked();
- }
- }
- }
- //嗯。这个就是最主要的方法了。
- privatevoidprocessValuesLocked(){
- booleanlogOutlier=false;
- longdischargeDuration=0;
- mBatteryLevelCritical=(mBatteryProps.batteryLevel<=mCriticalBatteryLevel);
- //充电器类型
- if(mBatteryProps.chargerAcOnline){
- mPlugType=BatteryManager.BATTERY_PLUGGED_AC;
- }elseif(mBatteryProps.chargerUsbOnline){
- mPlugType=BatteryManager.BATTERY_PLUGGED_USB;
- }elseif(mBatteryProps.chargerWirelessOnline){
- mPlugType=BatteryManager.BATTERY_PLUGGED_WIRELESS;
- }else{
- mPlugType=BATTERY_PLUGGED_NONE;
- }
- if(DEBUG){//日志,略过
- Slog.d(TAG,"Processingnewvalues:"
- +"chargerAcOnline="+mBatteryProps.chargerAcOnline
- +",chargerUsbOnline="+mBatteryProps.chargerUsbOnline
- +",chargerWirelessOnline="+mBatteryProps.chargerWirelessOnline
- +",batteryStatus="+mBatteryProps.batteryStatus
- +",batteryHealth="+mBatteryProps.batteryHealth
- +",batteryPresent="+mBatteryProps.batteryPresent
- +",batteryLevel="+mBatteryProps.batteryLevel
- +",batteryTechnology="+mBatteryProps.batteryTechnology
- +",batteryVoltage="+mBatteryProps.batteryVoltage
- +",batteryCurrentNow="+mBatteryProps.batteryCurrentNow
- +",batteryChargeCounter="+mBatteryProps.batteryChargeCounter
- +",batteryTemperature="+mBatteryProps.batteryTemperature
- +",mBatteryLevelCritical="+mBatteryLevelCritical
- +",mPlugType="+mPlugType);
- }
- //Letthebatterystatskeeptrackofthecurrentlevel.
- try{
- //把电池属性放到状态里面
- mBatteryStats.setBatteryState(mBatteryProps.batteryStatus,mBatteryProps.batteryHealth,
- mPlugType,mBatteryProps.batteryLevel,mBatteryProps.batteryTemperature,
- mBatteryProps.batteryVoltage);
- }catch(RemoteExceptione){
- //Shouldneverhappen.
- }
- //没电了
- shutdownIfNoPowerLocked();
- //温度过高了
- shutdownIfOverTempLocked();
- if(mBatteryProps.batteryStatus!=mLastBatteryStatus||
- mBatteryProps.batteryHealth!=mLastBatteryHealth||
- mBatteryProps.batteryPresent!=mLastBatteryPresent||
- mBatteryProps.batteryLevel!=mLastBatteryLevel||
- mPlugType!=mLastPlugType||
- mBatteryProps.batteryVoltage!=mLastBatteryVoltage||
- mBatteryProps.batteryTemperature!=mLastBatteryTemperature||
- mInvalidCharger!=mLastInvalidCharger){
- if(mPlugType!=mLastPlugType){//当前充电器类型与上次的不一样
- //并且上次充电器类型是noone,那就可以知道,现在是插上充电器了。
- if(mLastPlugType==BATTERY_PLUGGED_NONE){
- //discharging->charging
- //There'snovalueinthisdataunlesswe'vedischargedatleastonceandthe
- //batterylevelhaschanged;sodon'tloguntilitdoes.
- if(mDischargeStartTime!=0&&mDischargeStartLevel!=mBatteryProps.batteryLevel){
- dischargeDuration=SystemClock.elapsedRealtime()-mDischargeStartTime;
- logOutlier=true;
- EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE,dischargeDuration,
- mDischargeStartLevel,mBatteryProps.batteryLevel);
- //makesureweseeadischargeeventbeforeloggingagain
- mDischargeStartTime=0;
- }
- //并且本次充电器类型是noone,那就可以知道,现在是拔掉充电器了。
- }elseif(mPlugType==BATTERY_PLUGGED_NONE){
- //charging->dischargingorwejustpoweredup
- 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'tdothisjustfromvoltageortemperaturechanges,thatis
- //toonoisy.
- EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
- mBatteryProps.batteryLevel,mBatteryProps.batteryVoltage,mBatteryProps.batteryTemperature);
- }
- if(mBatteryLevelCritical&&!mLastBatteryLevelCritical&&
- mPlugType==BATTERY_PLUGGED_NONE){
- //Wewanttomakesurewelogdischargecycleoutliers
- //ifthebatteryisabouttodie.
- dischargeDuration=SystemClock.elapsedRealtime()-mDischargeStartTime;
- logOutlier=true;
- }
- //本次调用,当前的充电状态
- finalbooleanplugged=mPlugType!=BATTERY_PLUGGED_NONE;
- //本次调用,上次调用的充电状态
- finalbooleanoldPlugged=mLastPlugType!=BATTERY_PLUGGED_NONE;
- /*TheACTION_BATTERY_LOWbroadcastissentinthesesituations:
- *-isjustun-plugged(previouslywasplugged)andbatterylevelis
- *lessthanorequaltoWARNING,or
- *-isnotpluggedandbatterylevelfallstoWARNINGboundary
- *(becomes<=mLowBatteryWarningLevel).
- */
- //用于发送低电量广播的判断
- finalbooleansendBatteryLow=!plugged//(按sendBatteryLow=true来说)当前没有充电
- &&mBatteryProps.batteryStatus!=BatteryManager.BATTERY_STATUS_UNKNOWN//充电状态不是UNKNOWN
- &&mBatteryProps.batteryLevel<=mLowBatteryWarningLevel//当前电量小于告警值15
- &&(oldPlugged||mLastBatteryLevel>mLowBatteryWarningLevel);//上次状态是充电或者上次电量等级大于告警值15
- sendIntentLocked();//发送电池电量改变的广播Intent.ACTION_BATTERY_CHANGED
- //Separatebroadcastissentforpowerconnected/notconnected
- //sincethestandardintentwillnotwakeanyapplicationsandsome
- //applicationsmaywanttohavesmartbehaviorbasedonthis.
- if(mPlugType!=0&&mLastPlugType==0){//插上充电器了
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- IntentstatusIntent=newIntent(Intent.ACTION_POWER_CONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent,UserHandle.ALL);
- }
- });
- }
- elseif(mPlugType==0&&mLastPlugType!=0){//断开充电器了
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- IntentstatusIntent=newIntent(Intent.ACTION_POWER_DISCONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent,UserHandle.ALL);
- }
- });
- }
- //发送低电量提醒(这个跟系统低电量提醒没关系,只是发出去了)
- if(sendBatteryLow){
- mSentLowBatteryBroadcast=true;
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- IntentstatusIntent=newIntent(Intent.ACTION_BATTERY_LOW);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent,UserHandle.ALL);
- }
- });
- }elseif(mSentLowBatteryBroadcast&&mLastBatteryLevel>=mLowBatteryCloseWarningLevel){//电量超过20了。电池状态OK了
- mSentLowBatteryBroadcast=false;
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- IntentstatusIntent=newIntent(Intent.ACTION_BATTERY_OKAY);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent,UserHandle.ALL);
- }
- });
- }
- //UpdatethebatteryLED
- mLed.updateLightsLocked();
- //ThisneedstobedoneaftersendIntent()sothatwegetthelastestbatterystats.
- if(logOutlier&&dischargeDuration!=0){
- logOutlierLocked(dischargeDuration);
- }
- mLastBatteryStatus=mBatteryProps.batteryStatus;
- mLastBatteryHealth=mBatteryProps.batteryHealth;
- mLastBatteryPresent=mBatteryProps.batteryPresent;
- mLastBatteryLevel=mBatteryProps.batteryLevel;
- mLastPlugType=mPlugType;
- mLastBatteryVoltage=mBatteryProps.batteryVoltage;
- mLastBatteryTemperature=mBatteryProps.batteryTemperature;
- mLastBatteryLevelCritical=mBatteryLevelCritical;
- mLastInvalidCharger=mInvalidCharger;
- }
- }
- //电池电量改变,把属性发出去(系统低电量提醒接收的是这个广播)
- privatevoidsendIntentLocked(){
- //Packupthevaluesandbroadcastthemtoeveryone
- finalIntentintent=newIntent(Intent.ACTION_BATTERY_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- |Intent.FLAG_RECEIVER_REPLACE_PENDING);
- inticon=getIconLocked(mBatteryProps.batteryLevel);
- intent.putExtra(BatteryManager.EXTRA_STATUS,mBatteryProps.batteryStatus);
- intent.putExtra(BatteryManager.EXTRA_HEALTH,mBatteryProps.batteryHealth);
- intent.putExtra(BatteryManager.EXTRA_PRESENT,mBatteryProps.batteryPresent);
- intent.putExtra(BatteryManager.EXTRA_LEVEL,mBatteryProps.batteryLevel);
- 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);
- if(DEBUG){
- Slog.d(TAG,"SendingACTION_BATTERY_CHANGED.level:"+mBatteryProps.batteryLevel+
- ",scale:"+BATTERY_SCALE+",status:"+mBatteryProps.batteryStatus+
- ",health:"+mBatteryProps.batteryHealth+",present:"+mBatteryProps.batteryPresent+
- ",voltage:"+mBatteryProps.batteryVoltage+
- ",temperature:"+mBatteryProps.batteryTemperature+
- ",technology:"+mBatteryProps.batteryTechnology+
- ",ACpowered:"+mBatteryProps.chargerAcOnline+",USBpowered:"+mBatteryProps.chargerUsbOnline+
- ",Wirelesspowered:"+mBatteryProps.chargerWirelessOnline+
- ",icon:"+icon+",invalidcharger:"+mInvalidCharger);
- }
- mHandler.post(newRunnable(){
- @Override
- publicvoidrun(){
- ActivityManagerNative.broadcastStickyIntent(intent,null,UserHandle.USER_ALL);
- }
- });
- }
- privatevoidlogBatteryStatsLocked(){
- IBinderbatteryInfoService=ServiceManager.getService(BatteryStats.SERVICE_NAME);
- if(batteryInfoService==null)return;
- DropBoxManagerdb=(DropBoxManager)mContext.getSystemService(Context.DROPBOX_SERVICE);
- if(db==null||!db.isTagEnabled("BATTERY_DISCHARGE_INFO"))return;
- FiledumpFile=null;
- FileOutputStreamdumpStream=null;
- try{
- //dumptheservicetoafile
- dumpFile=newFile(DUMPSYS_DATA_PATH+BatteryStats.SERVICE_NAME+".dump");
- dumpStream=newFileOutputStream(dumpFile);
- batteryInfoService.dump(dumpStream.getFD(),DUMPSYS_ARGS);
- FileUtils.sync(dumpStream);
- //adddumpfiletodropbox
- db.addFile("BATTERY_DISCHARGE_INFO",dumpFile,DropBoxManager.IS_TEXT);
- }catch(RemoteExceptione){
- Slog.e(TAG,"failedtodumpbatteryservice",e);
- }catch(IOExceptione){
- Slog.e(TAG,"failedtowritedumpsysfile",e);
- }finally{
- //makesurewecleanup
- if(dumpStream!=null){
- try{
- dumpStream.close();
- }catch(IOExceptione){
- Slog.e(TAG,"failedtoclosedumpsysoutputstream");
- }
- }
- if(dumpFile!=null&&!dumpFile.delete()){
- Slog.e(TAG,"failedtodeletetemporarydumpsysfile:"
- +dumpFile.getAbsolutePath());
- }
- }
- }
- privatevoidlogOutlierLocked(longduration){
- ContentResolvercr=mContext.getContentResolver();
- StringdischargeThresholdString=Settings.Global.getString(cr,
- Settings.Global.BATTERY_DISCHARGE_THRESHOLD);
- StringdurationThresholdString=Settings.Global.getString(cr,
- Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD);
- if(dischargeThresholdString!=null&&durationThresholdString!=null){
- try{
- longdurationThreshold=Long.parseLong(durationThresholdString);
- intdischargeThreshold=Integer.parseInt(dischargeThresholdString);
- if(duration<=durationThreshold&&
- mDischargeStartLevel-mBatteryProps.batteryLevel>=dischargeThreshold){
- //Ifthedischargecycleisbadenoughwewanttoknowaboutit.
- logBatteryStatsLocked();
- }
- if(DEBUG)Slog.v(TAG,"durationthreshold:"+durationThreshold+
- "dischargethreshold:"+dischargeThreshold);
- if(DEBUG)Slog.v(TAG,"duration:"+duration+"discharge:"+
- (mDischargeStartLevel-mBatteryProps.batteryLevel));
- }catch(NumberFormatExceptione){
- Slog.e(TAG,"InvalidDischargeThresholdsGServicestring:"+
- durationThresholdString+"or"+dischargeThresholdString);
- return;
- }
- }
- }
- privateintgetIconLocked(intlevel){
- if(mBatteryProps.batteryStatus==BatteryManager.BATTERY_STATUS_CHARGING){
- returncom.android.internal.R.drawable.stat_sys_battery_charge;
- }elseif(mBatteryProps.batteryStatus==BatteryManager.BATTERY_STATUS_DISCHARGING){
- returncom.android.internal.R.drawable.stat_sys_battery;
- }elseif(mBatteryProps.batteryStatus==BatteryManager.BATTERY_STATUS_NOT_CHARGING
- ||mBatteryProps.batteryStatus==BatteryManager.BATTERY_STATUS_FULL){
- if(isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
- &&mBatteryProps.batteryLevel>=100){
- returncom.android.internal.R.drawable.stat_sys_battery_charge;
- }else{
- returncom.android.internal.R.drawable.stat_sys_battery;
- }
- }else{
- returncom.android.internal.R.drawable.stat_sys_battery_unknown;
- }
- }
- @Override
- protectedvoiddump(FileDescriptorfd,PrintWriterpw,String[]args){
- if(mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- !=PackageManager.PERMISSION_GRANTED){
- pw.println("PermissionDenial:can'tdumpBatteryservicefromfrompid="
- +Binder.getCallingPid()
- +",uid="+Binder.getCallingUid());
- return;
- }
- synchronized(mLock){
- if(args==null||args.length==0||"-a".equals(args[0])){
- pw.println("CurrentBatteryServicestate:");
- if(mUpdatesStopped){
- pw.println("(UPDATESSTOPPED--use'reset'torestart)");
- }
- pw.println("ACpowered:"+mBatteryProps.chargerAcOnline);
- pw.println("USBpowered:"+mBatteryProps.chargerUsbOnline);
- pw.println("Wirelesspowered:"+mBatteryProps.chargerWirelessOnline);
- pw.println("status:"+mBatteryProps.batteryStatus);
- pw.println("health:"+mBatteryProps.batteryHealth);
- pw.println("present:"+mBatteryProps.batteryPresent);
- pw.println("level:"+mBatteryProps.batteryLevel);
- pw.println("scale:"+BATTERY_SCALE);
- pw.println("voltage:"+mBatteryProps.batteryVoltage);
- if(mBatteryProps.batteryCurrentNow!=Integer.MIN_VALUE){
- pw.println("currentnow:"+mBatteryProps.batteryCurrentNow);
- }
- if(mBatteryProps.batteryChargeCounter!=Integer.MIN_VALUE){
- pw.println("chargecounter:"+mBatteryProps.batteryChargeCounter);
- }
- pw.println("temperature:"+mBatteryProps.batteryTemperature);
- pw.println("technology:"+mBatteryProps.batteryTechnology);
- }elseif(args.length==3&&"set".equals(args[0])){
- Stringkey=args[1];
- Stringvalue=args[2];
- try{
- booleanupdate=true;
- if("ac".equals(key)){
- mBatteryProps.chargerAcOnline=Integer.parseInt(value)!=0;
- }elseif("usb".equals(key)){
- mBatteryProps.chargerUsbOnline=Integer.parseInt(value)!=0;
- }elseif("wireless".equals(key)){
- mBatteryProps.chargerWirelessOnline=Integer.parseInt(value)!=0;
- }elseif("status".equals(key)){
- mBatteryProps.batteryStatus=Integer.parseInt(value);
- }elseif("level".equals(key)){
- mBatteryProps.batteryLevel=Integer.parseInt(value);
- }elseif("invalid".equals(key)){
- mInvalidCharger=Integer.parseInt(value);
- }else{
- pw.println("Unknownsetoption:"+key);
- update=false;
- }
- if(update){
- longident=Binder.clearCallingIdentity();
- try{
- mUpdatesStopped=true;
- processValuesLocked();
- }finally{
- Binder.restoreCallingIdentity(ident);
- }
- }
- }catch(NumberFormatExceptionex){
- pw.println("Badvalue:"+value);
- }
- }elseif(args.length==1&&"reset".equals(args[0])){
- longident=Binder.clearCallingIdentity();
- try{
- mUpdatesStopped=false;
- }finally{
- Binder.restoreCallingIdentity(ident);
- }
- }else{
- pw.println("Dumpcurrentbatterystate,or:");
- pw.println("setac|usb|wireless|status|level|invalid<value>");
- pw.println("reset");
- }
- }
- }
- privatefinalUEventObservermInvalidChargerObserver=newUEventObserver(){
- @Override
- publicvoidonUEvent(UEventObserver.UEventevent){
- finalintinvalidCharger="1".equals(event.get("SWITCH_STATE"))?1:0;
- synchronized(mLock){
- if(mInvalidCharger!=invalidCharger){
- mInvalidCharger=invalidCharger;
- }
- }
- }
- };
- privatefinalclassLed{
- privatefinalLightsService.LightmBatteryLight;
- privatefinalintmBatteryLowARGB;
- privatefinalintmBatteryMediumARGB;
- privatefinalintmBatteryFullARGB;
- privatefinalintmBatteryLedOn;
- privatefinalintmBatteryLedOff;
- publicLed(Contextcontext,LightsServicelights){
- mBatteryLight=lights.getLight(LightsService.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);
- }
- /**
- *SynchronizeonBatteryService.
- */
- publicvoidupdateLightsLocked(){
- finalintlevel=mBatteryProps.batteryLevel;
- finalintstatus=mBatteryProps.batteryStatus;
- if(level<mLowBatteryWarningLevel){
- if(status==BatteryManager.BATTERY_STATUS_CHARGING){
- //Solidredwhenbatteryischarging
- mBatteryLight.setColor(mBatteryLowARGB);
- }else{
- //Flashredwhenbatteryislowandnotcharging
- mBatteryLight.setFlashing(mBatteryLowARGB,LightsService.LIGHT_FLASH_TIMED,
- mBatteryLedOn,mBatteryLedOff);
- }
- }elseif(status==BatteryManager.BATTERY_STATUS_CHARGING
- ||status==BatteryManager.BATTERY_STATUS_FULL){
- if(status==BatteryManager.BATTERY_STATUS_FULL||level>=90){
- //Solidgreenwhenfullorchargingandnearlyfull
- mBatteryLight.setColor(mBatteryFullARGB);
- }else{
- //Solidorangewhenchargingandhalfwayfull
- mBatteryLight.setColor(mBatteryMediumARGB);
- }
- }else{
- //Nolightsifnotchargingandnotlow
- mBatteryLight.turnOff();
- }
- }
- }
- privatefinalclassBatteryListenerextendsIBatteryPropertiesListener.Stub{
- publicvoidbatteryPropertiesChanged(BatteryPropertiesprops){
- BatteryService.this.update(props);
- }
- }
- }
总结如下: 此服务构造时会注册监听到系统JNI层。 当电池电量改变的时候会调用update(BatteryProperties props) -----》processValuesLocked() 。 而processValuesLocked() 函数会把电池状态把广播发送出去。其他类再接收广播进行处理
下一个类就是低电量提醒了,文件目录:\frameworks\base\packages\SystemUI\src\com\android\systemui\power\PowerUI.java
[java] view plain copy
- /*
- *Copyright(C)2008TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packagecom.android.systemui.power;
- importandroid.app.AlertDialog;
- importandroid.content.BroadcastReceiver;
- importandroid.content.ContentResolver;
- importandroid.content.Context;
- importandroid.content.DialogInterface;
- importandroid.content.Intent;
- importandroid.content.IntentFilter;
- importandroid.media.AudioManager;
- importandroid.media.Ringtone;
- importandroid.media.RingtoneManager;
- importandroid.net.Uri;
- importandroid.os.BatteryManager;
- importandroid.os.Handler;
- importandroid.os.PowerManager;
- importandroid.os.SystemClock;
- importandroid.os.UserHandle;
- importandroid.provider.Settings;
- importandroid.util.Slog;
- importandroid.view.View;
- importandroid.view.WindowManager;
- importandroid.widget.TextView;
- importcom.android.systemui.R;
- importcom.android.systemui.SystemUI;
- importjava.io.FileDescriptor;
- importjava.io.PrintWriter;
- importjava.util.Arrays;
- publicclassPowerUIextendsSystemUI{//总体说一下,这里才是处理低电量提醒的地方,他接收的广播是Intent.ACTION_BATTERY_CHANGED
- staticfinalStringTAG="PowerUI";
- staticfinalbooleanDEBUG=false;
- HandlermHandler=newHandler();
- intmBatteryLevel=100;
- intmBatteryStatus=BatteryManager.BATTERY_STATUS_UNKNOWN;
- intmPlugType=0;
- intmInvalidCharger=0;
- intmLowBatteryAlertCloseLevel;
- int[]mLowBatteryReminderLevels=newint[2];
- AlertDialogmInvalidChargerDialog;
- AlertDialogmLowBatteryDialog;
- TextViewmBatteryLevelTextView;
- privatelongmScreenOffTime=-1;
- publicvoidstart(){//这个类会在手机启动后,在SystemUI里启动(就是系统界面)。
- mLowBatteryAlertCloseLevel=mContext.getResources().getInteger(//电量告警取消值,值20
- com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
- mLowBatteryReminderLevels[0]=mContext.getResources().getInteger(//低电量提醒15
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
- mLowBatteryReminderLevels[1]=mContext.getResources().getInteger(//低电量临界值4
- com.android.internal.R.integer.config_criticalBatteryWarningLevel);
- finalPowerManagerpm=(PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
- mScreenOffTime=pm.isScreenOn()?-1:SystemClock.elapsedRealtime();
- //RegisterforIntentbroadcastsfor...
- IntentFilterfilter=newIntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- mContext.registerReceiver(mIntentReceiver,filter,null,mHandler);
- }
- /**
- *Bucketsthebatterylevel.
- *
- *ThecodeinthisfunctionisalittleweirdbecauseIcouldn'tcomprehend
- *thebucketgoingupwhenthebatterylevelwasgoingdown.--joeo
- *
- *1meansthatthebatteryis"ok"
- *0meansthatthebatteryisbetween"ok"andwhatweshouldwarnabout.
- *lessthan0meansthatthebatteryislow
- */
- privateintfindBatteryLevelBucket(intlevel){//这个方法是用来警告判断用的。
- if(level>=mLowBatteryAlertCloseLevel){
- return1;
- }
- if(level>=mLowBatteryReminderLevels[0]){
- return0;
- }
- finalintN=mLowBatteryReminderLevels.length;
- for(inti=N-1;i>=0;i--){
- if(level<=mLowBatteryReminderLevels[i]){
- return-1-i;
- }
- }
- thrownewRuntimeException("notpossible!");
- }
- privateBroadcastReceivermIntentReceiver=newBroadcastReceiver(){//重点,广播接收处理
- @Override
- publicvoidonReceive(Contextcontext,Intentintent){
- Stringaction=intent.getAction();
- if(action.equals(Intent.ACTION_BATTERY_CHANGED)){//电池电量改变
- finalintoldBatteryLevel=mBatteryLevel;//下边就是根据Intent获取BatteryService传过来的电池属性
- mBatteryLevel=intent.getIntExtra(BatteryManager.EXTRA_LEVEL,100);/
- finalintoldBatteryStatus=mBatteryStatus;
- mBatteryStatus=intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- finalintoldPlugType=mPlugType;
- mPlugType=intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,1);
- finalintoldInvalidCharger=mInvalidCharger;
- mInvalidCharger=intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER,0);
- finalbooleanplugged=mPlugType!=0;
- finalbooleanoldPlugged=oldPlugType!=0;
- intoldBucket=findBatteryLevelBucket(oldBatteryLevel);//这两个值特别有意思,就是说记录下老的电量,记录一下新的电量,比较电量是增加了,还是减小了
- intbucket=findBatteryLevelBucket(mBatteryLevel);
- if(DEBUG){
- Slog.d(TAG,"buckets....."+mLowBatteryAlertCloseLevel
- +".."+mLowBatteryReminderLevels[0]
- +".."+mLowBatteryReminderLevels[1]);
- Slog.d(TAG,"level"+oldBatteryLevel+"-->"+mBatteryLevel);
- Slog.d(TAG,"status"+oldBatteryStatus+"-->"+mBatteryStatus);
- Slog.d(TAG,"plugType"+oldPlugType+"-->"+mPlugType);
- Slog.d(TAG,"invalidCharger"+oldInvalidCharger+"-->"+mInvalidCharger);
- Slog.d(TAG,"bucket"+oldBucket+"-->"+bucket);
- Slog.d(TAG,"plugged"+oldPlugged+"-->"+plugged);
- }
- if(oldInvalidCharger==0&&mInvalidCharger!=0){
- Slog.d(TAG,"showinginvalidchargerwarning");
- showInvalidChargerDialog();//就是充电器不识别的弹窗
- return;
- }elseif(oldInvalidCharger!=0&&mInvalidCharger==0){
- dismissInvalidChargerDialog();
- }elseif(mInvalidChargerDialog!=null){
- //ifinvalidchargerisshowing,don'tshowlowbattery
- return;
- }
- if(!plugged
- &&(bucket<oldBucket||oldPlugged)
- &&mBatteryStatus!=BatteryManager.BATTERY_STATUS_UNKNOWN
- &&bucket<0){
- showLowBatteryWarning();<spanstyle="color:#FF0000;">//这里哈,低电量提醒的弹窗</span>
- //onlyplaySFXwhenthedialogcomesuporthebucketchanges
- if(bucket!=oldBucket||oldPlugged){
- playLowBatterySound();
- }
- }elseif(plugged||(bucket>oldBucket&&bucket>0)){//插上充电器或者充电电池电量超过20取消弹窗
- dismissLowBatteryWarning();
- }elseif(mBatteryLevelTextView!=null){
- showLowBatteryWarning();
- }
- }elseif(Intent.ACTION_SCREEN_OFF.equals(action)){
- mScreenOffTime=SystemClock.elapsedRealtime();
- }elseif(Intent.ACTION_SCREEN_ON.equals(action)){
- mScreenOffTime=-1;
- }else{
- Slog.w(TAG,"unknownintent:"+intent);
- }
- }
- };
- voiddismissLowBatteryWarning(){
- if(mLowBatteryDialog!=null){
- Slog.i(TAG,"closinglowbatterywarning:level="+mBatteryLevel);
- mLowBatteryDialog.dismiss();
- }
- }
- voidshowLowBatteryWarning(){
- Slog.i(TAG,
- ((mBatteryLevelTextView==null)?"showing":"updating")
- +"lowbatterywarning:level="+mBatteryLevel
- +"["+findBatteryLevelBucket(mBatteryLevel)+"]");
- CharSequencelevelText=mContext.getString(
- R.string.battery_low_percent_format,mBatteryLevel);
- if(mBatteryLevelTextView!=null){
- mBatteryLevelTextView.setText(levelText);
- }else{
- Viewv=View.inflate(mContext,R.layout.battery_low,null);
- mBatteryLevelTextView=(TextView)v.findViewById(R.id.level_percent);
- mBatteryLevelTextView.setText(levelText);
- AlertDialog.Builderb=newAlertDialog.Builder(mContext);
- b.setCancelable(true);
- b.setTitle(R.string.battery_low_title);
- b.setView(v);
- b.setIconAttribute(android.R.attr.alertDialogIcon);
- b.setPositiveButton(android.R.string.ok,null);
- finalIntentintent=newIntent(Intent.ACTION_POWER_USAGE_SUMMARY);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- |Intent.FLAG_ACTIVITY_MULTIPLE_TASK
- |Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- |Intent.FLAG_ACTIVITY_NO_HISTORY);
- if(intent.resolveActivity(mContext.getPackageManager())!=null){
- b.setNegativeButton(R.string.battery_low_why,
- newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- mContext.startActivityAsUser(intent,UserHandle.CURRENT);
- dismissLowBatteryWarning();
- }
- });
- }
- AlertDialogd=b.create();
- d.setOnDismissListener(newDialogInterface.OnDismissListener(){
- @Override
- publicvoidonDismiss(DialogInterfacedialog){
- mLowBatteryDialog=null;
- mBatteryLevelTextView=null;
- }
- });
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- d.getWindow().getAttributes().privateFlags|=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- d.show();
- mLowBatteryDialog=d;
- }
- }
- voidplayLowBatterySound(){
- finalContentResolvercr=mContext.getContentResolver();
- finalintsilenceAfter=Settings.Global.getInt(cr,
- Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,0);
- finallongoffTime=SystemClock.elapsedRealtime()-mScreenOffTime;
- if(silenceAfter>0
- &&mScreenOffTime>0
- &&offTime>silenceAfter){
- Slog.i(TAG,"screenofftoolong("+offTime+"ms,limit"+silenceAfter
- +"ms):notwakinguptheuserwithlowbatterysound");
- return;
- }
- if(DEBUG){
- Slog.d(TAG,"playinglowbatterysound.pick-a-doop!");//WOMP-WOMPisdeprecated
- }
- if(Settings.Global.getInt(cr,Settings.Global.POWER_SOUNDS_ENABLED,1)==1){
- finalStringsoundPath=Settings.Global.getString(cr,
- Settings.Global.LOW_BATTERY_SOUND);
- if(soundPath!=null){
- finalUrisoundUri=Uri.parse("file://"+soundPath);
- if(soundUri!=null){
- finalRingtonesfx=RingtoneManager.getRingtone(mContext,soundUri);
- if(sfx!=null){
- sfx.setStreamType(AudioManager.STREAM_SYSTEM);
- sfx.play();
- }
- }
- }
- }
- }
- voiddismissInvalidChargerDialog(){
- if(mInvalidChargerDialog!=null){
- mInvalidChargerDialog.dismiss();
- }
- }
- voidshowInvalidChargerDialog(){
- Slog.d(TAG,"showinginvalidchargerdialog");
- dismissLowBatteryWarning();
- AlertDialog.Builderb=newAlertDialog.Builder(mContext);
- b.setCancelable(true);
- b.setMessage(R.string.invalid_charger);
- b.setIconAttribute(android.R.attr.alertDialogIcon);
- b.setPositiveButton(android.R.string.ok,null);
- AlertDialogd=b.create();
- d.setOnDismissListener(newDialogInterface.OnDismissListener(){
- publicvoidonDismiss(DialogInterfacedialog){
- mInvalidChargerDialog=null;
- mBatteryLevelTextView=null;
- }
- });
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- d.show();
- mInvalidChargerDialog=d;
- }
- publicvoiddump(FileDescriptorfd,PrintWriterpw,String[]args){
- pw.print("mLowBatteryAlertCloseLevel=");
- pw.println(mLowBatteryAlertCloseLevel);
- pw.print("mLowBatteryReminderLevels=");
- pw.println(Arrays.toString(mLowBatteryReminderLevels));
- pw.print("mInvalidChargerDialog=");
- pw.println(mInvalidChargerDialog==null?"null":mInvalidChargerDialog.toString());
- pw.print("mLowBatteryDialog=");
- pw.println(mLowBatteryDialog==null?"null":mLowBatteryDialog.toString());
- pw.print("mBatteryLevel=");
- pw.println(Integer.toString(mBatteryLevel));
- pw.print("mBatteryStatus=");
- pw.println(Integer.toString(mBatteryStatus));
- pw.print("mPlugType=");
- pw.println(Integer.toString(mPlugType));
- pw.print("mInvalidCharger=");
- pw.println(Integer.toString(mInvalidCharger));
- pw.print("mScreenOffTime=");
- pw.print(mScreenOffTime);
- if(mScreenOffTime>=0){
- pw.print("(");
- pw.print(SystemClock.elapsedRealtime()-mScreenOffTime);
- pw.print("ago)");
- }
- pw.println();
- pw.print("soundTimeout=");
- pw.println(Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,0));
- pw.print("bucket:");
- pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- }
- }
总结一下:这个类就是接收电池电量改变的广播,然后弹窗提醒。
下一个类就是没电关机界面了,文件目录:\frameworks\base\services\java\com\android\server\ShutdownLowBatteryActivity.java
这个Activity的配置文件是这样的(\frameworks\base\core\res\AndroidManifest.xml):
[html] view plain copy
- <activityandroid:name="com.android.server.ShutdownLowBatteryActivity"
- android:theme="@android:style/Theme.Translucent.NoTitleBar"
- android:configChanges="orientation|keyboardHidden|screenSize"
- android:windowSoftInputMode="stateHidden"
- android:permission="android.permission.SHUTDOWN"
- android:excludeFromRecents="true">
- <intent-filter>
- <actionandroid:name="android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY"/>
- <categoryandroid:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
android:theme="@android:style/Theme.Translucent.NoTitleBar"是API小于11的透明主题。这样弹出的dialog会是老版本的主题。(这个Activity是透明的)
对于Theme,因为是4.4,我更倾向于:android:theme="@android:style/Theme.Holo.Panel"
ShutdownLowBatteryActivity.java:
[java] view plain copy
- /*
- *Copyright(C)2009TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packagecom.android.server;
- importandroid.app.Activity;
- importandroid.app.AlertDialog;
- importandroid.app.KeyguardManager;
- importandroid.content.BroadcastReceiver;
- importandroid.content.Context;
- importandroid.content.DialogInterface;
- importandroid.content.Intent;
- importandroid.content.IntentFilter;
- importandroid.os.Bundle;
- importandroid.os.Handler;
- importandroid.util.Slog;
- importandroid.view.Window;
- importandroid.view.WindowManager;
- importandroid.view.View;
- //importcom.android.internal.app.ShutdownThread;
- importcom.android.server.power.ShutdownThread;
- importandroid.telephony.TelephonyManager;
- importandroid.telephony.PhoneStateListener;
- importandroid.media.MediaPlayer;
- importandroid.media.MediaPlayer.OnCompletionListener;
- importandroid.content.ContentResolver;
- importandroid.provider.Settings;
- importjava.io.IOException;
- publicclassShutdownLowBatteryActivityextendsActivity{
- privatestaticfinalStringTAG="ShutdownLowBatteryActivity";
- privatebooleanmConfirm;
- privateintmSeconds=15;//电池电量等于015秒内不插充电器就自动关机
- privateAlertDialogmDialog;
- privateHandlermyHandler=newHandler();
- privateRunnablemyRunnable=newRunnable(){//这里数秒关机
- @Override
- publicvoidrun(){
- mSeconds--;
- if(mSeconds<1)
- mSeconds=0;
- mDialog.setMessage(getString(com.android.internal.R.string.low_battery_shutdown_after_seconds,mSeconds));
- if(mSeconds<=1){
- myHandler.removeCallbacks(myRunnable);
- Handlerh=newHandler();
- h.post(newRunnable(){
- publicvoidrun(){
- ShutdownThread.shutdown(ShutdownLowBatteryActivity.this,mConfirm);
- }
- });
- }
- myHandler.postDelayed(myRunnable,1000);
- }
- };
- privateBroadcastReceivermReceiver;
- privateMediaPlayermplayer;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- mConfirm=getIntent().getBooleanExtra(Intent.EXTRA_KEY_CONFIRM,false);
- Slog.i(TAG,"onCreate():confirm="+mConfirm);
- //if(getIntent().getBooleanExtra("can_be_cancel",false)){//这行注释掉了:然后当连上充电器后或者电量涨到20的时候,就取消倒计时关机
- mReceiver=newBroadcastReceiver(){
- @Override
- publicvoidonReceive(Contextcontext,Intentintent){
- if(Intent.ACTION_BATTERY_OKAY.equals(intent.getAction())|
- Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())){
- ShutDownWakeLock.releaseCpuLock();
- myHandler.removeCallbacks(myRunnable);
- if(mReceiver!=null)
- unregisterReceiver(mReceiver);
- finish();
- }
- }
- };
- IntentFilterfilter=newIntentFilter(Intent.ACTION_POWER_CONNECTED);
- filter.addAction(Intent.ACTION_BATTERY_OKAY);
- registerReceiver(mReceiver,filter);
- //}
- PhoneStateListenermPhoneStateListener=newPhoneStateListener(){//如果正数秒呢,电话呼入了。取消自动关机
- @Override
- publicvoidonCallStateChanged(intstate,Stringignored){
- if(state==TelephonyManager.CALL_STATE_RINGING){
- ShutDownWakeLock.releaseCpuLock();
- myHandler.removeCallbacks(myRunnable);
- finish();
- }
- }
- };
- TelephonyManagermTelephonyManager=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
- mTelephonyManager.listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_CALL_STATE);
- requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
- Windowwin=getWindow();
- win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- |WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- |WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
- setContentView(newView(this));
- mDialog=newAlertDialog.Builder(this).create();
- mDialog.setTitle(com.android.internal.R.string.low_battery_shutdown_title);
- mDialog.setMessage(getString(com.android.internal.R.string.low_battery_shutdown_after_seconds,mSeconds));
- if(!getIntent().getBooleanExtra("cant_be_cancel_by_button",false)){//读取配置文件,是否运行取消,然后根据这个显示取消自动关机按钮
- mDialog.setButton(DialogInterface.BUTTON_NEUTRAL,getText(com.android.internal.R.string.cancel),newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- myHandler.removeCallbacks(myRunnable);
- dialog.cancel();
- if(mReceiver!=null)
- unregisterReceiver(mReceiver);
- finish();
- }});
- }
- mDialog.setCancelable(false);
- //mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- mDialog.show();
- if(mConfirm==false){
- myHandler.postDelayed(myRunnable,1000);
- }
- myHandler.post(newRunnable(){
- publicvoidrun(){
- finalContentResolvercr=getContentResolver();
- Stringpath=Settings.System.getString(cr,Settings.System.NOTIFICATION_SOUND);
- mplayer=newMediaPlayer();
- try{
- mplayer.reset();
- mplayer.setDataSource("system/media/audio/ui/LowBattery.ogg");
- mplayer.prepare();
- mplayer.start();
- mplayer.setOnCompletionListener(newOnCompletionListener(){
- @Override
- publicvoidonCompletion(MediaPlayermp){
- if(null!=mplayer){
- mplayer.stop();
- mplayer.release();
- mplayer=null;
- }
- }
- });
- }
- catch(IOExceptione){
- }
- }
- });
- }
- }
最后一个相关的类,文件路径:\frameworks\base\packages\SystemUI\src\com\android\systemui\BatteryMeterView.java
这个类是自定义控件,定义在手机状态栏里:
[java] view plain copy
- /*
- *Copyright(C)2013TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packagecom.android.systemui;
- importandroid.content.BroadcastReceiver;
- importandroid.content.Context;
- importandroid.content.Intent;
- importandroid.content.IntentFilter;
- importandroid.content.res.Resources;
- importandroid.content.res.TypedArray;
- importandroid.graphics.Canvas;
- importandroid.graphics.Paint;
- importandroid.graphics.Path;
- importandroid.graphics.PorterDuff;
- importandroid.graphics.PorterDuffXfermode;
- importandroid.graphics.Rect;
- importandroid.graphics.RectF;
- importandroid.graphics.Typeface;
- importandroid.os.BatteryManager;
- importandroid.os.Bundle;
- importandroid.provider.Settings;
- importandroid.util.AttributeSet;
- importandroid.view.View;
- publicclassBatteryMeterViewextendsViewimplementsDemoMode{
- publicstaticfinalStringTAG=BatteryMeterView.class.getSimpleName();
- publicstaticfinalStringACTION_LEVEL_TEST="com.android.systemui.BATTERY_LEVEL_TEST";
- publicstaticfinalbooleanENABLE_PERCENT=true;
- publicstaticfinalbooleanSINGLE_DIGIT_PERCENT=false;
- publicstaticfinalbooleanSHOW_100_PERCENT=false;
- publicstaticfinalintFULL=96;
- publicstaticfinalintEMPTY=4;
- publicstaticfinalfloatSUBPIXEL=0.4f;//insetrectsforsofteredges
- int[]mColors;
- booleanmShowPercent=true;
- PaintmFramePaint,mBatteryPaint,mWarningTextPaint,mTextPaint,mBoltPaint;
- intmButtonHeight;
- privatefloatmTextHeight,mWarningTextHeight;
- privateintmHeight;
- privateintmWidth;
- privateStringmWarningString;
- privatefinalintmChargeColor;
- privatefinalfloat[]mBoltPoints;
- privatefinalPathmBoltPath=newPath();
- privatefinalRectFmFrame=newRectF();
- privatefinalRectFmButtonFrame=newRectF();
- privatefinalRectFmClipFrame=newRectF();
- privatefinalRectFmBoltFrame=newRectF();
- privateclassBatteryTrackerextendsBroadcastReceiver{
- publicstaticfinalintUNKNOWN_LEVEL=-1;
- //currentbatterystatus
- intlevel=UNKNOWN_LEVEL;
- StringpercentStr;
- intplugType;
- booleanplugged;
- inthealth;
- intstatus;
- Stringtechnology;
- intvoltage;
- inttemperature;
- booleantestmode=false;
- @Override
- publicvoidonReceive(Contextcontext,Intentintent){
- finalStringaction=intent.getAction();
- if(action.equals(Intent.ACTION_BATTERY_CHANGED)){//接收电量改变的广播,取电池状态的属性
- if(testmode&&!intent.getBooleanExtra("testmode",false))return;
- level=(int)(100f
- *intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0)
- /intent.getIntExtra(BatteryManager.EXTRA_SCALE,100));
- plugType=intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,0);
- plugged=plugType!=0;
- health=intent.getIntExtra(BatteryManager.EXTRA_HEALTH,
- BatteryManager.BATTERY_HEALTH_UNKNOWN);
- status=intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- technology=intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
- voltage=intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE,0);
- temperature=intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE,0);
- setContentDescription(
- context.getString(R.string.accessibility_battery_level,level));
- postInvalidate();
- }elseif(action.equals(ACTION_LEVEL_TEST)){
- testmode=true;
- post(newRunnable(){
- intcurLevel=0;
- intincr=1;
- intsaveLevel=level;
- intsavePlugged=plugType;
- Intentdummy=newIntent(Intent.ACTION_BATTERY_CHANGED);
- @Override
- publicvoidrun(){
- if(curLevel<0){
- testmode=false;
- dummy.putExtra("level",saveLevel);
- dummy.putExtra("plugged",savePlugged);
- dummy.putExtra("testmode",false);
- }else{
- dummy.putExtra("level",curLevel);
- dummy.putExtra("plugged",incr>0?BatteryManager.BATTERY_PLUGGED_AC:0);
- dummy.putExtra("testmode",true);
- }
- getContext().sendBroadcast(dummy);
- if(!testmode)return;
- curLevel+=incr;
- if(curLevel==100){
- incr*=-1;
- }
- postDelayed(this,200);
- }
- });
- }
- }
- }
- BatteryTrackermTracker=newBatteryTracker();
- @Override
- publicvoidonAttachedToWindow(){
- super.onAttachedToWindow();
- IntentFilterfilter=newIntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(ACTION_LEVEL_TEST);
- finalIntentsticky=getContext().registerReceiver(mTracker,filter);
- if(sticky!=null){
- //preloadthebatterylevel
- mTracker.onReceive(getContext(),sticky);
- }
- }
- @Override
- publicvoidonDetachedFromWindow(){
- super.onDetachedFromWindow();
- getContext().unregisterReceiver(mTracker);
更多相关文章
- Android(安卓)实现定时开关机另类实现--BSP级
- unity android获取电量和wifi信号强度
- 蓝牙遥控器获取电量GATT
- Android(安卓)优化电池使用时间 ——监控电池电量和充电状态
- Android实现电量控制降低耗电
- 展讯android LEDS模块分析----一个bug
- [置顶] Android(安卓)显示手机电池的当前电量
- 降低android应用程序耗电量的解决方案
- Android功耗测试小工具集锦