成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入解析Android關(guān)機

移動開發(fā) Android
最后關(guān)機一定是在Linux kernel完成,說到底層其實就是Linux。所有的調(diào)用是為了停掉運行Android的虛擬機Dalvik和Dalvik與Kernel交互用的Server,至于關(guān)機按鈕怎么用,就是改改系統(tǒng)調(diào)用的事情。

Android 關(guān)機順序

  • 當我們長按電源按鈕時,手機里究竟發(fā)了什么?
  • 什么又是關(guān)機順序?
  • Android的關(guān)機順序與Linux桌面系統(tǒng)有何不同?
  • 如何更改關(guān)機菜單?

當我們說起Android的關(guān)機順序時,許多諸如此類的問題便會涌進我們的腦袋。 不過,在繼續(xù)閱讀之前,建議您首先能對開機順序有一個了解開機順序文章

Android是基于Linux內(nèi)核的開源操作系統(tǒng)。盡管x86(x86 是一系列計算機微處理器指令集及其架構(gòu)的統(tǒng)稱,這種架構(gòu)基于Intel 8086 CPU)是大多數(shù)Linux系統(tǒng)所采用的處理器架構(gòu),然而絕大多數(shù)Android系統(tǒng)卻運行于ARM架構(gòu)之上(ARM,又稱Advanced RISC Machine,其前身為Acorn RISC Machine),除了來自Intel的Xolo設(shè)備。這種移動設(shè)備使用了Atom 1. 6Ghz x86處理器。 但不論哪種架構(gòu),Android的關(guān)機順序都區(qū)別于Linux的桌面系統(tǒng),如Ubuntu、Fedora等。 本文主要介紹Android的關(guān)機順序, 如果想更多地了解Linux桌面系統(tǒng)的關(guān)機順序,請參考Linux的啟動與關(guān)閉流程

下圖詳細闡釋了Android的關(guān)機順序。

第一步: 按住電源按鈕半秒鐘(500ms)。

第二步: 之后,PhoneWindowManager.java 將捕獲長按電源按鈕這一事件并調(diào)用“interceptKeyBeforeQueueing”方法。

下面是處理長按電源鍵事件的代碼片段

  1. /** {@inheritDoc} */ 
  2. @Override 
  3. public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { 
  4. .... 
  5. .... 
  6. .... 
  7. case KeyEvent.KEYCODE_POWER: { 
  8.      result &= ~ACTION_PASS_TO_USER; 
  9.        if (down) { 
  10.          if (isScreenOn && !mPowerKeyTriggered 
  11.                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 
  12.                    mPowerKeyTriggered = true
  13.                    mPowerKeyTime = event.getDownTime(); 
  14.                    interceptScreenshotChord(); 
  15.             } 
  16.                ITelephony telephonyService = getTelephonyService(); 
  17.                 boolean hungUp = false
  18.                if (telephonyService != null) { 
  19.                    try { 
  20.                        if (telephonyService.isRinging()) { 
  21.                            // 如果在來電響鈴時按下電源鍵,則系統(tǒng)將關(guān)閉來電提示 
  22.                             telephonyService.silenceRinger(); 
  23.                        } else if ((mIncallPowerBehavior 
  24.                                 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 
  25.                                && telephonyService.isOffhook()) { 
  26.                             // 如果處在通話中且電源鍵掛斷選項已啟用,則按下電源鍵會結(jié)束當前通話 
  27.                             hungUp = telephonyService.endCall(); 
  28.                        } 
  29.                    } catch (RemoteException ex) { 
  30.                         Log.w(TAG, "ITelephony threw RemoteException", ex); 
  31.                    } 
  32.                } 
  33.                interceptPowerKeyDown(!isScreenOn || hungUp 
  34.                        || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered); 
  35.            } else { 
  36.                mPowerKeyTriggered = false
  37.                cancelPendingScreenshotChordAction(); 
  38.                if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { 
  39.                    result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; 
  40.                } 
  41.                mPendingPowerKeyUpCanceled = false
  42.            } 
  43.           break
  44.       } 
  45. .... 
  46. .... 
  47. .... 

上面的代碼包含了對多種情形下對長按電源鍵時間的處理,例如靜默來電響鈴、屏幕截圖以及關(guān)閉電源等。 系統(tǒng)將根據(jù)電源鍵被按住的時間長短以及相關(guān)按鍵的使用情況來決定如何恰當?shù)靥幚懋斍暗挠脩舨僮鳌?nbsp;當電源鍵被按下且沒有截屏操作觸發(fā)時interceptPowerKeyDown 將被調(diào)用,這時其他的按鍵響應(yīng)(其他按鍵響應(yīng)指 interceptKeyBeforeQueueing 中其他cases)將不會被觸發(fā)。

下面的代碼展示了 interceptPowerKeyDown 函數(shù)內(nèi)容, 函數(shù)將注冊一個回調(diào)函數(shù),在500毫秒超時事件(ViewConfiguration#getGlobalActionKeyTimeout())觸發(fā)時啟動 mPowerLongPress 線程。

  1. private void interceptPowerKeyDown(boolean handled) { 
  2.   mPowerKeyHandled = handled; 
  3.   if (!handled) { 
  4.        mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); 
  5.   } 

mPowerLongPress 線程的實現(xiàn)如下:

  1. private final Runnable mPowerLongPress = new Runnable() { 
  2.         @Override 
  3.         public void run() { 
  4.             // The context isn't read 
  5.             if (mLongPressOnPowerBehavior < 0) { 
  6.                 mLongPressOnPowerBehavior = mContext.getResources().getInteger( 
  7.                         com.android.internal.R.integer.config_longPressOnPowerBehavior); 
  8.             } 
  9.             int resolvedBehavior = mLongPressOnPowerBehavior; 
  10.             if (FactoryTest.isLongPressOnPowerOffEnabled()) { 
  11.                 resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; 
  12.             } 
  13.   
  14.             switch (resolvedBehavior) { 
  15.             case LONG_PRESS_POWER_NOTHING: 
  16.                 break
  17.             case LONG_PRESS_POWER_GLOBAL_ACTIONS: 
  18.                 mPowerKeyHandled = true
  19.                 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { 
  20.                     performAuditoryFeedbackForAccessibilityIfNeed(); 
  21.                 } 
  22.                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 
  23.                 showGlobalActionsDialog(); 
  24.                 break
  25.             case LONG_PRESS_POWER_SHUT_OFF: 
  26.             case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: 
  27.                 mPowerKeyHandled = true
  28.                 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 
  29.                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 
  30.                 mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF); 
  31.                 break
  32.             } 
  33.         } 
  34.     }; 

第三步: 由上面代碼的Switch分支可知,當程序進去Long_Press_Power_Global_Options時控制將移交給 GlobalActions 類, 該模塊則負責顯示關(guān)機選項的對話框,這些選項在各Android發(fā)行版(各OEM廠商定制的Android系統(tǒng), 不同的手機型號和不同版本的Android系統(tǒng))中不盡相同,通常包括關(guān)閉電源、飛行模式和屏幕截圖。也可能包括其他一些選項按鍵。GlobalActions 類實現(xiàn)了一個showdialog方法,該方法將根據(jù)當前系統(tǒng)支持的菜單內(nèi)容來創(chuàng)建這個對話框。

  1. void showGlobalActionsDialog() { 
  2.     if (mGlobalActions == null) { 
  3.         mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs); 
  4.     } 
  5.     final boolean keyguardShowing = keyguardIsShowingTq(); 
  6.     mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); 
  7.     if (keyguardShowing) { 
  8.          // 由于激活關(guān)機對話框需要長按電源鍵兩秒以上,所以當對話框顯示之后,屏幕的喚醒狀態(tài)將被鎖定,以方便用戶瀏覽對話框中內(nèi)容 
  9.         mKeyguardMediator.userActivity(); 
  10.     } 

第四步: 若用戶選擇“關(guān)閉電源“,則對系統(tǒng)的控制將交回給 PhoneWindowManager, 然后由PhoneWindowManager 啟動關(guān)閉流程。

第五步: 整個關(guān)機過程起始于ShutdownThread模塊中的shutdowninner方法。該方法首先創(chuàng)建一個確認對話框給用戶, 用戶可以選擇確認關(guān)機或是取消關(guān)機操作。 如果用戶選擇確認,則系統(tǒng)將真正進入關(guān)機流程。

第六步: 如上所述,當用戶點擊確認按鈕后beginShutdownSequence方法將被調(diào)用以啟動關(guān)機順序。

  1. private static void beginShutdownSequence(Context context) { 
  2.         synchronized (sIsStartedGuard) { 
  3.             if (sIsStarted) { 
  4.                 Log.d(TAG, "Shutdown sequence already running, returning."); 
  5.                 return
  6.             } 
  7.             sIsStarted = true
  8.         } 
  9.   
  10.         // 顯示正在關(guān)閉電源的對話框 
  11.         ProgressDialog pd = new ProgressDialog(context); 
  12.         pd.setTitle(context.getText(com.android.internal.R.string.power_off)); 
  13.         pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); 
  14.         pd.setIndeterminate(true); 
  15.         pd.setCancelable(false); 
  16.  
  17. pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 
  18.         pd.show(); 
  19.         sInstance.mContext = context; 
  20.         sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 
  21.         // 阻止CPU進入休眠狀態(tài) 
  22.         sInstance.mCpuWakeLock = null
  23.         try { 
  24.             sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( 
  25.                     PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu"); 
  26.             sInstance.mCpuWakeLock.setReferenceCounted(false); 
  27.             sInstance.mCpuWakeLock.acquire(); 
  28.         } catch (SecurityException e) { 
  29.             Log.w(TAG, "No permission to acquire wake lock", e); 
  30.             sInstance.mCpuWakeLock = null
  31.         } 
  32.         // 電源關(guān)閉前一直保持屏幕喚醒狀態(tài),以便提升用戶體驗 
  33.         sInstance.mScreenWakeLock = null
  34.         if (sInstance.mPowerManager.isScreenOn()) { 
  35.             try { 
  36.                 sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock( 
  37.                         PowerManager.FULL_WAKE_LOCK, TAG + "-screen"); 
  38.                sInstance.mScreenWakeLock.setReferenceCounted(false); 
  39.                 sInstance.mScreenWakeLock.acquire(); 
  40.             } catch (SecurityException e) { 
  41.                 Log.w(TAG, "No permission to acquire wake lock", e); 
  42.                 sInstance.mScreenWakeLock = null
  43.             } 
  44.         } 
  45.         // 啟動負責關(guān)機順序的線程 
  46.         sInstance.mHandler = new Handler() { 
  47.         }; 
  48.         sInstance.start(); 
  49.     } 

運行函數(shù),啟動實際的關(guān)機流程

  1. public void run() { 
  2.         BroadcastReceiver br = new BroadcastReceiver() { 
  3.             @Override public void onReceive(Context context, Intent intent) { 
  4.                 // We don't allow apps to cancel this, so ignore the result. 
  5.                 actionDone(); 
  6.             } 
  7.         }; 
  8.   
  9.         /* 
  10.          *  寫入一個系統(tǒng)參數(shù),以防Android系統(tǒng)中的System Server 
  11.          * (一個運行于Dalvik虛擬機與真實系統(tǒng)內(nèi)核間的server,負責虛擬機與內(nèi)核的通信)在真實硬件重啟前完成重啟。 
  12.          * 當上述情況發(fā)生時, 則在System Server完成啟動后重試之前的重啟操作。 
  13.          */ 
  14.         { 
  15.             String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : ""); 
  16.             SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); 
  17.         } 
  18.   
  19.         /* 
  20.          * 寫入一個系統(tǒng)參數(shù)以便重啟后進入安全模式 
  21.          */ 
  22.         if (mRebootSafeMode) { 
  23.             SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1"); 
  24.         } 
  25.   
  26.         Log.i(TAG, "Sending shutdown broadcast..."); 
  27.   
  28.         // 關(guān)閉移動通信 
  29.         mActionDone = false
  30.         Intent intent = new Intent(Intent.ACTION_SHUTDOWN); 
  31.         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 
  32.         mContext.sendOrderedBroadcastAsUser(intent, 
  33.                 UserHandle.ALL, null, br, mHandler, 0nullnull); 
  34.   
  35.         final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; 
  36.         synchronized (mActionDoneSync) { 
  37.             while (!mActionDone) { 
  38.                 long delay = endTime - SystemClock.elapsedRealtime(); 
  39.                 if (delay <= 0) { 
  40.                     Log.w(TAG, "Shutdown broadcast timed out"); 
  41.                     break
  42.                 } 
  43.                 try { 
  44.                     mActionDoneSync.wait(delay); 
  45.                 } catch (InterruptedException e) { 
  46.                 } 
  47.             } 
  48.         } 
  49.   
  50.         Log.i(TAG, "Shutting down activity manager..."); 
  51.   
  52.         final IActivityManager am = 
  53.             ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); 
  54.         if (am != null) { 
  55.             try { 
  56.                 am.shutdown(MAX_BROADCAST_TIME); 
  57.             } catch (RemoteException e) { 
  58.             } 
  59.         } 
  60.   
  61.         // 關(guān)閉移動通信 
  62.         shutdownRadios(MAX_RADIO_WAIT_TIME); 
  63.   
  64.         // 安全移除外部存儲卡 
  65.         IMountShutdownObserver observer = new IMountShutdownObserver.Stub() { 
  66.             public void onShutDownComplete(int statusCode) throws RemoteException { 
  67.                 Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown"); 
  68.                 actionDone(); 
  69.             } 
  70.         }; 
  71.   
  72.         Log.i(TAG, "Shutting down MountService"); 
  73.   
  74.         // 初始化變量,并設(shè)置關(guān)機超時時限 
  75.         mActionDone = false
  76.         final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME; 
  77.         synchronized (mActionDoneSync) { 
  78.             try { 
  79.                 final IMountService mount = IMountService.Stub.asInterface( 
  80.                         ServiceManager.checkService("mount")); 
  81.                 if (mount != null) { 
  82.                     mount.shutdown(observer); 
  83.                 } else { 
  84.                     Log.w(TAG, "MountService unavailable for shutdown"); 
  85.                 } 
  86.             } catch (Exception e) { 
  87.                 Log.e(TAG, "Exception during MountService shutdown", e); 
  88.             } 
  89.             while (!mActionDone) { 
  90.                 long delay = endShutTime - SystemClock.elapsedRealtime(); 
  91.                 if (delay <= 0) { 
  92.                     Log.w(TAG, "Shutdown wait timed out"); 
  93.                     break
  94.                 } 
  95.                 try { 
  96.                     mActionDoneSync.wait(delay); 
  97.                 } catch (InterruptedException e) { 
  98.                 } 
  99.             } 
  100.         } 
  101.   
  102.         rebootOrShutdown(mReboot, mRebootReason); 
  103.     } 

第七步: 當rebootOrShutdown方法被調(diào)用時,系統(tǒng)控制權(quán)首先轉(zhuǎn)至底層函數(shù) nativeShutdown(在com_android_server_power_PowerManagerService。cpp中定義) 并最終調(diào)用android_reboot函數(shù)(定義于android_reboot.c中)來完成整個關(guān)機順序

  1. static void nativeShutdown(JNIEnv *env, jclass clazz) { 
  2.     android_reboot(ANDROID_RB_POWEROFF, 00); 

原文鏈接: javacodegeeks 翻譯: ImportNew.com - 靳禹
譯文鏈接: http://www.importnew.com/6356.html

責任編輯:閆佳明 來源: importnew
相關(guān)推薦

2014-06-23 10:31:09

Android啟動過程

2013-03-26 13:55:45

Android Bro

2016-05-18 17:15:17

互動出版網(wǎng)

2014-12-10 10:37:45

Android自定義布局

2010-09-17 15:44:21

網(wǎng)絡(luò)協(xié)議

2010-10-09 11:20:13

2016-10-31 19:41:29

Java垃圾回收

2009-09-02 14:00:34

C#文件處理

2011-08-03 09:18:39

RIP路由協(xié)議RIP

2009-03-16 15:47:16

Java線程多線程

2023-12-12 07:16:34

HTML標簽開發(fā)

2013-04-01 10:12:39

2011-12-01 14:56:30

Java字節(jié)碼

2010-09-25 12:54:24

JVM內(nèi)存

2011-04-07 10:23:00

路由

2011-06-07 13:58:38

光纖通信光纖

2011-04-07 10:34:12

路由

2011-02-15 11:46:41

2011-07-14 13:09:13

終端服務(wù)入侵檢測陷阱技術(shù)

2024-12-18 21:37:24

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲一区二区三区在线播放 | 中文字幕免费视频 | www国产精| 麻豆一区一区三区四区 | 日本精品一区二区三区在线观看视频 | 久久99视频 | 成人在线视频网址 | 四虎影视免费在线 | 成人在线播放网址 | 精品国产乱码久久久久久牛牛 | 久久国产精品一区二区三区 | 精品久久久久久久久久 | 日本亚洲欧美 | 国产亚洲人成a在线v网站 | av资源网站 | 亚洲在线 | 婷婷综合| 久久久久久高潮国产精品视 | 91精品国产91综合久久蜜臀 | 欧美阿v | sese视频在线观看 | 黄色成人免费看 | 中文字幕av一区 | 91精品久久久久久久久 | 97久久国产| 欧美精品1区2区3区 免费黄篇 | 国产高清一区二区三区 | 欧美做暖暖视频 | 日本国产一区二区 | 免费一级欧美在线观看视频 | 久久久91| 久久久久国产精品一区二区 | 亚洲大片 | 国产婷婷色一区二区三区 | 99在线视频观看 | 久久精品久久综合 | 国产日产精品一区二区三区四区 | 一区二区三区精品在线 | 亚洲一区二区视频在线播放 | 日日天天 | 99视频网 |