Google原生的Android系统1般是没有“重启”这个选项的。有时候重启也是不可或缺的1个Feature,那末如何在源码环境下添加这个选项呢?
1. 在frameworksasecore
es
esvaluesstrings.xml
中添加标签:
<span style="font-size:14px;"><!--zms add start-->
<!-- label for item that power reboot in phone options dialog -->
<string name="zzzzz_global_action_power_reboot">Reboot</string>
<!--zms add end--></span>
固然这只是英语语系的,需要添加其它语系的标示,把"Reboot" 替换成其它语言。
2. 在alpsframeworksasecore
es
esdrawable-hdpi 中添加图标:
zzzzz_ic_lock_power_reboot.png
3. 打开frameworkspoliciesasephonecomandroidinternalpolicyimplGlobalActions.java
大概在这个文件的261行有这样的代码:
mItems = Lists.newArrayList(
// silent mode
mSilentModeToggle,
// next: airplane mode
mAirplaneModeOn,
// last: power off
在这里,我们添加power reboot 的新的item.
具体这个mItems 更新为以下:
mItems = Lists.newArrayList(
// silent mode
mSilentModeToggle,
// next: airplane mode
mAirplaneModeOn,
// last: power off
new SinglePressAction(
com.android.internal.R.drawable.ic_lock_power_off,
R.string.global_action_power_off) {
public void onPress() {
// shutdown by making sure radio and power are handled
accordingly.
ShutdownThread.shutdown(mContext, true);
}
public boolean showDuringKeyguard() {
return true;
}
public boolean showBeforeProvisioning() {
return true;
}
}//zms add start
,
new SinglePressAction(
com.android.internal.R.drawable.zzzzz_ic_lock_power_reboot,
R.string.zzzzz_global_action_power_reboot) {
public void onPress() {
// reboot by making sure radio and power are handled
accordingly.
ShutdownThread.reboot(mContext, null, true);
}
public boolean showDuringKeyguard() {
return true;
}
public boolean showBeforeProvisioning() {
return true;
}
}
//zms add end.
);
经过这样的添加/修改后,这项feature 便可运行。
注意如果测试的话,由于有修改framework 中的文件,最好new 1下全部工程。
另外还需要修改1下ShutdownThread.java 中的那个dialog 显示描写,不然将照旧看到“关机”的信息。
位置:frameworks/base/services/java/com/android/server/power/ShutdownThread.java
不同版本的代码位置可能有所差别,可以在根目录下find1下:
find -name ShutdownThread.java
参照以下文件便可:
package com.android.server.power;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.IActivityManager;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothManager;
import android.nfc.NfcAdapter;
import android.nfc.INfcAdapter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Vibrator;
import android.os.SystemVibrator;
import android.os.storage.IMountService;
import android.os.storage.IMountShutdownObserver;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.view.Surface;
import android.net.ConnectivityManager;
import com.android.internal.telephony.ITelephony;
import com.android.server.power.PowerManagerService;
import android.util.Log;
import android.view.WindowManager;
import android.view.IWindowManager;
// Wakelock
import android.os.PowerManager.WakeLock;
// For IPO
import com.android.internal.app.ShutdownManager;
import com.mediatek.common.featureoption.FeatureOption;
import android.provider.Settings;
import com.mediatek.common.bootanim.IBootAnimExt;
import com.mediatek.common.MediatekClassFactory;
import com.mediatek.common.hdmi.IHDMINative; // add for HDMI power control
import dalvik.system.Zygote;
public final class ShutdownThread extends Thread {
// constants
private static final String TAG = "ShutdownThread";
private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
// maximum time we wait for the shutdown broadcast before going on.
private static final int MAX_BROADCAST_TIME = 10*1000;
private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
private static final int MAX_RADIO_WAIT_TIME = 12*1000;
// length of vibration before shutting down
private static final int SHUTDOWN_VIBRATE_MS = 500;
// state tracking
private static Object sIsStartedGuard = new Object();
private static boolean sIsStarted = false;
private static boolean mReboot;
private static boolean mRebootSafeMode;
private static String mRebootReason;
// Provides shutdown assurance in case the system_server is killed
public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
// Indicates whether we are rebooting into safe mode
public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
// static instance of this thread
private static final ShutdownThread sInstance = new ShutdownThread();
private final Object mActionDoneSync = new Object();
private boolean mActionDone;
private Context mContext;
private PowerManager mPowerManager;
private PowerManager.WakeLock mCpuWakeLock;
private PowerManager.WakeLock mScreenWakeLock;
private Handler mHandler;
private static AlertDialog sConfirmDialog = null;
// IPO
private static ProgressDialog pd = null;
private static Object mShutdownThreadSync = new Object();
private ShutdownManager stMgr = new ShutdownManager();
// Shutdown Flow Settings
private static final int NORMAL_SHUTDOWN_FLOW = 0x0;
private static final int IPO_SHUTDOWN_FLOW = 0x1;
private static int mShutdownFlow;
// Shutdown Animation
private static final int MIN_SHUTDOWN_ANIMATION_PLAY_TIME = 5*1000; // CU/CMCC operator require 3⑸s
private static long beginAnimationTime = 0;
private static long endAnimationTime = 0;
private static boolean bConfirmForAnimation = true;
private static boolean bPlayaudio = true;
private static final Object mEnableAnimatingSync = new Object();
private static boolean mEnableAnimating = true;
// length of waiting for memory dump if Modem Exception occurred
private static final int MAX_MEMORY_DUMP_TIME = 60 * 1000;
private static String command; //for bypass radioOff
private static int screen_turn_off_time = 5 * 1000; //after 5sec the screen become OFF, you can change the time delay
private static IHDMINative ImHDMI = null; // for MFR
private static final boolean mSpew = true; //debug enable
private static IBootAnimExt mIBootAnim = null; // for boot animation
private ShutdownThread() {
}
public static boolean isPowerOffDialogShowing() {
return (sConfirmDialog != null && sConfirmDialog.isShowing());
}
public static void EnableAnimating(boolean enable) {
synchronized (mEnableAnimatingSync) {
mEnableAnimating = enable;
}
}
/**
* 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;
Log.d(TAG, "!!! Request to shutdown !!!");
ShutdownManager.startFtraceCapture();
if (mSpew) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack)
{
Log.d(TAG, " |----" + element.toString());
}
}
createPreShutdownApi(context);
if (SystemProperties.getBoolean("ro.monkey", false)) {
Log.d(TAG, "Cannot request to shutdown when Monkey is running, returning.");
return;
}
shutdownInner(context, confirm);
}
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;
}
}
Log.d(TAG, "Notifying thread to start radio shutdown");
bConfirmForAnimation = confirm;
final int longPressBehavior = context.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
final int resourceId = (mReboot && !mRebootSafeMode)
? com.android.internal.R.string.reboot_confirm
: (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));
Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
if (confirm) {
final CloseDialogReceiver closer = new CloseDialogReceiver(context);
if (sConfirmDialog != null) {
sConfirmDialog.dismiss();
}
if (sConfirmDialog == null) {
Log.d(TAG, "PowerOff dialog doesn't exist. Create it first");
sConfirmDialog = new AlertDialog.Builder(context)
.setTitle((mReboot && !mRebootSafeMode)
? com.android.internal.R.string.reboot_title
: (mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
: com.android.internal.R.string.power_off))
.setMessage(resourceId)
.setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
beginShutdownSequence(context);
if (sConfirmDialog != null) {
sConfirmDialog = null;
}
}
})
.setNegativeButton(com.android.internal.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
synchronized (sIsStartedGuard) {
sIsStarted = false;
}
if (sConfirmDialog != null) {
sConfirmDialog = null;
}
}
})
.create();
sConfirmDialog.setCancelable(false);//blocking back key
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
/*if (!context.getResources().getBoolean(
com.android.internal.R.bool.config_sf_slowBlur)) {
sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
}*/
/* To fix video+UI+blur flick issue */
sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
if (!sConfirmDialog.isShowing()) {
sConfirmDialog.show();
}
} else {
beginShutdownSequence(context);
}
}
private static class CloseDialogReceiver extends BroadcastReceiver
implements DialogInterface.OnDismissListener {
private Context mContext;
public Dialog dialog;
CloseDialogReceiver(Context context) {
mContext = context;
IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(this, filter);
}
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "CloseDialogReceiver: onReceive");
dialog.cancel();
}
public void onDismiss(DialogInterface unused) {
mContext.unregisterReceiver(this);
}
}
private static Runnable mDelayDim = new Runnable() { //use for animation, add by how.wang
public void run() {
Log.d(TAG, "setBacklightBrightness: Off");
if (sInstance.mScreenWakeLock != null && sInstance.mScreenWakeLock.isHeld()) {
sInstance.mScreenWakeLock.release();
sInstance.mScreenWakeLock = null;
}
sInstance.mPowerManager.setBacklightBrightnessOff(true);
}
};
/**
* 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 reason code to pass to the kernel (e.g. "recovery"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootReason = reason;
Log.d(TAG, "reboot");
if (mSpew) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack)
{
Log.d(TAG, " |----" + element.toString());
}
}
shutdownInner(context, confirm);
}
/**
* Request a reboot into safe mode. 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 rebootSafeMode(final Context context, boolean confirm) {
mReboot = true;
mRebootSafeMode = true;
mRebootReason = null;
Log.d(TAG, "rebootSafeMode");
shutdownInner(context, confirm);
}
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, "Shutdown sequence already running, returning.");
return;
}
sIsStarted = true;
}
// start the thread that initiates shutdown
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
sInstance.mHandler = new Handler() {
};
bPlayaudio = true;
if (!bConfirmForAnimation) {
if (!sInstance.mPowerManager.isScreenOn()) {
bPlayaudio = false;
}
}
// throw up an indeterminate system dialog to indicate radio is
// shutting down.
beginAnimationTime = 0;
boolean mShutOffAnimation = false;
try {
if (mIBootAnim == null) {
mIBootAnim = MediatekClassFactory.createInstance(IBootAnimExt.class);
}
} catch (Exception e) {
e.printStackTrace();
}
int screenTurnOffTime = mIBootAnim.getScreenTurnOffTime();
mShutOffAnimation = mIBootAnim.isCustBootAnim();
Log.e(TAG, "mIBootAnim get screenTurnOffTime : " + screenTurnOffTime);
String cust = SystemProperties.get("ro.operator.optr");
if (cust != null) {
if (cust.equals("CUST")) {
mShutOffAnimation = true;
}
}
synchronized (mEnableAnimatingSync) {
if(!mEnableAnimating) {
//sInstance.mPowerManager.setBacklightBrightness(PowerManager.BRIGHTNESS_DIM);
} else {
if (mShutOffAnimation) {
Log.e(TAG, "mIBootAnim.isCustBootAnim() is true");
bootanimCust();
} else {
pd = new ProgressDialog(context);
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
/* To fix video+UI+blur flick issue */
pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
pd.show();
}
sInstance.mHandler.postDelayed(mDelayDim, screenTurnOffTime);
}
}
// 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);
sInstance.mCpuWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mCpuWakeLock = null;
}
Log.d(TAG, "shutdown acquire partial WakeLock: cpu");
// 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
if (sInstance.getState() != Thread.State.NEW || sInstance.isAlive()) {
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
Log.d(TAG, "ShutdownThread exists already");
checkShutdownFlow();
synchronized (mShutdownThreadSync) {
mShutdownThreadSync.notify();
}
} else {
Log.e(TAG, "Thread state is not normal! froce to shutdown!");
delayForPlayAnimation();
//unmout data/cache partitions while performing shutdown
//Power.shutdown();
SystemProperties.set("ctl.start", "shutdown");
}
} else {
sInstance.start();
}
}
private static void bootanimCust() {
// [MTK] fix shutdown animation timing issue
//==================================================================
SystemProperties.set("service.shutanim.running","0");
Log.i(TAG, "set service.shutanim.running to 0");
//==================================================================
boolean isRotaionEnabled = false;
try {
isRotaionEnabled = Settings.System.getInt(sInstance.mContext.getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 1) != 0;
if (isRotaionEnabled) {
final IWindowManager wm = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
wm.freezeRotation(Surface.ROTATION_0);
Settings.System.putInt(sInstance.mContext.getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0);
Settings.System.putInt(sInstance.mContext.getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION_RESTORE, 1);
}
} catch (NullPointerException ex) {
Log.e(TAG, "check Rotation: sInstance.mContext object is null when get Rotation");
} catch (RemoteException e) {
}
beginAnimationTime = SystemClock.elapsedRealtime() + MIN_SHUTDOWN_ANIMATION_PLAY_TIME;
// +MediaTek 2012-02⑵5 Disable key dispatch
try {
final IWindowManager wm = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
wm.setEventDispatching(false);
} catch (RemoteException e) {}
// -MediaTek 2012-02⑵5 Disable key dispatch
startBootAnimation();
}
private static void startBootAnimation() {
try {
SystemProperties.set("service.bootanim.exit","0");
Log.d(TAG, "Set 'service.bootanim.exit' = 0).");
} catch (Exception ex) {
Log.e(TAG, "Failed to set 'service.bootanim.exit' = 0).");
}
if (bPlayaudio) {
SystemProperties.set("ctl.start","bootanim:shut mp3");
Log.d(TAG, "bootanim:shut mp3" );
} else {
SystemProperties.set("ctl.start","bootanim:shut nomp3");
Log.d(TAG, "bootanim:shut nomp3" );
}
}
void actionDone() {
synchronized (mActionDoneSync) {
mActionDone = true;
mActionDoneSync.notifyAll();
}
}
private static void delayForPlayAnimation() {
if (beginAnimationTime <= 0) {
return;
}
endAnimationTime = beginAnimationTime - SystemClock.elapsedRealtime();
if (endAnimationTime > 0) {
try {
Thread.currentThread().sleep(endAnimationTime);
} catch ( Exception e) {
Log.e(TAG, "Shutdown stop bootanimation Thread.currentThread().sleep exception!");
}
}
}
/*
* Please make sure that context object is already instantiated already before calling this method.
* However, we'll still catch null pointer exception here in case.
*/
private static void checkShutdownFlow() {
Log.d(TAG, "checkShutdownFlow: IPO_Support=" + FeatureOption.MTK_IPO_SUPPORT + " mReboot=" + mReboot);
if (FeatureOption.MTK_IPO_SUPPORT == false || mReboot == true || Zygote.systemInSafeMode == true) {
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
return;
}
boolean isIPOEnabled;
try {
isIPOEnabled = Settings.System.getInt(sInstance.mContext.getContentResolver(),
Settings.System.IPO_SETTING, 1) == 1;
} catch (NullPointerException ex) {
Log.e(TAG, "checkShutdownFlow: sInstance.mContext object is null when get IPO enable/disable Option");
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
return;
}
if (isIPOEnabled == true) {
if ("1".equals(SystemProperties.get("sys.ipo.battlow")))
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
else
mShutdownFlow = IPO_SHUTDOWN_FLOW;
} else {
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
}
// power off auto test, don't modify
Log.d(TAG, "checkShutdownFlow: isIPOEnabled=" + isIPOEnabled + " mShutdownFlow=" + mShutdownFlow);
return;
}
/**
* Makes sure we handle the shutdown gracefully.
* Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
*/
public void run() {
checkShutdownFlow();
while (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
stMgr.saveStates(mContext);
stMgr.enterShutdown(mContext);
running();
}
if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {
stMgr.enterShutdown(mContext);
running();
}
}
public void running() {
if(sPreShutdownApi != null){
try {
sPreShutdownApi.onPowerOff();
} catch (RemoteException e) {
Log.e(TAG, "onPowerOff exception" + e.getMessage());
}
}else{
Log.w(TAG, "sPreShutdownApi is null");
}
command = SystemProperties.get("sys.ipo.pwrdncap");
BroadcastReceiver br = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
// We don't allow apps to cancel this, so ignore the result.
actionDone();
}
};
/*
* Write a system property in case the system_server reboots before we
* get to the actual hardware restart. If that happens, we'll retry at
* the beginning of the SystemServer startup.
*/
{
String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
}
/*
* If we are rebooting into safe mode, write a system property
* indicating so.
*/
if (mRebootSafeMode) {
SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
}
Log.i(TAG, "Sending shutdown broadcast...");
// First send the high-level shut down broadcast.
mActionDone = false;
/// M: 2012-05⑵0 ALPS00286063 @{
mContext.sendBroadcast(new Intent("android.intent.action.ACTION_PRE_SHUTDOWN"));
/// @} 2012-05⑵0
mContext.sendOrderedBroadcastAsUser((new Intent()).setAction(Intent.ACTION_SHUTDOWN).putExtra("_mode", mShutdownFlow),
UserHandle.ALL, null, br, mHandler, 0, null, null);
final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
synchronized (mActionDoneSync) {
while (!mActionDone) {
long delay = endTime - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, "Shutdown broadcast ACTION_SHUTDOWN timed out");
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
Log.d(TAG, "change shutdown flow from ipo to normal: ACTION_SHUTDOWN timeout");
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
}
break;
}
try {
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
}
}
}
// Also send ACTION_SHUTDOWN_IPO in IPO shut down flow
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
mActionDone = false;
mContext.sendOrderedBroadcast(new Intent("android.intent.action.ACTION_SHUTDOWN_IPO"), null,
br, mHandler, 0, null, null);
final long endTimeIPO = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
synchronized (mActionDoneSync) {
while (!mActionDone) {
long delay = endTimeIPO - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, "Shutdown broadcast ACTION_SHUTDOWN_IPO timed out");
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
Log.d(TAG, "change shutdown flow from ipo to normal: ACTION_SHUTDOWN_IPO timeout");
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
}
break;
}
try {
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
}
}
}
}
if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {
// power off auto test, don't modify
Log.i(TAG, "Shutting down activity manager...");
final IActivityManager am =
ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
if (am != null) {
try {
am.shutdown(MAX_BROADCAST_TIME);
} catch (RemoteException e) {
}
}
}
// power off auto test, don't modify
// Shutdown radios.
Log.i(TAG, "Shutting down radios...");
shutdownRadios(MAX_RADIO_WAIT_TIME);
// power off auto test, don't modify
Log.i(TAG, "Shutting down MountService...");
if ( (mShutdownFlow == IPO_SHUTDOWN_FLOW) && (command.equals("1")||command.equals("3")) ) {
Log.i(TAG, "bypass MountService!");
} else {
// Shutdown MountService to ensure media is in a safe state
IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
public void onShutDownComplete(int statusCode) throws RemoteException {
Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
if (statusCode < 0) {
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
}
actionDone();
}
};
// Set initial variables and time out time.
mActionDone = false;
final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
synchronized (mActionDoneSync) {
try {
final IMountService mount = IMountService.Stub.asInterface(
ServiceManager.checkService("mount"));
if (mount != null) {
mount.shutdown(observer);
} else {
Log.w(TAG, "MountService unavailable for shutdown");
}
} catch (Exception e) {
Log.e(TAG, "Exception during MountService shutdown", e);
}
while (!mActionDone) {
long delay = endShutTime - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, "Shutdown wait timed out");
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
Log.d(TAG, "change shutdown flow from ipo to normal: MountService");
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
}
break;
}
try {
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
}
}
}
}
// power off auto test, don't modify
//mountSerivce
Log.i(TAG, "MountService shut done.
------分隔线----------------------------
------分隔线----------------------------