blob: c9c1d005a85a59e4204498e156948862570ffeb6 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package com.android.server.am;
18
Adrian Roosad028c12016-05-17 14:30:42 -070019import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.Context;
Adrian Roosad028c12016-05-17 14:30:42 -070021import android.content.Intent;
22import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.res.Resources;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070024import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.Handler;
26import android.os.Message;
Adrian Roosad028c12016-05-17 14:30:42 -070027import android.provider.Settings;
Adrian Roos890f1f32016-03-03 16:23:30 -080028import android.text.BidiFormatter;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070029import android.view.LayoutInflater;
30import android.view.View;
Dianne Hackborn38cc8962011-10-13 11:33:55 -070031import android.view.WindowManager;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070032import android.widget.FrameLayout;
33import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
Adrian Roos20d7df32016-01-12 18:59:43 +010035import static com.android.server.am.ActivityManagerService.IS_USER_BUILD;
36
37final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListener {
Adrian Roos90462222016-02-17 15:45:09 -080038
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -070039 private final ActivityManagerService mService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040 private final AppErrorResult mResult;
41 private final ProcessRecord mProc;
Adrian Roos20d7df32016-01-12 18:59:43 +010042 private final boolean mRepeating;
Adrian Roos805ea302016-07-27 12:25:54 -070043 private final boolean mIsRestartable;
Adrian Roos20d7df32016-01-12 18:59:43 +010044
Filip Gruszczynskia925f182015-07-28 09:36:51 -070045 private CharSequence mName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
Adrian Roos90462222016-02-17 15:45:09 -080047 static int CANT_SHOW = -1;
48 static int BACKGROUND_USER = -2;
49 static int ALREADY_SHOWING = -3;
50
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 // Event 'what' codes
Adrian Roos20d7df32016-01-12 18:59:43 +010052 static final int FORCE_QUIT = 1;
53 static final int FORCE_QUIT_AND_REPORT = 2;
54 static final int RESTART = 3;
Adrian Roos20d7df32016-01-12 18:59:43 +010055 static final int MUTE = 5;
Adrian Roos90462222016-02-17 15:45:09 -080056 static final int TIMEOUT = 6;
Adrian Roosad028c12016-05-17 14:30:42 -070057 static final int CANCEL = 7;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 // 5-minute timeout, then we automatically dismiss the crash dialog
60 static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070061
Adrian Roos20d7df32016-01-12 18:59:43 +010062 public AppErrorDialog(Context context, ActivityManagerService service, Data data) {
63 super(context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 Resources res = context.getResources();
Filip Gruszczynskia925f182015-07-28 09:36:51 -070065
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -070066 mService = service;
Adrian Roos20d7df32016-01-12 18:59:43 +010067 mProc = data.proc;
68 mResult = data.result;
69 mRepeating = data.repeating;
Adrian Roos805ea302016-07-27 12:25:54 -070070 mIsRestartable = data.task != null || data.isRestartableForService;
Adrian Roos890f1f32016-03-03 16:23:30 -080071 BidiFormatter bidi = BidiFormatter.getInstance();
72
Adrian Roos20d7df32016-01-12 18:59:43 +010073 if ((mProc.pkgList.size() == 1) &&
74 (mName = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
75 setTitle(res.getString(
76 mRepeating ? com.android.internal.R.string.aerr_application_repeated
77 : com.android.internal.R.string.aerr_application,
Adrian Roos890f1f32016-03-03 16:23:30 -080078 bidi.unicodeWrap(mName.toString()),
79 bidi.unicodeWrap(mProc.info.processName)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 } else {
Adrian Roos20d7df32016-01-12 18:59:43 +010081 mName = mProc.processName;
82 setTitle(res.getString(
83 mRepeating ? com.android.internal.R.string.aerr_process_repeated
84 : com.android.internal.R.string.aerr_process,
Adrian Roos890f1f32016-03-03 16:23:30 -080085 bidi.unicodeWrap(mName.toString())));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 }
87
Adrian Roosad028c12016-05-17 14:30:42 -070088 setCancelable(true);
89 setCancelMessage(mHandler.obtainMessage(CANCEL));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070091 WindowManager.LayoutParams attrs = getWindow().getAttributes();
Adrian Roos20d7df32016-01-12 18:59:43 +010092 attrs.setTitle("Application Error: " + mProc.info.processName);
Adam Lesinski95c42972013-10-02 10:13:27 -070093 attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
94 | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070095 getWindow().setAttributes(attrs);
Adrian Roos20d7df32016-01-12 18:59:43 +010096 if (mProc.persistent) {
Dianne Hackborn38cc8962011-10-13 11:33:55 -070097 getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
98 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099
100 // After the timeout, pretend the user clicked the quit button
101 mHandler.sendMessageDelayed(
Adrian Roos90462222016-02-17 15:45:09 -0800102 mHandler.obtainMessage(TIMEOUT),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 DISMISS_TIMEOUT);
104 }
Dan Egnorb7f03672009-12-09 16:22:32 -0800105
Filip Gruszczynskia925f182015-07-28 09:36:51 -0700106 @Override
107 protected void onCreate(Bundle savedInstanceState) {
108 super.onCreate(savedInstanceState);
Alan Viverette51efddb2017-04-05 10:00:01 -0400109 final FrameLayout frame = findViewById(android.R.id.custom);
Adrian Roos20d7df32016-01-12 18:59:43 +0100110 final Context context = getContext();
111 LayoutInflater.from(context).inflate(
112 com.android.internal.R.layout.app_error_dialog, frame, true);
113
Adrian Roos805ea302016-07-27 12:25:54 -0700114 boolean hasRestart = !mRepeating && mIsRestartable;
Adrian Roosad028c12016-05-17 14:30:42 -0700115 final boolean hasReceiver = mProc.errorReportReceiver != null;
116
Alan Viverette51efddb2017-04-05 10:00:01 -0400117 final TextView restart = findViewById(com.android.internal.R.id.aerr_restart);
Adrian Roos20d7df32016-01-12 18:59:43 +0100118 restart.setOnClickListener(this);
Adrian Roosad028c12016-05-17 14:30:42 -0700119 restart.setVisibility(hasRestart ? View.VISIBLE : View.GONE);
Alan Viverette51efddb2017-04-05 10:00:01 -0400120 final TextView report = findViewById(com.android.internal.R.id.aerr_report);
Adrian Roos20d7df32016-01-12 18:59:43 +0100121 report.setOnClickListener(this);
Adrian Roos20d7df32016-01-12 18:59:43 +0100122 report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
Alan Viverette51efddb2017-04-05 10:00:01 -0400123 final TextView close = findViewById(com.android.internal.R.id.aerr_close);
Adrian Roosad028c12016-05-17 14:30:42 -0700124 close.setVisibility(!hasRestart ? View.VISIBLE : View.GONE);
Adrian Roos20d7df32016-01-12 18:59:43 +0100125 close.setOnClickListener(this);
Adrian Roosad028c12016-05-17 14:30:42 -0700126
127 boolean showMute = !IS_USER_BUILD && Settings.Global.getInt(context.getContentResolver(),
128 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
Alan Viverette51efddb2017-04-05 10:00:01 -0400129 final TextView mute = findViewById(com.android.internal.R.id.aerr_mute);
Adrian Roos20d7df32016-01-12 18:59:43 +0100130 mute.setOnClickListener(this);
Adrian Roosad028c12016-05-17 14:30:42 -0700131 mute.setVisibility(showMute ? View.VISIBLE : View.GONE);
Adrian Roos20d7df32016-01-12 18:59:43 +0100132
133 findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
Filip Gruszczynskia925f182015-07-28 09:36:51 -0700134 }
135
Adrian Roosad028c12016-05-17 14:30:42 -0700136 @Override
137 public void onStart() {
138 super.onStart();
139 getContext().registerReceiver(mReceiver,
140 new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
141 }
142
143 @Override
144 protected void onStop() {
145 super.onStop();
146 getContext().unregisterReceiver(mReceiver);
147 }
148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 private final Handler mHandler = new Handler() {
150 public void handleMessage(Message msg) {
Adrian Roos0da67d662017-04-17 14:50:22 -0700151 setResult(msg.what);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 dismiss();
153 }
154 };
Wale Ogunwale31dd3a72015-07-07 17:13:13 -0700155
156 @Override
157 public void dismiss() {
158 if (!mResult.mHasResult) {
159 // We are dismissing and the result has not been set...go ahead and set.
Adrian Roos0da67d662017-04-17 14:50:22 -0700160 setResult(FORCE_QUIT);
Wale Ogunwale31dd3a72015-07-07 17:13:13 -0700161 }
162 super.dismiss();
163 }
Adrian Roos20d7df32016-01-12 18:59:43 +0100164
Adrian Roos0da67d662017-04-17 14:50:22 -0700165 private void setResult(int result) {
166 synchronized (mService) {
167 if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
168 mProc.crashDialog = null;
169 }
170 }
171 mResult.set(result);
172
173 // Make sure we don't have time timeout still hanging around.
174 mHandler.removeMessages(TIMEOUT);
175 }
176
Adrian Roos20d7df32016-01-12 18:59:43 +0100177 @Override
178 public void onClick(View v) {
179 switch (v.getId()) {
180 case com.android.internal.R.id.aerr_restart:
181 mHandler.obtainMessage(RESTART).sendToTarget();
182 break;
Adrian Roos20d7df32016-01-12 18:59:43 +0100183 case com.android.internal.R.id.aerr_report:
184 mHandler.obtainMessage(FORCE_QUIT_AND_REPORT).sendToTarget();
185 break;
186 case com.android.internal.R.id.aerr_close:
187 mHandler.obtainMessage(FORCE_QUIT).sendToTarget();
188 break;
189 case com.android.internal.R.id.aerr_mute:
190 mHandler.obtainMessage(MUTE).sendToTarget();
191 break;
192 default:
193 break;
194 }
195 }
196
Adrian Roosad028c12016-05-17 14:30:42 -0700197 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
198 @Override
199 public void onReceive(Context context, Intent intent) {
200 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
201 cancel();
202 }
203 }
204 };
205
Adrian Roos20d7df32016-01-12 18:59:43 +0100206 static class Data {
207 AppErrorResult result;
208 TaskRecord task;
209 boolean repeating;
210 ProcessRecord proc;
Adrian Roos805ea302016-07-27 12:25:54 -0700211 boolean isRestartableForService;
Adrian Roos20d7df32016-01-12 18:59:43 +0100212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213}