1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.am; 18 19 import android.content.Context; 20 import android.content.DialogInterface; 21 import android.content.res.Resources; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.view.WindowManager; 25 26 final class AppErrorDialog extends BaseErrorDialog { 27 private final ActivityManagerService mService; 28 private final AppErrorResult mResult; 29 private final ProcessRecord mProc; 30 31 // Event 'what' codes 32 static final int FORCE_QUIT = 0; 33 static final int FORCE_QUIT_AND_REPORT = 1; 34 35 // 5-minute timeout, then we automatically dismiss the crash dialog 36 static final long DISMISS_TIMEOUT = 1000 * 60 * 5; 37 AppErrorDialog(Context context, ActivityManagerService service, AppErrorResult result, ProcessRecord app)38 public AppErrorDialog(Context context, ActivityManagerService service, 39 AppErrorResult result, ProcessRecord app) { 40 super(context); 41 42 Resources res = context.getResources(); 43 44 mService = service; 45 mProc = app; 46 mResult = result; 47 CharSequence name; 48 if ((app.pkgList.size() == 1) && 49 (name=context.getPackageManager().getApplicationLabel(app.info)) != null) { 50 setMessage(res.getString( 51 com.android.internal.R.string.aerr_application, 52 name.toString(), app.info.processName)); 53 } else { 54 name = app.processName; 55 setMessage(res.getString( 56 com.android.internal.R.string.aerr_process, 57 name.toString())); 58 } 59 60 setCancelable(false); 61 62 setButton(DialogInterface.BUTTON_POSITIVE, 63 res.getText(com.android.internal.R.string.force_close), 64 mHandler.obtainMessage(FORCE_QUIT)); 65 66 if (app.errorReportReceiver != null) { 67 setButton(DialogInterface.BUTTON_NEGATIVE, 68 res.getText(com.android.internal.R.string.report), 69 mHandler.obtainMessage(FORCE_QUIT_AND_REPORT)); 70 } 71 72 setTitle(res.getText(com.android.internal.R.string.aerr_title)); 73 WindowManager.LayoutParams attrs = getWindow().getAttributes(); 74 attrs.setTitle("Application Error: " + app.info.processName); 75 attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR 76 | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 77 getWindow().setAttributes(attrs); 78 if (app.persistent) { 79 getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); 80 } 81 82 // After the timeout, pretend the user clicked the quit button 83 mHandler.sendMessageDelayed( 84 mHandler.obtainMessage(FORCE_QUIT), 85 DISMISS_TIMEOUT); 86 } 87 88 private final Handler mHandler = new Handler() { 89 public void handleMessage(Message msg) { 90 synchronized (mService) { 91 if (mProc != null && mProc.crashDialog == AppErrorDialog.this) { 92 mProc.crashDialog = null; 93 } 94 } 95 mResult.set(msg.what); 96 97 // Make sure we don't have time timeout still hanging around. 98 removeMessages(FORCE_QUIT); 99 100 // If this is a timeout we won't be automatically closed, so go 101 // ahead and explicitly dismiss ourselves just in case. 102 dismiss(); 103 } 104 }; 105 106 @Override dismiss()107 public void dismiss() { 108 if (!mResult.mHasResult) { 109 // We are dismissing and the result has not been set...go ahead and set. 110 mResult.set(FORCE_QUIT); 111 } 112 super.dismiss(); 113 } 114 } 115