In Depth : Android Shutdown Sequence
来源:互联网 发布:linux桌面环境比较 编辑:程序博客网 时间:2024/05/16 10:21
- What happened when I long press power button ?
- What is shutdown sequence ?
- How is it different from desktop linux shutdown sequence?
- How to change shutdown menu ?
Many questions pop-up in mind when we think about Android shutdown sequence. Before you read about shutdown sequence I suggest you to read about boot sequence article.
Android is linux based open source operating system, x86 (x86 is a series of computer microprocessor instruction set architectures based on the Intel 8086 CPU.) is most likely system where linux kernel is deployed however all Android devices are running on ARM process (ARM (formerly Advanced RISC Machine, which was formerly Acorn RISC Machine)) except Intel’s Xolo device (http://xolo.in/xolo-x900-features). Xolo comes with Atom 1.6 GHz x86 processor. Android shutdown sequence is different from desktop linux like ubuntu, fedora, etc.
In this article I am going to explain shutdown sequence for Android only. Please refer “Linux Boot and Shutdown Process” for details of desktop linux shutdown process.
Following diagram illustrate shutdown sequence in detail.
Step 1: Long Press Power Button for 500ms.
Step 2: PhoneWindowManager.java identify Power Button long press and call method named “interceptKeyBeforeQueueing”.
Following code display power key snippet from the function.
01
/** {@inheritDoc} */
02
@Override
03
public
int
interceptKeyBeforeQueueing(KeyEvent event,
int
policyFlags,
boolean
isScreenOn) {
04
....
05
....
06
....
07
case
KeyEvent.KEYCODE_POWER: {
08
result &= ~ACTION_PASS_TO_USER;
09
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
// Pressing Power while there's a ringing incoming
22
// call should silence the ringer.
23
telephonyService.silenceRinger();
24
}
else
if
((mIncallPowerBehavior
25
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) !=
0
26
&& telephonyService.isOffhook()) {
27
// Otherwise, if "Power button ends call" is enabled,
28
// the Power button will hang up any current active call.
29
hungUp = telephonyService.endCall();
30
}
31
}
catch
(RemoteException ex) {
32
Log.w(TAG,
"ITelephony threw RemoteException"
, ex);
33
}
34
}
35
interceptPowerKeyDown(!isScreenOn || hungUp
36
|| mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
37
}
else
{
38
mPowerKeyTriggered =
false
;
39
cancelPendingScreenshotChordAction();
40
if
(interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
41
result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
42
}
43
mPendingPowerKeyUpCanceled =
false
;
44
}
45
break
;
46
}
47
....
48
....
49
....
50
}
Above code handle multiple options like silence ringtone, take screenshots and power off. It will identify appropriate option based on time duration and other key’s status. It will call “interceptPowerKeyDown” option by eliminate other options.
Following code display interceptPowerKeyDown function. It will wait for 500 millisecond (ViewConfiguration#getGlobalActionKeyTimeout())
then call mPowerLongPress Thread.
1
private
void
interceptPowerKeyDown(
boolean
handled) {
2
mPowerKeyHandled = handled;
3
if
(!handled) {
4
mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
5
}
6
}
Following code represent mPowerLongPress thread
01
private
final
Runnable mPowerLongPress =
new
Runnable() {
02
@Override
03
public
void
run() {
04
// The context isn't read
05
if
(mLongPressOnPowerBehavior <
0
) {
06
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
07
com.android.internal.R.integer.config_longPressOnPowerBehavior);
08
}
09
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
};
Step 3: Controls goes to GlobalActions.java which is responsible to display dialogbox with various options like (Power Off, Airplan mode, Take screenshot and few toggle buttons), This dialog box has different options are per your OEM provider, model and Android OS version. GlobalAction class has method named showdialog() which is responsible to create object of Dialogbox with options.
01
void
showGlobalActionsDialog() {
02
if
(mGlobalActions ==
null
) {
03
mGlobalActions =
new
GlobalActions(mContext, mWindowManagerFuncs);
04
}
05
final
boolean
keyguardShowing = keyguardIsShowingTq();
06
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
07
if
(keyguardShowing) {
08
// since it took two seconds of long press to bring this up,
09
// poke the wake lock so they have some time to see the dialog.
10
mKeyguardMediator.userActivity();
11
}
12
}
Step 4: If user select “Power Off” option from the dialogbox then control again goes back to PhoneWindowManager, It will start shutdown process.
Step 5: Shutdown process initiate from ShutdownThread.java file’s shoutdowninner() function, It wil display confirmation dialog with ok / cancel button, If user select ok option then actual shutdown process starts.
Step 6: beginShutdownSequence() function called when user select OK option from the dialog.
01
private
static
void
beginShutdownSequence(Context context) {
02
synchronized
(sIsStartedGuard) {
03
if
(sIsStarted) {
04
Log.d(TAG,
"Shutdown sequence already running, returning."
);
05
return
;
06
}
07
sIsStarted =
true
;
08
}
09
10
// throw up an indeterminate system dialog to indicate radio is
11
// shutting down.
12
ProgressDialog pd =
new
ProgressDialog(context);
13
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
14
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
15
pd.setIndeterminate(
true
);
16
pd.setCancelable(
false
);
17
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
18
19
pd.show();
20
21
sInstance.mContext = context;
22
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
23
24
// make sure we never fall asleep again
25
sInstance.mCpuWakeLock =
null
;
26
try
{
27
sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
28
PowerManager.PARTIAL_WAKE_LOCK, TAG +
"-cpu"
);
29
sInstance.mCpuWakeLock.setReferenceCounted(
false
);
30
sInstance.mCpuWakeLock.acquire();
31
}
catch
(SecurityException e) {
32
Log.w(TAG,
"No permission to acquire wake lock"
, e);
33
sInstance.mCpuWakeLock =
null
;
34
}
35
36
// also make sure the screen stays on for better user experience
37
sInstance.mScreenWakeLock =
null
;
38
if
(sInstance.mPowerManager.isScreenOn()) {
39
try
{
40
sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
41
PowerManager.FULL_WAKE_LOCK, TAG +
"-screen"
);
42
sInstance.mScreenWakeLock.setReferenceCounted(
false
);
43
sInstance.mScreenWakeLock.acquire();
44
}
catch
(SecurityException e) {
45
Log.w(TAG,
"No permission to acquire wake lock"
, e);
46
sInstance.mScreenWakeLock =
null
;
47
}
48
}
49
50
// start the thread that initiates shutdown
51
sInstance.mHandler =
new
Handler() {
52
};
53
sInstance.start();
54
}
Run method, start actual shutdown process
001
public
void
run() {
002
BroadcastReceiver br =
new
BroadcastReceiver() {
003
@Override
public
void
onReceive(Context context, Intent intent) {
004
// We don't allow apps to cancel this, so ignore the result.
005
actionDone();
006
}
007
};
008
009
/*
010
* Write a system property in case the system_server reboots before we
011
* get to the actual hardware restart. If that happens, we'll retry at
012
* the beginning of the SystemServer startup.
013
*/
014
{
015
String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
016
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
017
}
018
019
/*
020
* If we are rebooting into safe mode, write a system property
021
* indicating so.
022
*/
023
if
(mRebootSafeMode) {
024
SystemProperties.set(REBOOT_SAFEMODE_PROPERTY,
"1"
);
025
}
026
027
Log.i(TAG,
"Sending shutdown broadcast..."
);
028
029
// First send the high-level shut down broadcast.
030
mActionDone =
false
;
031
Intent intent =
new
Intent(Intent.ACTION_SHUTDOWN);
032
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
033
mContext.sendOrderedBroadcastAsUser(intent,
034
UserHandle.ALL,
null
, br, mHandler,
0
,
null
,
null
);
035
036
final
long
endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
037
synchronized
(mActionDoneSync) {
038
while
(!mActionDone) {
039
long
delay = endTime - SystemClock.elapsedRealtime();
040
if
(delay <=
0
) {
041
Log.w(TAG,
"Shutdown broadcast timed out"
);
042
break
;
043
}
044
try
{
045
mActionDoneSync.wait(delay);
046
}
catch
(InterruptedException e) {
047
}
048
}
049
}
050
051
Log.i(TAG,
"Shutting down activity manager..."
);
052
053
final
IActivityManager am =
054
ActivityManagerNative.asInterface(ServiceManager.checkService(
"activity"
));
055
if
(am !=
null
) {
056
try
{
057
am.shutdown(MAX_BROADCAST_TIME);
058
}
catch
(RemoteException e) {
059
}
060
}
061
062
// Shutdown radios.
063
shutdownRadios(MAX_RADIO_WAIT_TIME);
064
065
// Shutdown MountService to ensure media is in a safe state
066
IMountShutdownObserver observer =
new
IMountShutdownObserver.Stub() {
067
public
void
onShutDownComplete(
int
statusCode)
throws
RemoteException {
068
Log.w(TAG,
"Result code "
+ statusCode +
" from MountService.shutdown"
);
069
actionDone();
070
}
071
};
072
073
Log.i(TAG,
"Shutting down MountService"
);
074
075
// Set initial variables and time out time.
076
mActionDone =
false
;
077
final
long
endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
078
synchronized
(mActionDoneSync) {
079
try
{
080
final
IMountService mount = IMountService.Stub.asInterface(
081
ServiceManager.checkService(
"mount"
));
082
if
(mount !=
null
) {
083
mount.shutdown(observer);
084
}
else
{
085
Log.w(TAG,
"MountService unavailable for shutdown"
);
086
}
087
}
catch
(Exception e) {
088
Log.e(TAG,
"Exception during MountService shutdown"
, e);
089
}
090
while
(!mActionDone) {
091
long
delay = endShutTime - SystemClock.elapsedRealtime();
092
if
(delay <=
0
) {
093
Log.w(TAG,
"Shutdown wait timed out"
);
094
break
;
095
}
096
try
{
097
mActionDoneSync.wait(delay);
098
}
catch
(InterruptedException e) {
099
}
100
}
101
}
102
103
rebootOrShutdown(mReboot, mRebootReason);
104
}
Step 7: With rebootOrShutdown() method controls transfer to the native function of com_android_server_power_PowerManagerService.cpp file, and finally control goes to android_reboot.c file which is final step of shutdown sequence.
1
static
void
nativeShutdown(JNIEnv *env, jclass clazz) {
2
android_reboot(ANDROID_RB_POWEROFF,
0
,
0
);
3
}
- In Depth : Android Shutdown Sequence
- Sequence of shopping carts in-depth analysis with R(1)
- Sequence of shopping carts in-depth analysis with R(3)– Sequence of events
- Sequence of shopping carts in-depth analysis with R(2) – Clustering
- Network+ 2005 In Depth
- read 'Database In Depth'
- Containers in depth笔记
- Controller in depth
- [CSharp In Depth]迭代器
- Lightmapping In-Depth[Unity]
- C# in Depth
- C# in Depth
- 《Indy In Depth》中文版
- Startup- and Shutdown sequence of OpenOffice.org
- [SQL] Shutdown is in progress
- ORA-01090: shutdown in progress
- Android 4.2 Shutdown procedure
- Android Security Internals, An In-Depth Guide to Android's Security Architecture 笔记
- C# WinForm开发系列 - DataGrid/DataGridView(转)
- CSS控制文本超出指定宽度后用省略号代替
- 自动编译工具 Visual Build Professional
- web.xml里面添加注释的方法<!-- -->
- 空格验证
- In Depth : Android Shutdown Sequence
- C# WinForm开发系列 - Grid Controls(转)
- 使用 xmanager 4 远程连接 centos6.3
- Oracle 11.2.0.4.0 Patchset released
- 检查点基础
- Loadrunner 中html 模式与URL模式的区别
- 不可或缺的xmlhttp.setRequestHeader()
- USB android 层链接
- mysql-tpcc使用方法