AppErrorDialog.java revision a925f1897f9e8fa0db7cf8b72b53d7c56dc3921c
123c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis/*
223c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * Copyright (C) 2006 The Android Open Source Project
323c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis *
423c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
523c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * you may not use this file except in compliance with the License.
623c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * You may obtain a copy of the License at
723c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis *
823c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
923c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis *
1023c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * Unless required by applicable law or agreed to in writing, software
1123c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
1223c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * See the License for the specific language governing permissions and
1423c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis * limitations under the License.
1523c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis */
1623c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis
17718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wupackage com.android.server.am;
18718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
19718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wuimport android.content.Context;
20718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wuimport android.content.DialogInterface;
21718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wuimport android.content.res.Resources;
2223c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennisimport android.os.Bundle;
2323c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennisimport android.os.Handler;
245a16a62950de06d48769e29f0c68a154ed7a7a89Michael Lentineimport android.os.Message;
255a16a62950de06d48769e29f0c68a154ed7a7a89Michael Lentineimport android.view.LayoutInflater;
2690ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopianimport android.view.View;
274cdc58f6840d15b4952149d2b345ec1f97d505bcRobert Carrimport android.view.ViewGroup;
284cdc58f6840d15b4952149d2b345ec1f97d505bcRobert Carrimport android.view.WindowManager;
2990ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopianimport android.widget.CheckBox;
3090ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopianimport android.widget.FrameLayout;
3190ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopianimport android.widget.TextView;
3290ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian
33c666cae2d5995097ec49a87e375e2afdd92802b7Mathias Agopianfinal class AppErrorDialog extends BaseErrorDialog {
34718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    private final ActivityManagerService mService;
351078bbba175b7a4b62a2c24ec64928345feb42e6Chia-I Wu    private final AppErrorResult mResult;
3623c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis    private final ProcessRecord mProc;
375e4fcbe411f0a941d604d8a9974a02faa3fda170Pablo Ceballos    private CharSequence mName;
3813fdc49516d17f41e64e62e73c313b0928bf13ccchaviw
395e4fcbe411f0a941d604d8a9974a02faa3fda170Pablo Ceballos    // Event 'what' codes
4023c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis    static final int FORCE_QUIT = 0;
4123c2c5d1c6aaeaeb1804b7aa9b667e7e58c941bbJamie Gennis    static final int FORCE_QUIT_AND_REPORT = 1;
42718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
43718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    // 5-minute timeout, then we automatically dismiss the crash dialog
44718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
45718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
46718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    public AppErrorDialog(Context context, ActivityManagerService service,
47718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            AppErrorResult result, ProcessRecord app) {
48718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        super(context);
49718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
50718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        Resources res = context.getResources();
510ea0f82a7d89190ceff5701ea012ea7611291928Chia-I Wu
52493133032d4d7e680b76553c1b5a4d7a76cda6b1Chia-I Wu        mService = service;
5393853fe18c4b7201774337b104db1974a74d1982Chia-I Wu        mProc = app;
54718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        mResult = result;
552113bdd3561e17238a1787c749329b995016aec4Chia-I Wu        if ((app.pkgList.size() == 1) &&
56718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                (mName = context.getPackageManager().getApplicationLabel(app.info)) != null) {
57718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            setMessage(res.getString(
58718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                    com.android.internal.R.string.aerr_application,
590ea0f82a7d89190ceff5701ea012ea7611291928Chia-I Wu                    mName.toString(), app.info.processName));
60493133032d4d7e680b76553c1b5a4d7a76cda6b1Chia-I Wu        } else {
6193853fe18c4b7201774337b104db1974a74d1982Chia-I Wu            mName = app.processName;
62718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            setMessage(res.getString(
632113bdd3561e17238a1787c749329b995016aec4Chia-I Wu                    com.android.internal.R.string.aerr_process,
64718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                    mName.toString()));
65718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        }
66718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
67718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        setCancelable(false);
68718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
69718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        setButton(DialogInterface.BUTTON_POSITIVE,
70718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                res.getText(com.android.internal.R.string.force_close),
71718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                mHandler.obtainMessage(FORCE_QUIT));
72718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
73718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        if (app.errorReportReceiver != null) {
74718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            setButton(DialogInterface.BUTTON_NEGATIVE,
75718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                    res.getText(com.android.internal.R.string.report),
76718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                    mHandler.obtainMessage(FORCE_QUIT_AND_REPORT));
77718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        }
78718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
79718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        setTitle(res.getText(com.android.internal.R.string.aerr_title));
80718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        WindowManager.LayoutParams attrs = getWindow().getAttributes();
81718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        attrs.setTitle("Application Error: " + app.info.processName);
82718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
83718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
84718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        getWindow().setAttributes(attrs);
85718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        if (app.persistent) {
86718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
87718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        }
88718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
89718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        // After the timeout, pretend the user clicked the quit button
90718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        mHandler.sendMessageDelayed(
91718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                mHandler.obtainMessage(FORCE_QUIT),
92718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                DISMISS_TIMEOUT);
93718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    }
94718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
95718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    @Override
96718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    protected void onCreate(Bundle savedInstanceState) {
97718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        super.onCreate(savedInstanceState);
98718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        if (!ActivityManagerService.IS_USER_BUILD) {
99718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            FrameLayout frame = (FrameLayout) findViewById(android.R.id.custom);
100718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            Context context = getContext();
101718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            LayoutInflater.from(context).inflate(
102718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                    com.android.internal.R.layout.app_error_dialog_dont_show_again, frame, true);
103718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            ((TextView) frame.findViewById(com.android.internal.R.id.text)).setText(
104718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                    context.getResources().getString(
105718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                            com.android.internal.R.string.aerr_process_silence,
106718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                            mName.toString()));
10740482ff650751819d4104c10a30974838168438cChavi Weingarten            findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
108718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        }
109718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    }
110718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
111718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    private final Handler mHandler = new Handler() {
112718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        public void handleMessage(Message msg) {
113718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            View view = findViewById(com.android.internal.R.id.checkbox);
11440482ff650751819d4104c10a30974838168438cChavi Weingarten            final boolean stopReporting = view != null && ((CheckBox) view).isChecked();
11540482ff650751819d4104c10a30974838168438cChavi Weingarten            synchronized (mService) {
11640482ff650751819d4104c10a30974838168438cChavi Weingarten                if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
11740482ff650751819d4104c10a30974838168438cChavi Weingarten                    mProc.crashDialog = null;
11840482ff650751819d4104c10a30974838168438cChavi Weingarten                }
119718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu                if (stopReporting) {
12040482ff650751819d4104c10a30974838168438cChavi Weingarten                    mService.stopReportingCrashesLocked(mProc);
12140482ff650751819d4104c10a30974838168438cChavi Weingarten                }
12240482ff650751819d4104c10a30974838168438cChavi Weingarten            }
123718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            mResult.set(msg.what);
124718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
125718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            // Make sure we don't have time timeout still hanging around.
126718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            removeMessages(FORCE_QUIT);
127718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
128718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            // If this is a timeout we won't be automatically closed, so go
129718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            // ahead and explicitly dismiss ourselves just in case.
13040482ff650751819d4104c10a30974838168438cChavi Weingarten            dismiss();
131718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        }
132718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    };
133718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu
134718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    @Override
135718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    public void dismiss() {
136718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        if (!mResult.mHasResult) {
137718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            // We are dismissing and the result has not been set...go ahead and set.
138718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu            mResult.set(FORCE_QUIT);
139718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        }
140718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu        super.dismiss();
141718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu    }
142718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu}
143718daf8b58cdaa4fb87ee4093df44d423218aa9fChia-I Wu