Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 438d0595 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick
Browse files

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
parent 8f1bfb00
Loading
Loading
Loading
Loading
+112 −2
Original line number Diff line number Diff line
@@ -77980,7 +77980,7 @@
 type="float"
 transient="false"
 volatile="false"
 value="0.0010f"
 value="0.001f"
 static="true"
 final="true"
 deprecated="not deprecated"
@@ -124950,6 +124950,116 @@
</parameter>
</method>
</class>
<class name="StrictMode"
 extends="java.lang.Object"
 abstract="false"
 static="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
<method name="getThreadBlockingPolicy"
 return="int"
 abstract="false"
 native="false"
 synchronized="false"
 static="true"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="setThreadBlockingPolicy"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="true"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="policyMask" type="int">
</parameter>
</method>
<field name="DISALLOW_DISK_READ"
 type="int"
 transient="false"
 volatile="false"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="DISALLOW_DISK_WRITE"
 type="int"
 transient="false"
 volatile="false"
 value="1"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="DISALLOW_NETWORK"
 type="int"
 transient="false"
 volatile="false"
 value="4"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="PENALTY_DEATH"
 type="int"
 transient="false"
 volatile="false"
 value="64"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="PENALTY_DIALOG"
 type="int"
 transient="false"
 volatile="false"
 value="32"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="PENALTY_DROPBOX"
 type="int"
 transient="false"
 volatile="false"
 value="128"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="PENALTY_LOG"
 type="int"
 transient="false"
 volatile="false"
 value="16"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
</class>
<class name="SystemClock"
 extends="java.lang.Object"
 abstract="false"
@@ -218779,7 +218889,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="arg0" type="T">
<parameter name="t" type="T">
</parameter>
</method>
</interface>
+24 −0
Original line number Diff line number Diff line
@@ -1062,6 +1062,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder app = data.readStrongBinder();
            ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
            handleApplicationStrictModeViolation(app, ci);
            reply.writeNoException();
            return true;
        }

        case SIGNAL_PERSISTENT_PROCESSES_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            int sig = data.readInt();
@@ -2523,6 +2532,7 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
        data.recycle();
    }

    public boolean handleApplicationWtf(IBinder app, String tag,
            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
    {
@@ -2540,6 +2550,20 @@ class ActivityManagerProxy implements IActivityManager
        return res;
    }

    public void handleApplicationStrictModeViolation(IBinder app,
            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app);
        crashInfo.writeToParcel(data, 0);
        mRemote.transact(HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION, data, reply, 0);
        reply.readException();
        reply.recycle();
        data.recycle();
    }

    public void signalPersistentProcesses(int sig) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
+16 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
@@ -53,6 +54,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.AndroidRuntimeException;
import android.util.Config;
@@ -4131,6 +4133,20 @@ public final class ActivityThread {

        data.info = getPackageInfoNoCheck(data.appInfo);

        /**
         * For system applications on userdebug/eng builds, log stack
         * traces of disk and network access to dropbox for analysis.
         */
        if ((data.appInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0 &&
            !"user".equals(Build.TYPE)) {
            StrictMode.setDropBoxManager(ContextImpl.createDropBoxManager());
            StrictMode.setThreadBlockingPolicy(
                StrictMode.DISALLOW_DISK_WRITE |
                StrictMode.DISALLOW_DISK_READ |
                StrictMode.DISALLOW_NETWORK |
                StrictMode.PENALTY_DROPBOX);
        }

        /**
         * Switch this process to density compatibility mode if needed.
         */
+7 −3
Original line number Diff line number Diff line
@@ -1157,12 +1157,16 @@ class ContextImpl extends Context {
        return mAudioManager;
    }

    /* package */ static DropBoxManager createDropBoxManager() {
        IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
        IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
        return new DropBoxManager(service);
    }

    private DropBoxManager getDropBoxManager() {
        synchronized (mSync) {
            if (mDropBoxManager == null) {
                IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
                IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
                mDropBoxManager = new DropBoxManager(service);
                mDropBoxManager = createDropBoxManager();
            }
        }
        return mDropBoxManager;
+4 −1
Original line number Diff line number Diff line
@@ -256,6 +256,8 @@ public interface IActivityManager extends IInterface {
            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
    public boolean handleApplicationWtf(IBinder app, String tag,
            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
    public void handleApplicationStrictModeViolation(IBinder app,
            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;

    /*
     * This will deliver the specified signal to all the persistent processes. Currently only 
@@ -516,4 +518,5 @@ public interface IActivityManager extends IInterface {
    int START_ACTIVITY_WITH_CONFIG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+106;
    int GET_RUNNING_EXTERNAL_APPLICATIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+107;
    int FINISH_HEAVY_WEIGHT_APP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+108;
    int HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+109;
}
Loading