前回のエントリのサンプルコードで、LowBatteryの場合と、電源キー押しでのShutdownの場合に、ACTION_SHUTDOWNのBroadcast Intentが投げられることがわかりました。
これを拾って、終了処理をすればよいわけですが、ふと疑問に思います。
「終了処理で、無限ループに陥ったら、どうなるの?」
前回のサンプルコードで、onShutdown()に無限ループのコードを入れたところ・・・端末は正常に?終了しました。
onStop()/onDestroy()にも入れてみましたが、同じ動作です。
なんだか怪しいので、こちらを参考に、Shutdown処理を追ってみました。
ShutdownThread.javaの213行目(Gingerbread 12/23版の場合)で、Broadcast Intentを発行しています。
以下、抜粋。
- Log.i(TAG, "Sending shutdown broadcast...");
- // First send the high-level shut down broadcast.
- mActionDone = false;
- mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), 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 timed out");
- break;
- }
- try {
- mActionDoneSync.wait(delay);
- } catch (InterruptedException e) {
- }
- }
- }
- 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) {
- }
- }
IActivityManagerはリモートインターフェースですが、リモートの先はframeworks/base/services/java/com/android/server/am/ActivityManagerService.javaです。
ActivityManagerService::shutdown()はどのようになっているかというと。
- public boolean shutdown(int timeout) {
- if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires permission "
- + android.Manifest.permission.SHUTDOWN);
- }
- boolean timedout = false;
- synchronized(this) {
- mShuttingDown = true;
- mWindowManager.setEventDispatching(false);
- if (mMainStack.mResumedActivity != null) {
- mMainStack.pauseIfSleepingLocked();
- final long endTime = System.currentTimeMillis() + timeout;
- while (mMainStack.mResumedActivity != null
- || mMainStack.mPausingActivity != null) {
- long delay = endTime - System.currentTimeMillis();
- if (delay <= 0) {
- Slog.w(TAG, "Activity manager shutdown timed out");
- timedout = true;
- break;
- }
- try {
- this.wait();
- } catch (InterruptedException e) {
- }
- }
- }
- }
- mUsageStatsService.shutdown();
- mBatteryStatsService.shutdown();
- return timedout;
- }
あきらめた後は、、、System系のServiceの停止や、ファイルシステムのアンマウントが始まるようなので、終了できなかったアプリは、動作が不安定になって最終的にKillされちゃうだけかなと。
なお、このTimeoutは、ShutdownThread.javaのMAX_BROADCAST_TIMEで指定されている時間で、Android Originalソースだと10秒になっていました。
MAX_BROADCAST_TIMEの10秒、というのは、単一のアプリからするとかなり長いですが、ほかにShutdown、終了処理をするアプリもいる訳なので、あまり悠長に処理をしてられる余裕もないのかも。
Shutdownで処理をする場合は、間に合わなくなる可能性も考えて、重要なデータから退避するとか、そもそもKillされる前提で設計した方がいいのかな、と思います。
・・・少し考えすぎているような気もしますが、そーいうこともあるのかな、と、頭の片隅に入れておきます。
0 件のコメント:
コメントを投稿