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

Commit 6804433b authored by Brad Fitzpatrick's avatar Brad Fitzpatrick
Browse files

StrictMode visual notification support.

Change-Id: I64a5adb683060d9649f1132414547bb3c346a2a8
parent 621e17de
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -144242,6 +144242,17 @@
 visibility="public"
>
</method>
<method name="penaltyFlashScreen"
 return="android.os.StrictMode.ThreadPolicy.Builder"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="penaltyLog"
 return="android.os.StrictMode.ThreadPolicy.Builder"
 abstract="false"
+37 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.app.ApplicationErrorReport;
import android.content.Intent;
import android.util.Log;
import android.util.Printer;
import android.view.IWindowManager;

import com.android.internal.os.RuntimeInit;

@@ -108,6 +109,7 @@ public final class StrictMode {
    private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);

    private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
    private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);

    // Only log a duplicate stack trace to the logs every second.
    private static final long MIN_LOG_INTERVAL_MS = 1000;
@@ -179,6 +181,13 @@ public final class StrictMode {
     */
    public static final int PENALTY_DEATH_ON_NETWORK = 0x200;

    /**
     * Flash the screen during violations.
     *
     * @hide
     */
    public static final int PENALTY_FLASH = 0x800;

    /**
     * @hide
     */
@@ -202,7 +211,7 @@ public final class StrictMode {
     */
    private static final int PENALTY_MASK =
            PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
            PENALTY_DEATH_ON_NETWORK;
            PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;

    /**
     * The current VmPolicy in effect.
@@ -376,6 +385,13 @@ public final class StrictMode {
                return enable(PENALTY_DEATH_ON_NETWORK);
            }

            /**
             * Flash the screen during a violation.
             */
            public Builder penaltyFlashScreen() {
                return enable(PENALTY_FLASH);
            }

            /**
             * Log detected violations to the system log.
             */
@@ -710,7 +726,9 @@ public final class StrictMode {
            StrictMode.DETECT_DISK_WRITE |
            StrictMode.DETECT_DISK_READ |
            StrictMode.DETECT_NETWORK |
            StrictMode.PENALTY_DROPBOX);
            StrictMode.PENALTY_DROPBOX |
            (IS_ENG_BUILD ? StrictMode.PENALTY_FLASH : 0)
        );
        sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS |
                StrictMode.DETECT_VM_CLOSABLE_LEAKS |
                StrictMode.PENALTY_DROPBOX;
@@ -904,6 +922,17 @@ public final class StrictMode {
                return;
            }

            // TODO: cache the window manager stub?
            final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
                    IWindowManager.Stub.asInterface(ServiceManager.getService("window")) :
                    null;
            if (windowManager != null) {
                try {
                    windowManager.showStrictModeViolation(true);
                } catch (RemoteException unused) {
                }
            }

            queue.addIdleHandler(new MessageQueue.IdleHandler() {
                    public boolean queueIdle() {
                        long loopFinishTime = SystemClock.uptimeMillis();
@@ -915,6 +944,12 @@ public final class StrictMode {
                            handleViolation(v);
                        }
                        records.clear();
                        if (windowManager != null) {
                            try {
                                windowManager.showStrictModeViolation(false);
                            } catch (RemoteException unused) {
                            }
                        }
                        return false;  // remove this idle handler from the array
                    }
                });
+9 −2
Original line number Diff line number Diff line
@@ -133,6 +133,13 @@ interface IWindowManager
    // For testing
    void setInTouchMode(boolean showFocus);

    // For StrictMode flashing a red border on violations from the UI
    // thread.  The uid/pid is implicit from the Binder call, and the Window
    // Manager uses that to determine whether or not the red border should
    // actually be shown.  (it will be ignored that pid doesn't have windows
    // on screen)
    void showStrictModeViolation(boolean on);

    // These can only be called with the SET_ORIENTATION permission.
    /**
     * Change the current screen rotation, constants as per
+114 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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;  // TODO: use com.android.server.wm, once things move there

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceSession;

class StrictModeFlash {
    private static final String TAG = "StrictModeFlash";

    Surface mSurface;
    int mLastDW;
    int mLastDH;
    boolean mDrawNeeded;
    final int mThickness = 20;

    public StrictModeFlash(Display display, SurfaceSession session) {
        final DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);

        try {
            mSurface = new Surface(session, 0, "StrictModeFlash", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
        } catch (Surface.OutOfResourcesException e) {
            return;
        }

        mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
        mSurface.setPosition(0, 0);
        mDrawNeeded = true;
    }

    private void drawIfNeeded() {
        if (!mDrawNeeded) {
            return;
        }
        mDrawNeeded = false;
        final int dw = mLastDW;
        final int dh = mLastDH;

        Rect dirty = new Rect(0, 0, dw, dh);
        Canvas c = null;
        try {
            c = mSurface.lockCanvas(dirty);
        } catch (IllegalArgumentException e) {
        } catch (Surface.OutOfResourcesException e) {
        }
        if (c == null) {
            return;
        }

        // Top
        c.clipRect(new Rect(0, 0, dw, mThickness), Region.Op.REPLACE);
        c.drawColor(Color.RED);
        // Left
        c.clipRect(new Rect(0, 0, mThickness, dh), Region.Op.REPLACE);
        c.drawColor(Color.RED);
        // Right
        c.clipRect(new Rect(dw - mThickness, 0, dw, dh), Region.Op.REPLACE);
        c.drawColor(Color.RED);
        // Bottom
        c.clipRect(new Rect(0, dh - mThickness, dw, dh), Region.Op.REPLACE);
        c.drawColor(Color.RED);

        mSurface.unlockCanvasAndPost(c);
    }

    // Note: caller responsible for being inside
    // Surface.openTransaction() / closeTransaction()
    public void setVisibility(boolean on) {
        if (mSurface == null) {
            return;
        }
        drawIfNeeded();
        if (on) {
            mSurface.show();
        } else {
            mSurface.hide();
        }
    }

    void positionSurface(int dw, int dh) {
        if (mLastDW == dw && mLastDH == dh) {
            return;
        }
        mLastDW = dw;
        mLastDH = dh;
        mSurface.setSize(dw, dh);
        mDrawNeeded = true;
    }

}
+35 −0
Original line number Diff line number Diff line
@@ -376,6 +376,7 @@ public class WindowManagerService extends IWindowManager.Stub
    Surface mBlurSurface;
    boolean mBlurShown;
    Watermark mWatermark;
    StrictModeFlash mStrictModeFlash;

    int mTransactionSequence = 0;

@@ -4883,6 +4884,36 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    // TODO: more accounting of which pid(s) turned it on, keep count,
    // only allow disables from pids which have count on, etc.
    public void showStrictModeViolation(boolean on) {
        int pid = Binder.getCallingPid();
        synchronized(mWindowMap) {
            // Ignoring requests to enable the red border from clients
            // which aren't on screen.  (e.g. Broadcast Receivers in
            // the background..)
            if (on) {
                boolean isVisible = false;
                for (WindowState ws : mWindows) {
                    if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
                        isVisible = true;
                        break;
                    }
                }
                if (!isVisible) {
                    return;
                }
            }

            Surface.openTransaction();
            if (mStrictModeFlash == null) {
                mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
            }
            mStrictModeFlash.setVisibility(on);
            Surface.closeTransaction();
        }
    }

    public void freezeRotation() {
        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
                "setRotation()")) {
@@ -9198,6 +9229,7 @@ public class WindowManagerService extends IWindowManager.Stub
        return mPolicy.finishLayoutLw();
    }

    // "Something has changed!  Let's make it correct now."
    private final void performLayoutAndPlaceSurfacesLockedInner(
            boolean recoveringMemory) {
        if (mDisplay == null) {
@@ -9249,6 +9281,9 @@ public class WindowManagerService extends IWindowManager.Stub
        if (mWatermark != null) {
            mWatermark.positionSurface(dw, dh);
        }
        if (mStrictModeFlash != null) {
            mStrictModeFlash.positionSurface(dw, dh);
        }

        try {
            boolean wallpaperForceHidingChanged = false;