一,主要涉及的类

  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) { } } } } }

上面的代码

            
    // ShutdownThread must run on a looper capable of displaying the UI. Message msg = Message.obtain(mHandler, runnable) ; msg.setAsynchronous(true); mHandler.sendMessage(msg);

接下来转到ShutdownThread.java中,

            
    /** * Request a clean shutdown, waiting for subsystems to clean up their * state etc. Must be called from a Looper thread in which its UI * is shown. * * @param context Context used to display the shutdown progress dialog. * @param confirm true if user confirmation is needed before shutting down. */ public static void shutdown(final Context context, boolean confirm) { mReboot = false; mRebootSafeMode = false; shutdownInner(context, confirm); }
                
    // shutdown system ... confirm==false static void shutdownInner(final Context context, boolean confirm) { // ensure that only one thread is trying to power down. // any additional calls are just returned synchronized (sIsStartedGuard) { if (sIsStarted) { Log.d(TAG, "Request to shutdown already running, returning."); return; } } final int longPressBehavior = context.getResources().getInteger(

    com.android.internal.R.integer.config_longPressOnPowerBehavior);

    final int resourceId = mRebootSafeMode ? com.android.internal.R.string.reboot_safemode_confirm : (longPressBehavior == 2 ? com.android.internal.R.string.shutdown_confirm_question : com.android.internal.R.string.shutdown_confirm); //shutdown_confirm 您的手机将会关机 Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior); if (confirm) { //低电量关机流程时,confirm==false,因此走else分支 final CloseDialogReceiver closer = new CloseDialogReceiver(context); if (sConfirmDialog != null) { sConfirmDialog.dismiss(); } //Knight 2015.06.15 #### sConfirmDialog = new AlertDialog.Builder(context) .setTitle(mRebootSafeMode ? com.android.internal.R.string.reboot_safemode_title : (mReboot ? com.android.internal.R.string.reboot_title : com.android.internal.R.string.power_off)) .setMessage(mReboot ? com.android.internal.R.string.reboot_confirm : resourceId) .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { beginShutdownSequence(context); } }) .setNegativeButton(com.android.internal.R.string.no, null) .create(); closer.dialog = sConfirmDialog; sConfirmDialog.setOnDismissListener(closer); sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); sConfirmDialog.show(); } else { //低电量关机走的流程 beginShutdownSequence(context); } }
                    
    private static void beginShutdownSequence(Context context) { // 这部分显得有些多余,因为在进入该方法之前已经调用过下面这段代码了。 xiangxm add comments /* synchronized (sIsStartedGuard) { if (sIsStarted) { Log.d(TAG, "Shutdown sequence already running, returning."); return; } sIsStarted = true; }*/ // check the shutdown animation exists or not. boolean showShutdownAnim = new File("/system/media/shutdownanimation.zip").exists();

    下面的代码,主要是处理当关机的时候显示Dialog,并且显示进度条,以及使用PowerManager.WakeLock 保持cpu和屏幕

    不休眠。

    // throw up an indeterminate system dialog to indicate radio is

    // shutting down. ProgressDialog pd = new ProgressDialog(context); Log.d("frank_08_19", "mReboot = " + String.valueOf(mReboot)); //frank 08-19 if(mReboot){ // reboot progress pd.setTitle(context.getText(com.android.internal.R.string.reboot_wh)); pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress)); }else{ pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); } if (showShutdownAnim && SystemProperties.getBoolean("rw.use.shutdown.movie.wh", false)) { Log.d("frank_09_20", "shutdown animation"); SystemProperties.set("debug.shutdown_movie", "2"); //what android.os.SystemProperties.set("service.bootanim.exit", "0"); Intent intent=new Intent(); intent.setAction("wh_test_func_key"); //do home key context.sendBroadcast(intent); intent.setAction("frank.shutdown.rotation.screen"); //disable gsensor in database context.sendBroadcast(intent); //frank 09-20 int shutdown_movie = SystemProperties.getInt("rw.shutdownanim_frank.wh", 0); if(shutdown_movie != 0 ) { try{ Thread.sleep(shutdown_movie); }catch(InterruptedException ex){ } } android.os.SystemProperties.set("ctl.start", "shutdownanim"); //start shutdown movie } else //if(SystemProperties.getBoolean("rw.show.shutdown.dialog.wh", false)) { pd.setIndeterminate(true); pd.setCancelable(false); pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); pd.show(); } sInstance.mContext = context; sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); // make sure we never fall asleep again sInstance.mCpuWakeLock = null; try { sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu"); sInstance.mCpuWakeLock.setReferenceCounted(false);//many acqure() only onece release() sInstance.mCpuWakeLock.acquire(); } catch (SecurityException e) { Log.w(TAG, "No permission to acquire wake lock", e); sInstance.mCpuWakeLock = null; } // also make sure the screen stays on for better user experience sInstance.mScreenWakeLock = null; if (sInstance.mPowerManager.isScreenOn()) { try { sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock( PowerManager.FULL_WAKE_LOCK, TAG + "-screen"); sInstance.mScreenWakeLock.setReferenceCounted(false); sInstance.mScreenWakeLock.acquire(); } catch (SecurityException e) { Log.w(TAG, "No permission to acquire wake lock", e); sInstance.mScreenWakeLock = null; } } // start the thread that initiates shutdown sInstance.mHandler = new Handler() { }; sInstance.start(); }

接下来转到shutdownThread的run方法中,

run方法中,陆续关闭各个service等。后面的部分暂时不做分析。


更多相关文章

  1. Android中一些比较好的开源代码项目
  2. 推荐几个android 学习与应用 网站
  3. Android(安卓)使用WebView控件展示SVG图
  4. Android实现全屏
  5. 系出名门Android(6) - 控件(View)
  6. 【分享】大量android软件开发资料和实例代码【转】
  7. android异步图片加载三之handler+线程池+消息队列模式
  8. Android实现九宫格
  9. 获得Android(安卓)Linux系统增删文件的权限

随机推荐

  1. Android窗口机制
  2. 安卓学习教程
  3. Android异步处理系列文章四篇之一使用Thr
  4. android 系统源码在线阅读-------值得收
  5. Failed to find an AVD compatible with
  6. Android常见知识汇总
  7. Android异步任务
  8. Android中 android:gravity 和 android:l
  9. Android接口定义语言(AIDL)
  10. Android xml资源文件中@、@android:type