blob: 541226682bac3a8aeb23b8ef51eceeb99f30cf8f [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;
Jeff Sharkey5ab02432017-06-27 11:01:36 -060024import android.os.Build;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070025import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.os.Handler;
27import android.os.Message;
Adrian Roosad028c12016-05-17 14:30:42 -070028import android.provider.Settings;
Adrian Roos890f1f32016-03-03 16:23:30 -080029import android.text.BidiFormatter;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070030import android.view.LayoutInflater;
31import android.view.View;
Dianne Hackborn38cc8962011-10-13 11:33:55 -070032import android.view.WindowManager;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070033import android.widget.FrameLayout;
34import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Adrian Roos20d7df32016-01-12 18:59:43 +010036final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListener {
Adrian Roos90462222016-02-17 15:45:09 -080037
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -070038 private final ActivityManagerService mService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 private final AppErrorResult mResult;
40 private final ProcessRecord mProc;
Adrian Roos20d7df32016-01-12 18:59:43 +010041 private final boolean mRepeating;
Adrian Roos805ea302016-07-27 12:25:54 -070042 private final boolean mIsRestartable;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070043 private CharSequence mName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044
Adrian Roos90462222016-02-17 15:45:09 -080045 static int CANT_SHOW = -1;
46 static int BACKGROUND_USER = -2;
47 static int ALREADY_SHOWING = -3;
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 // Event 'what' codes
Adrian Roos20d7df32016-01-12 18:59:43 +010050 static final int FORCE_QUIT = 1;
51 static final int FORCE_QUIT_AND_REPORT = 2;
52 static final int RESTART = 3;
Adrian Roos20d7df32016-01-12 18:59:43 +010053 static final int MUTE = 5;
Adrian Roos90462222016-02-17 15:45:09 -080054 static final int TIMEOUT = 6;
Adrian Roosad028c12016-05-17 14:30:42 -070055 static final int CANCEL = 7;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
57 // 5-minute timeout, then we automatically dismiss the crash dialog
58 static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
Filip Gruszczynskia925f182015-07-28 09:36:51 -070059
Adrian Roos20d7df32016-01-12 18:59:43 +010060 public AppErrorDialog(Context context, ActivityManagerService service, Data data) {
61 super(context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 Resources res = context.getResources();
Filip Gruszczynskia925f182015-07-28 09:36:51 -070063
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -070064 mService = service;
Adrian Roos20d7df32016-01-12 18:59:43 +010065 mProc = data.proc;
66 mResult = data.result;
67 mRepeating = data.repeating;
Adrian Roos805ea302016-07-27 12:25:54 -070068 mIsRestartable = data.task != null || data.isRestartableForService;
Adrian Roos890f1f32016-03-03 16:23:30 -080069 BidiFormatter bidi = BidiFormatter.getInstance();
70
Adrian Roos20d7df32016-01-12 18:59:43 +010071 if ((mProc.pkgList.size() == 1) &&
72 (mName = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
73 setTitle(res.getString(
74 mRepeating ? com.android.internal.R.string.aerr_application_repeated
75 : com.android.internal.R.string.aerr_application,
Adrian Roos890f1f32016-03-03 16:23:30 -080076 bidi.unicodeWrap(mName.toString()),
77 bidi.unicodeWrap(mProc.info.processName)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 } else {
Adrian Roos20d7df32016-01-12 18:59:43 +010079 mName = mProc.processName;
80 setTitle(res.getString(
81 mRepeating ? com.android.internal.R.string.aerr_process_repeated
82 : com.android.internal.R.string.aerr_process,
Adrian Roos890f1f32016-03-03 16:23:30 -080083 bidi.unicodeWrap(mName.toString())));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 }
85
Adrian Roosad028c12016-05-17 14:30:42 -070086 setCancelable(true);
87 setCancelMessage(mHandler.obtainMessage(CANCEL));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070089 WindowManager.LayoutParams attrs = getWindow().getAttributes();
Adrian Roos20d7df32016-01-12 18:59:43 +010090 attrs.setTitle("Application Error: " + mProc.info.processName);
Adam Lesinski95c42972013-10-02 10:13:27 -070091 attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
92 | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070093 getWindow().setAttributes(attrs);
Adrian Roos20d7df32016-01-12 18:59:43 +010094 if (mProc.persistent) {
Dianne Hackborn38cc8962011-10-13 11:33:55 -070095 getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
96 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
98 // After the timeout, pretend the user clicked the quit button
99 mHandler.sendMessageDelayed(
Adrian Roos90462222016-02-17 15:45:09 -0800100 mHandler.obtainMessage(TIMEOUT),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 DISMISS_TIMEOUT);
102 }
Dan Egnorb7f03672009-12-09 16:22:32 -0800103
Filip Gruszczynskia925f182015-07-28 09:36:51 -0700104 @Override
105 protected void onCreate(Bundle savedInstanceState) {
106 super.onCreate(savedInstanceState);
Alan Viverette51efddb2017-04-05 10:00:01 -0400107 final FrameLayout frame = findViewById(android.R.id.custom);
Adrian Roos20d7df32016-01-12 18:59:43 +0100108 final Context context = getContext();
109 LayoutInflater.from(context).inflate(
110 com.android.internal.R.layout.app_error_dialog, frame, true);
111
Adrian Roosad028c12016-05-17 14:30:42 -0700112 final boolean hasReceiver = mProc.errorReportReceiver != null;
113
Alan Viverette51efddb2017-04-05 10:00:01 -0400114 final TextView restart = findViewById(com.android.internal.R.id.aerr_restart);
Adrian Roos20d7df32016-01-12 18:59:43 +0100115 restart.setOnClickListener(this);
Amith Yamasanib0c8a882017-08-28 09:36:42 -0700116 restart.setVisibility(mIsRestartable ? View.VISIBLE : View.GONE);
Alan Viverette51efddb2017-04-05 10:00:01 -0400117 final TextView report = findViewById(com.android.internal.R.id.aerr_report);
Adrian Roos20d7df32016-01-12 18:59:43 +0100118 report.setOnClickListener(this);
Adrian Roos20d7df32016-01-12 18:59:43 +0100119 report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
Alan Viverette51efddb2017-04-05 10:00:01 -0400120 final TextView close = findViewById(com.android.internal.R.id.aerr_close);
Amith Yamasanib0c8a882017-08-28 09:36:42 -0700121 close.setVisibility(mRepeating ? View.VISIBLE : View.GONE);
Adrian Roos20d7df32016-01-12 18:59:43 +0100122 close.setOnClickListener(this);
Adrian Roosad028c12016-05-17 14:30:42 -0700123
Jeff Sharkey5ab02432017-06-27 11:01:36 -0600124 boolean showMute = !Build.IS_USER && Settings.Global.getInt(context.getContentResolver(),
Adrian Roosad028c12016-05-17 14:30:42 -0700125 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
Alan Viverette51efddb2017-04-05 10:00:01 -0400126 final TextView mute = findViewById(com.android.internal.R.id.aerr_mute);
Adrian Roos20d7df32016-01-12 18:59:43 +0100127 mute.setOnClickListener(this);
Adrian Roosad028c12016-05-17 14:30:42 -0700128 mute.setVisibility(showMute ? View.VISIBLE : View.GONE);
Adrian Roos20d7df32016-01-12 18:59:43 +0100129
130 findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
Filip Gruszczynskia925f182015-07-28 09:36:51 -0700131 }
132
Adrian Roosad028c12016-05-17 14:30:42 -0700133 @Override
134 public void onStart() {
135 super.onStart();
136 getContext().registerReceiver(mReceiver,
137 new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
138 }
139
140 @Override
141 protected void onStop() {
142 super.onStop();
143 getContext().unregisterReceiver(mReceiver);
144 }
145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 private final Handler mHandler = new Handler() {
147 public void handleMessage(Message msg) {
Adrian Roos0da67d662017-04-17 14:50:22 -0700148 setResult(msg.what);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 dismiss();
150 }
151 };
Wale Ogunwale31dd3a72015-07-07 17:13:13 -0700152
153 @Override
154 public void dismiss() {
155 if (!mResult.mHasResult) {
156 // We are dismissing and the result has not been set...go ahead and set.
Adrian Roos0da67d662017-04-17 14:50:22 -0700157 setResult(FORCE_QUIT);
Wale Ogunwale31dd3a72015-07-07 17:13:13 -0700158 }
159 super.dismiss();
160 }
Adrian Roos20d7df32016-01-12 18:59:43 +0100161
Adrian Roos0da67d662017-04-17 14:50:22 -0700162 private void setResult(int result) {
163 synchronized (mService) {
164 if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
165 mProc.crashDialog = null;
166 }
167 }
168 mResult.set(result);
169
170 // Make sure we don't have time timeout still hanging around.
171 mHandler.removeMessages(TIMEOUT);
172 }
173
Adrian Roos20d7df32016-01-12 18:59:43 +0100174 @Override
175 public void onClick(View v) {
176 switch (v.getId()) {
177 case com.android.internal.R.id.aerr_restart:
178 mHandler.obtainMessage(RESTART).sendToTarget();
179 break;
Adrian Roos20d7df32016-01-12 18:59:43 +0100180 case com.android.internal.R.id.aerr_report:
181 mHandler.obtainMessage(FORCE_QUIT_AND_REPORT).sendToTarget();
182 break;
183 case com.android.internal.R.id.aerr_close:
184 mHandler.obtainMessage(FORCE_QUIT).sendToTarget();
185 break;
186 case com.android.internal.R.id.aerr_mute:
187 mHandler.obtainMessage(MUTE).sendToTarget();
188 break;
189 default:
190 break;
191 }
192 }
193
Adrian Roosad028c12016-05-17 14:30:42 -0700194 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
195 @Override
196 public void onReceive(Context context, Intent intent) {
197 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
198 cancel();
199 }
200 }
201 };
202
Adrian Roos20d7df32016-01-12 18:59:43 +0100203 static class Data {
204 AppErrorResult result;
205 TaskRecord task;
206 boolean repeating;
207 ProcessRecord proc;
Adrian Roos805ea302016-07-27 12:25:54 -0700208 boolean isRestartableForService;
Adrian Roos20d7df32016-01-12 18:59:43 +0100209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210}