diff options
author | Brad Fitzpatrick <bradfitz@android.com> | 2010-06-10 12:19:19 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@android.com> | 2010-06-10 14:38:58 -0700 |
commit | 438d0595121a7a2cdf19741e76e3c0e21a5c173d (patch) | |
tree | d4a76171b2eb52c472c2900eb6947ff073bed81a /services/java/com/android | |
parent | 8f1bfb001b522a370a65c8e4545183b7611f672b (diff) | |
download | frameworks_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.java | 50 | ||||
-rw-r--r-- | services/java/com/android/server/am/StrictModeViolationDialog.java | 101 |
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(); + } + }; +} |