summaryrefslogtreecommitdiffstats
path: root/services/java/com/android
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@android.com>2010-06-10 12:19:19 -0700
committerBrad Fitzpatrick <bradfitz@android.com>2010-06-10 14:38:58 -0700
commit438d0595121a7a2cdf19741e76e3c0e21a5c173d (patch)
treed4a76171b2eb52c472c2900eb6947ff073bed81a /services/java/com/android
parent8f1bfb001b522a370a65c8e4545183b7611f672b (diff)
downloadframeworks_base-438d0595121a7a2cdf19741e76e3c0e21a5c173d.zip
frameworks_base-438d0595121a7a2cdf19741e76e3c0e21a5c173d.tar.gz
frameworks_base-438d0595121a7a2cdf19741e76e3c0e21a5c173d.tar.bz2
Introduce "StrictMode"
This is a new public API for developers to opt-in to strict rules about what they're allowed to do on certain threads. (this is the public face of the @hide dalvik.system.BlockGuard, added recently...) In practice this will be used for developers to opt-in to declaring that they don't want to be allowed to do various operations (such as disk I/O or network operations) on their main UI threads. (these operations are often accidental, or even when they are fast come with a good chance of being slow or very slow in some cases....) Implementation wise, this is just a thread-local integer that has a bitmask of the things that aren't allowed, and more bits for saying what the violation penalty is. The penalties, of which multiple can be chosen, include: * logging * dropbox uploading for analysis/reporting * annoying dialog * full-on crashing These are all only very roughly implemented at this point, but all parts now minimally work end-to-end now, so this is a good checkpoint commit before this gets too large. Future CLs will polish all the above 4 penalties, including checksumming of stacktraces and minimizing penalties for duplicate violations. Change-Id: Icbe61a2e950119519e7364030b10c3c28d243abe
Diffstat (limited to 'services/java/com/android')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java50
-rw-r--r--services/java/com/android/server/am/StrictModeViolationDialog.java101
2 files changed, 151 insertions, 0 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b3c5199..cfcac86 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1023,6 +1023,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
static final int FINALIZE_PENDING_INTENT_MSG = 23;
static final int POST_HEAVY_NOTIFICATION_MSG = 24;
static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
+ static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
AlertDialog mUidAlert;
@@ -1076,6 +1077,31 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
ensureBootCompleted();
} break;
+ case SHOW_STRICT_MODE_VIOLATION_MSG: {
+ HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
+ synchronized (ActivityManagerService.this) {
+ ProcessRecord proc = (ProcessRecord) data.get("app");
+ if (proc == null) {
+ Slog.e(TAG, "App not found when showing strict mode dialog.");
+ break;
+ }
+ if (proc.crashDialog != null) {
+ Slog.e(TAG, "App already has strict mode dialog: " + proc);
+ return;
+ }
+ AppErrorResult res = (AppErrorResult) data.get("result");
+ if (!mSleeping && !mShuttingDown) {
+ Dialog d = new StrictModeViolationDialog(mContext, res, proc);
+ d.show();
+ proc.crashDialog = d;
+ } else {
+ // The device is asleep, so just pretend that the user
+ // saw a crash dialog and hit "force quit".
+ res.set(0);
+ }
+ }
+ ensureBootCompleted();
+ } break;
case SHOW_FACTORY_ERROR_MSG: {
Dialog d = new FactoryErrorDialog(
mContext, msg.getData().getCharSequence("msg"));
@@ -9311,6 +9337,30 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
crashApplication(r, crashInfo);
}
+ public void handleApplicationStrictModeViolation(
+ IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
+ ProcessRecord r = findAppProcess(app);
+ // TODO: implement
+ Log.w(TAG, "handleApplicationStrictModeViolation.");
+
+ AppErrorResult result = new AppErrorResult();
+ synchronized (this) {
+ final long origId = Binder.clearCallingIdentity();
+
+ Message msg = Message.obtain();
+ msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
+ HashMap<String, Object> data = new HashMap<String, Object>();
+ data.put("result", result);
+ data.put("app", r);
+ msg.obj = data;
+ mHandler.sendMessage(msg);
+
+ Binder.restoreCallingIdentity(origId);
+ }
+ int res = result.get();
+ Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
+ }
+
/**
* Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
* @param app object of the crashing app, null for the system server
diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/java/com/android/server/am/StrictModeViolationDialog.java
new file mode 100644
index 0000000..f4329e2
--- /dev/null
+++ b/services/java/com/android/server/am/StrictModeViolationDialog.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Slog;
+
+class StrictModeViolationDialog extends BaseErrorDialog {
+ private final static String TAG = "StrictModeViolationDialog";
+
+ private final AppErrorResult mResult;
+ private final ProcessRecord mProc;
+
+ // Event 'what' codes
+ static final int ACTION_OK = 0;
+ static final int ACTION_OK_AND_REPORT = 1;
+
+ // 1-minute timeout, then we automatically dismiss the violation
+ // dialog
+ static final long DISMISS_TIMEOUT = 1000 * 60 * 1;
+
+ public StrictModeViolationDialog(Context context, AppErrorResult result, ProcessRecord app) {
+ super(context);
+
+ Resources res = context.getResources();
+
+ mProc = app;
+ mResult = result;
+ CharSequence name;
+ if ((app.pkgList.size() == 1) &&
+ (name=context.getPackageManager().getApplicationLabel(app.info)) != null) {
+ setMessage(res.getString(
+ com.android.internal.R.string.smv_application,
+ name.toString(), app.info.processName));
+ } else {
+ name = app.processName;
+ setMessage(res.getString(
+ com.android.internal.R.string.smv_process,
+ name.toString()));
+ }
+
+ setCancelable(false);
+
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ res.getText(com.android.internal.R.string.dlg_ok),
+ mHandler.obtainMessage(ACTION_OK));
+
+ if (app.errorReportReceiver != null) {
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ res.getText(com.android.internal.R.string.report),
+ mHandler.obtainMessage(ACTION_OK_AND_REPORT));
+ }
+
+ setTitle(res.getText(com.android.internal.R.string.aerr_title));
+ getWindow().addFlags(FLAG_SYSTEM_ERROR);
+ getWindow().setTitle("Strict Mode Violation: " + app.info.processName);
+
+ // After the timeout, pretend the user clicked the quit button
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(ACTION_OK),
+ DISMISS_TIMEOUT);
+ }
+
+ public void onStop() {
+ }
+
+ private final Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ synchronized (mProc) {
+ if (mProc != null && mProc.crashDialog == StrictModeViolationDialog.this) {
+ mProc.crashDialog = null;
+ }
+ }
+ mResult.set(msg.what);
+
+ // If this is a timeout we won't be automatically closed, so go
+ // ahead and explicitly dismiss ourselves just in case.
+ dismiss();
+ }
+ };
+}