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

深入解析Android關機

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

Android 關機順序

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

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

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

下圖詳細闡釋了Android的關機順序。

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

第二步: 之后,PhoneWindowManager.java 將捕獲長按電源按鈕這一事件并調用“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.                            // 如果在來電響鈴時按下電源鍵,則系統將關閉來電提示 
  22.                             telephonyService.silenceRinger(); 
  23.                        } else if ((mIncallPowerBehavior 
  24.                                 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 
  25.                                && telephonyService.isOffhook()) { 
  26.                             // 如果處在通話中且電源鍵掛斷選項已啟用,則按下電源鍵會結束當前通話 
  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. .... 

上面的代碼包含了對多種情形下對長按電源鍵時間的處理,例如靜默來電響鈴、屏幕截圖以及關閉電源等。 系統將根據電源鍵被按住的時間長短以及相關按鍵的使用情況來決定如何恰當地處理當前的用戶操作。 當電源鍵被按下且沒有截屏操作觸發時interceptPowerKeyDown 將被調用,這時其他的按鍵響應(其他按鍵響應指 interceptKeyBeforeQueueing 中其他cases)將不會被觸發。

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

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

mPowerLongPress 線程的實現如下:

  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 類, 該模塊則負責顯示關機選項的對話框,這些選項在各Android發行版(各OEM廠商定制的Android系統, 不同的手機型號和不同版本的Android系統)中不盡相同,通常包括關閉電源、飛行模式和屏幕截圖。也可能包括其他一些選項按鍵。GlobalActions 類實現了一個showdialog方法,該方法將根據當前系統支持的菜單內容來創建這個對話框。

  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.          // 由于激活關機對話框需要長按電源鍵兩秒以上,所以當對話框顯示之后,屏幕的喚醒狀態將被鎖定,以方便用戶瀏覽對話框中內容 
  9.         mKeyguardMediator.userActivity(); 
  10.     } 

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

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

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

  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.         // 顯示正在關閉電源的對話框 
  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進入休眠狀態 
  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.         // 電源關閉前一直保持屏幕喚醒狀態,以便提升用戶體驗 
  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.         // 啟動負責關機順序的線程 
  46.         sInstance.mHandler = new Handler() { 
  47.         }; 
  48.         sInstance.start(); 
  49.     } 

運行函數,啟動實際的關機流程

  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.          *  寫入一個系統參數,以防Android系統中的System Server 
  11.          * (一個運行于Dalvik虛擬機與真實系統內核間的server,負責虛擬機與內核的通信)在真實硬件重啟前完成重啟。 
  12.          * 當上述情況發生時, 則在System Server完成啟動后重試之前的重啟操作。 
  13.          */ 
  14.         { 
  15.             String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : ""); 
  16.             SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); 
  17.         } 
  18.   
  19.         /* 
  20.          * 寫入一個系統參數以便重啟后進入安全模式 
  21.          */ 
  22.         if (mRebootSafeMode) { 
  23.             SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1"); 
  24.         } 
  25.   
  26.         Log.i(TAG, "Sending shutdown broadcast..."); 
  27.   
  28.         // 關閉移動通信 
  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.         // 關閉移動通信 
  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.         // 初始化變量,并設置關機超時時限 
  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方法被調用時,系統控制權首先轉至底層函數 nativeShutdown(在com_android_server_power_PowerManagerService。cpp中定義) 并最終調用android_reboot函數(定義于android_reboot.c中)來完成整個關機順序

  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
相關推薦

2014-06-23 10:31:09

Android啟動過程

2013-03-26 13:55:45

Android Bro

2016-05-18 17:15:17

互動出版網

2014-12-10 10:37:45

Android自定義布局

2010-09-17 15:44:21

網絡協議

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路由協議RIP

2009-03-16 15:47:16

Java線程多線程

2023-12-12 07:16:34

HTML標簽開發

2013-04-01 10:12:39

2011-12-01 14:56:30

Java字節碼

2010-09-25 12:54:24

JVM內存

2011-04-07 10:23:00

路由

2011-06-07 13:58:38

光纖通信光纖

2011-04-07 10:34:12

路由

2024-12-18 21:37:24

2011-02-15 11:46:41

2011-07-14 13:09:13

終端服務入侵檢測陷阱技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久精选 | 国产在线观看一区二区三区 | 日韩欧美三级电影 | 毛片视频免费观看 | 五月综合激情网 | 一区二区av| av在线天堂网 | 91p在线观看 | 成人黄色在线 | 一区二区小视频 | 亚洲逼院 | 国产视频福利 | 午夜激情在线视频 | 欧美日韩综合视频 | 中文字幕一区在线观看视频 | 欧美三级三级三级爽爽爽 | 操人视频在线观看 | 亚洲精品中文字幕在线观看 | 91精品一区| 亚洲a毛片| 超碰精品在线 | 亚洲一二三区精品 | 免费精品 | 午夜电影福利 | 国产精品不卡视频 | 日韩免费高清视频 | 精品久久久久久久久久久下田 | 久久视频一区 | 国产黄色网址在线观看 | 午夜精品久久 | 日韩高清中文字幕 | 亚洲激情综合网 | 天天做日日做 | 亚洲性视频网站 | 一级片aaa | 国产成人99久久亚洲综合精品 | 在线观看www | 亚洲日本国产 | av资源中文在线天堂 | 亚洲免费三区 | 日韩电影免费在线观看中文字幕 |