android framework 低电量关机处理流程 浅析

2019-04-13 13:50发布

一,主要涉及的类
  1.  ./base/services/java/com/android/server/BatteryService.java
  2.  ./base/services/java/com/android/server/ShutdownActivity.java
  3.  ./base/services/java/com/android/server/power/PowerManagerService.java
  4.  ./base/services/java/com/android/server/power/ShutdownThread.java
  5. ./base/core/java/android/os/PowerManager.java
二.BatteryService  监控电池电量等信息 android系统app上层更新显示电池电量信息,主要是靠BatterySerivice不断为其更新数据信息。至于如何更新的,另外的博文有分析。 这里主要分析低电量关机相关流程。 BatteryService中的update方法会间隔时间的不断更新。
    // 低电量的时候会弹出对话框并且接着关机。    private void shutdownIfNoPowerLocked() {        // shut down gracefully if our battery is critically low and we are not powered.        // wait until the system has booted before attempting to display the shutdown dialog.       //从这里的if判断条件可以看出低电量关机条件电量接近0并且没有连接充电。        if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {            mHandler.post(new Runnable() { // the battery is low and battery plugged .                @Override                public void run() {                    //跳转到ShutdownActivity.java                    if (ActivityManagerNative.isSystemReady()) {                        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);                        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);                    }                }            });        }    }
接下来,跳转到ShutdownActivity.java,这个acitivity比较简单,他吧另外的逻辑放在了子线程,直接获得PowerManagerService并调用其中的方法,因此重点是PowerManagerService.java
       @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);         Intent intent = getIntent();        if(intent==null){return ;} // google do not add this . but i add .        mReboot = Intent.ACTION_REBOOT.equals(intent.getAction()); //false  from the batteryService.java        mConfirm = intent.getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false); // false from the BatteryService.java        Slog.i(TAG, "onCreate(): confirm=" + mConfirm);         Thread thr = new Thread("ShutdownActivity") {            @Override            public void run() {                IPowerManager pm = IPowerManager.Stub.asInterface(                        ServiceManager.getService(Context.POWER_SERVICE));                try {                    if (mReboot) {                        pm.reboot(mConfirm, null, false);                    } else {                        pm.shutdown(mConfirm, false); //mConfirm ==false                    }                } catch (RemoteException e) {                }            }        };        thr.start();        finish();        // Wait for us to tell the power manager to shutdown.        try {            thr.join(); // wait for worker thread to do has job.        } catch (InterruptedException e) {        }    }
接下来,逻辑转移到PowerManagerService中、
       /**     * Shuts down the device.     *     * @param confirm If true, shows a shutdown confirmation dialog.     * @param wait If true, this call waits for the shutdown to complete and does not return.     */    @Override // Binder call    public void shutdown(boolean confirm, boolean wait) {        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);// u must get get the permission of reboot .        final long ident = Binder.clearCallingIdentity();        try {            shutdownOrRebootInternal(true, confirm, null, wait);// true ,false ,null,false        } finally {            Binder.restoreCallingIdentity(ident);        }    }     private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,            final String reason, boolean wait) {        if (mHandler == null || !mSystemReady) {            throw new IllegalStateException("Too early to call shutdown() or reboot()");        }  //看到这里你是否和我一样有点不解? why:  在ShutdownActivity中,是放在了子线程的,而到了这里继续被放到新的子线程。这样?        Runnable runnable = new Runnable() {            @Override            public void run() {                synchronized (this) {                    if (shutdown) {                        ShutdownThread.shutdown(mContext, confirm);//confirm == false                    } else {                        ShutdownThread.reboot(mContext, reason, confirm);                    }                }            }        };        // ShutdownThread must run on a looper capable of displaying the UI.        Message msg = Message.obtain(mHandler, runnable) ;        msg.setAsynchronous(true); //异步消息        mHandler.sendMessage(msg);         // PowerManager.reboot() is documented not to return so just wait for the inevitable.下面这段代码......        if (wait) {            synchronized (runnable) {                while (true) {                    try {                        runnable.wait();                    } catch (InterruptedException e) {                    }                }