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

Commit a770df1d authored by Xin Li's avatar Xin Li
Browse files

DO NOT MERGE - Merge build QP1A.190711.019 into stage-aosp-master

Bug: 139893257
Change-Id: I94fce9c5c0b35cbb88ee27fa4cd037927964d2cd
parents d5f1fed4 57bb140b
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ import java.util.Arrays;

/**
 * Variant of {@link FileDescriptor} that allows its creator to specify regions
 * that should be redacted (appearing as zeros to the reader).
 * that should be redacted.
 *
 * @hide
 */
@@ -44,13 +44,16 @@ public class RedactingFileDescriptor {
    private static final boolean DEBUG = true;

    private volatile long[] mRedactRanges;
    private volatile long[] mFreeOffsets;

    private FileDescriptor mInner = null;
    private ParcelFileDescriptor mOuter = null;

    private RedactingFileDescriptor(Context context, File file, int mode, long[] redactRanges)
    private RedactingFileDescriptor(
            Context context, File file, int mode, long[] redactRanges, long[] freeOffsets)
            throws IOException {
        mRedactRanges = checkRangesArgument(redactRanges);
        mFreeOffsets = freeOffsets;

        try {
            try {
@@ -88,13 +91,17 @@ public class RedactingFileDescriptor {
     *
     * @param file The underlying file to open.
     * @param mode The {@link ParcelFileDescriptor} mode to open with.
     * @param redactRanges List of file offsets that should be redacted, stored
     * @param redactRanges List of file ranges that should be redacted, stored
     *            as {@code [start1, end1, start2, end2, ...]}. Start values are
     *            inclusive and end values are exclusive.
     * @param freePositions List of file offsets at which the four byte value 'free' should be
     *            written instead of zeros within parts of the file covered by {@code redactRanges}.
     *            Non-redacted bytes will not be modified even if covered by a 'free'. This is
     *            useful for overwriting boxes in ISOBMFF files with padding data.
     */
    public static ParcelFileDescriptor open(Context context, File file, int mode,
            long[] redactRanges) throws IOException {
        return new RedactingFileDescriptor(context, file, mode, redactRanges).mOuter;
            long[] redactRanges, long[] freePositions) throws IOException {
        return new RedactingFileDescriptor(context, file, mode, redactRanges, freePositions).mOuter;
    }

    /**
@@ -169,6 +176,15 @@ public class RedactingFileDescriptor {
                for (long j = start; j < end; j++) {
                    data[(int) (j - offset)] = 0;
                }
                // Overwrite data at 'free' offsets within the redaction ranges.
                for (long freeOffset : mFreeOffsets) {
                    final long freeEnd = freeOffset + 4;
                    final long redactFreeStart = Math.max(freeOffset, start);
                    final long redactFreeEnd = Math.min(freeEnd, end);
                    for (long j = redactFreeStart; j < redactFreeEnd; j++) {
                        data[(int) (j - offset)] = (byte) "free".charAt((int) (j - freeOffset));
                    }
                }
            }
            return n;
        }
+1 −1
Original line number Diff line number Diff line
@@ -300,5 +300,5 @@ interface IWindowSession {
    /**
     * Called when the system gesture exclusion has changed.
     */
    void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
    oneway void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
}
+15 −0
Original line number Diff line number Diff line
@@ -967,6 +967,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    static boolean sBrokenInsetsDispatch;
    /**
     * Prior to Q, calling
     * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
     * did not call update the window format so the opacity of the background was not correctly
     * applied to the window. Some applications rely on this misbehavior to work properly.
     * <p>
     * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
     * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
     * which updates the window format.
     * @hide
     */
    protected static boolean sBrokenWindowBackground;
    /** @hide */
    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
    @Retention(RetentionPolicy.SOURCE)
@@ -5104,6 +5117,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
                    || targetSdkVersion < Build.VERSION_CODES.Q;
            sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
            sCompatibilityDone = true;
        }
    }
+295 −210
Original line number Diff line number Diff line
@@ -16,252 +16,167 @@

package com.android.internal.app;

import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.View;
import android.widget.FrameLayout;
import android.view.ViewGroup;
import android.widget.ImageView;

import org.json.JSONObject;

public class PlatLogoActivity extends Activity {
    FrameLayout layout;
    TimeAnimator anim;
    PBackground bg;

    private class PBackground extends Drawable {
        private float maxRadius, radius, x, y, dp;
        private int[] palette;
        private int darkest;
        private float offset;

        public PBackground() {
            randomizePalette();
        }
import com.android.internal.R;

        /**
         * set inner radius of "p" logo
         */
        public void setRadius(float r) {
            this.radius = Math.max(48*dp, r);
        }

        /**
         * move the "p"
         */
        public void setPosition(float x, float y) {
            this.x = x;
            this.y = y;
        }

        /**
         * for animating the "p"
         */
        public void setOffset(float o) {
            this.offset = o;
        }

        /**
         * rough luminance calculation
         * https://www.w3.org/TR/AERT/#color-contrast
         */
        public float lum(int rgb) {
            return ((Color.red(rgb) * 299f) + (Color.green(rgb) * 587f) + (Color.blue(rgb) * 114f)) / 1000f;
        }
import org.json.JSONObject;

/**
         * create a random evenly-spaced color palette
         * guaranteed to contrast!
 * @hide
 */
        public void randomizePalette() {
            final int slots = 2 + (int)(Math.random() * 2);
            float[] color = new float[] { (float) Math.random() * 360f, 1f, 1f };
            palette = new int[slots];
            darkest = 0;
            for (int i=0; i<slots; i++) {
                palette[i] = Color.HSVToColor(color);
                color[0] = (color[0] + 360f/slots) % 360f;
                if (lum(palette[i]) < lum(palette[darkest])) darkest = i;
            }

            final StringBuilder str = new StringBuilder();
            for (int c : palette) {
                str.append(String.format("#%08x ", c));
            }
            Log.v("PlatLogoActivity", "color palette: " + str);
        }

        @Override
        public void draw(Canvas canvas) {
            if (dp == 0) dp = getResources().getDisplayMetrics().density;
            final float width = canvas.getWidth();
            final float height = canvas.getHeight();
            if (radius == 0) {
                setPosition(width / 2, height / 2);
                setRadius(width / 6);
            }
            final float inner_w = radius * 0.667f;

            final Paint paint = new Paint();
            paint.setStrokeCap(Paint.Cap.BUTT);
            canvas.translate(x, y);

            Path p = new Path();
            p.moveTo(-radius, height);
            p.lineTo(-radius, 0);
            p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
            p.lineTo(-radius, radius);

            float w = Math.max(canvas.getWidth(), canvas.getHeight())  * 1.414f;
            paint.setStyle(Paint.Style.FILL);

            int i=0;
            while (w > radius*2 + inner_w*2) {
                paint.setColor(0xFF000000 | palette[i % palette.length]);
                // for a slower but more complete version:
                // paint.setStrokeWidth(w);
                // canvas.drawPath(p, paint);
                canvas.drawOval(-w/2, -w/2, w/2, w/2, paint);
                w -= inner_w * (1.1f + Math.sin((i/20f + offset) * 3.14159f));
                i++;
            }

            // the innermost circle needs to be a constant color to avoid rapid flashing
            paint.setColor(0xFF000000 | palette[(darkest+1) % palette.length]);
            canvas.drawOval(-radius, -radius, radius, radius, paint);

            p.reset();
            p.moveTo(-radius, height);
            p.lineTo(-radius, 0);
            p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
            p.lineTo(-radius + inner_w, radius);

            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(inner_w*2);
            paint.setColor(palette[darkest]);
            canvas.drawPath(p, paint);
            paint.setStrokeWidth(inner_w);
            paint.setColor(0xFFFFFFFF);
            canvas.drawPath(p, paint);
        }

        @Override
        public void setAlpha(int alpha) {

        }

        @Override
        public void setColorFilter(ColorFilter colorFilter) {
public class PlatLogoActivity extends Activity {
    ImageView mZeroView, mOneView;
    BackslashDrawable mBackslash;
    int mClicks;

    static final Paint sPaint = new Paint();
    static {
        sPaint.setStyle(Paint.Style.STROKE);
        sPaint.setStrokeWidth(4f);
        sPaint.setStrokeCap(Paint.Cap.SQUARE);
    }

    @Override
        public int getOpacity() {
            return 0;
    protected void onPause() {
        if (mBackslash != null) {
            mBackslash.stopAnimating();
        }
        mClicks = 0;
        super.onPause();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final float dp = getResources().getDisplayMetrics().density;

        layout = new FrameLayout(this);
        setContentView(layout);
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        getWindow().setNavigationBarColor(0);
        getWindow().setStatusBarColor(0);

        bg = new PBackground();
        layout.setBackground(bg);
        getActionBar().hide();

        final ContentResolver cr = getContentResolver();
        setContentView(R.layout.platlogo_layout);

        layout.setOnTouchListener(new View.OnTouchListener() {
            final String TOUCH_STATS = "touch.stats";
        mBackslash = new BackslashDrawable((int) (50 * dp));

            final PointerCoords pc0 = new PointerCoords();
            final PointerCoords pc1 = new PointerCoords();
        mOneView = findViewById(R.id.one);
        mOneView.setImageDrawable(new OneDrawable());
        mZeroView = findViewById(R.id.zero);
        mZeroView.setImageDrawable(new ZeroDrawable());

            double pressure_min, pressure_max;
            int maxPointers;
            int tapCount;
        final ViewGroup root = (ViewGroup) mOneView.getParent();
        root.setClipChildren(false);
        root.setBackground(mBackslash);
        root.getBackground().setAlpha(0x20);

        View.OnTouchListener tl = new View.OnTouchListener() {
            float mOffsetX, mOffsetY;
            long mClickTime;
            ObjectAnimator mRotAnim;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final float pressure = event.getPressure();
                measureTouchPressure(event);
                switch (event.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        pressure_min = pressure_max = pressure;
                        // fall through
                    case MotionEvent.ACTION_MOVE:
                        if (pressure < pressure_min) pressure_min = pressure;
                        if (pressure > pressure_max) pressure_max = pressure;
                        final int pc = event.getPointerCount();
                        if (pc > maxPointers) maxPointers = pc;
                        if (pc > 1) {
                            event.getPointerCoords(0, pc0);
                            event.getPointerCoords(1, pc1);
                            bg.setRadius((float) Math.hypot(pc0.x - pc1.x, pc0.y - pc1.y) / 2f);
                        v.animate().scaleX(1.1f).scaleY(1.1f);
                        v.getParent().bringChildToFront(v);
                        mOffsetX = event.getRawX() - v.getX();
                        mOffsetY = event.getRawY() - v.getY();
                        long now = System.currentTimeMillis();
                        if (now - mClickTime < 350) {
                            mRotAnim = ObjectAnimator.ofFloat(v, View.ROTATION,
                                    v.getRotation(), v.getRotation() + 3600);
                            mRotAnim.setDuration(10000);
                            mRotAnim.start();
                            mClickTime = 0;
                        } else {
                            mClickTime = now;
                        }
                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_MOVE:
                        v.setX(event.getRawX() - mOffsetX);
                        v.setY(event.getRawY() - mOffsetY);
                        v.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE);
                        break;
                    case MotionEvent.ACTION_UP:
                        try {
                            final String touchDataJson = Settings.System.getString(cr, TOUCH_STATS);
                            final JSONObject touchData = new JSONObject(
                                    touchDataJson != null ? touchDataJson : "{}");
                            if (touchData.has("min")) {
                                pressure_min = Math.min(pressure_min, touchData.getDouble("min"));
                        v.performClick();
                        // fall through
                    case MotionEvent.ACTION_CANCEL:
                        v.animate().scaleX(1f).scaleY(1f);
                        if (mRotAnim != null) mRotAnim.cancel();
                        testOverlap();
                        break;
                }
                            if (touchData.has("max")) {
                                pressure_max = Math.max(pressure_max, touchData.getDouble("max"));
                return true;
            }
                            touchData.put("min", pressure_min);
                            touchData.put("max", pressure_max);
                            Settings.System.putString(cr, TOUCH_STATS, touchData.toString());
                        } catch (Exception e) {
                            Log.e("PlatLogoActivity", "Can't write touch settings", e);
        };

        findViewById(R.id.one).setOnTouchListener(tl);
        findViewById(R.id.zero).setOnTouchListener(tl);
        findViewById(R.id.text).setOnTouchListener(tl);
    }

                        if (maxPointers == 1) {
                            tapCount ++;
                            if (tapCount < 7) {
                                bg.randomizePalette();
                            } else {
    private void testOverlap() {
        final float width = mZeroView.getWidth();
        final float targetX = mZeroView.getX() + width * .2f;
        final float targetY = mZeroView.getY() + width * .3f;
        if (Math.hypot(targetX - mOneView.getX(), targetY - mOneView.getY()) < width * .2f
                && Math.abs(mOneView.getRotation() % 360 - 315) < 15) {
            mOneView.animate().x(mZeroView.getX() + width * .2f);
            mOneView.animate().y(mZeroView.getY() + width * .3f);
            mOneView.setRotation(mOneView.getRotation() % 360);
            mOneView.animate().rotation(315);
            mOneView.performHapticFeedback(HapticFeedbackConstants.CONFIRM);

            mBackslash.startAnimating();

            mClicks++;
            if (mClicks >= 7) {
                launchNextStage();
            }
        } else {
                            tapCount = 0;
                        }
                        maxPointers = 0;
                        break;
                }
                return true;
            mBackslash.stopAnimating();
        }
        });
    }

    private void launchNextStage() {
        final ContentResolver cr = getContentResolver();

        if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0) == 0) {
        if (Settings.System.getLong(cr, "egg_mode" /* Settings.System.EGG_MODE */, 0) == 0) {
            // For posterity: the moment this user unlocked the easter egg
            try {
                Settings.System.putLong(cr,
                        Settings.System.EGG_MODE,
                        "egg_mode", // Settings.System.EGG_MODE,
                        System.currentTimeMillis());
            } catch (RuntimeException e) {
                Log.e("PlatLogoActivity", "Can't write settings", e);
                Log.e("com.android.internal.app.PlatLogoActivity", "Can't write settings", e);
            }
        }
        try {
@@ -270,36 +185,206 @@ public class PlatLogoActivity extends Activity {
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK)
                    .addCategory("com.android.internal.category.PLATLOGO"));
        } catch (ActivityNotFoundException ex) {
            Log.e("PlatLogoActivity", "No more eggs.");
            Log.e("com.android.internal.app.PlatLogoActivity", "No more eggs.");
        }
        finish();
    }

    static final String TOUCH_STATS = "touch.stats";
    double mPressureMin = 0, mPressureMax = -1;

    private void measureTouchPressure(MotionEvent event) {
        final float pressure = event.getPressure();
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                if (mPressureMax < 0) {
                    mPressureMin = mPressureMax = pressure;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (pressure < mPressureMin) mPressureMin = pressure;
                if (pressure > mPressureMax) mPressureMax = pressure;
                break;
        }
    }

    private void syncTouchPressure() {
        try {
            final String touchDataJson = Settings.System.getString(
                    getContentResolver(), TOUCH_STATS);
            final JSONObject touchData = new JSONObject(
                    touchDataJson != null ? touchDataJson : "{}");
            if (touchData.has("min")) {
                mPressureMin = Math.min(mPressureMin, touchData.getDouble("min"));
            }
            if (touchData.has("max")) {
                mPressureMax = Math.max(mPressureMax, touchData.getDouble("max"));
            }
            if (mPressureMax >= 0) {
                touchData.put("min", mPressureMin);
                touchData.put("max", mPressureMax);
                Settings.System.putString(getContentResolver(), TOUCH_STATS, touchData.toString());
            }
        } catch (Exception e) {
            Log.e("com.android.internal.app.PlatLogoActivity", "Can't write touch settings", e);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        syncTouchPressure();
    }

        bg.randomizePalette();
    @Override
    public void onStop() {
        syncTouchPressure();
        super.onStop();
    }

    static class ZeroDrawable extends Drawable {
        int mTintColor;

        anim = new TimeAnimator();
        anim.setTimeListener(
                new TimeAnimator.TimeListener() {
        @Override
                    public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
                        bg.setOffset((float) totalTime / 60000f);
                        bg.invalidateSelf();
        public void draw(Canvas canvas) {
            sPaint.setColor(mTintColor | 0xFF000000);

            canvas.save();
            canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);

            canvas.drawCircle(12f, 12f, 10f, sPaint);
            canvas.restore();
        }
                });

        anim.start();
        @Override
        public void setAlpha(int alpha) { }

        @Override
        public void setColorFilter(ColorFilter colorFilter) { }

        @Override
        public void setTintList(ColorStateList tint) {
            mTintColor = tint.getDefaultColor();
        }

        @Override
    public void onStop() {
        if (anim != null) {
            anim.cancel();
            anim = null;
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }
        super.onStop();
    }

    static class OneDrawable extends Drawable {
        int mTintColor;

        @Override
        public void draw(Canvas canvas) {
            sPaint.setColor(mTintColor | 0xFF000000);

            canvas.save();
            canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);

            final Path p = new Path();
            p.moveTo(12f, 21.83f);
            p.rLineTo(0f, -19.67f);
            p.rLineTo(-5f, 0f);
            canvas.drawPath(p, sPaint);
            canvas.restore();
        }

        @Override
        public void setAlpha(int alpha) { }

        @Override
        public void setColorFilter(ColorFilter colorFilter) { }

        @Override
        public void setTintList(ColorStateList tint) {
            mTintColor = tint.getDefaultColor();
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }
    }

    private static class BackslashDrawable extends Drawable implements TimeAnimator.TimeListener {
        Bitmap mTile;
        Paint mPaint = new Paint();
        BitmapShader mShader;
        TimeAnimator mAnimator = new TimeAnimator();
        Matrix mMatrix = new Matrix();

        public void draw(Canvas canvas) {
            canvas.drawPaint(mPaint);
        }

        BackslashDrawable(int width) {
            mTile = Bitmap.createBitmap(width, width, Bitmap.Config.ALPHA_8);
            mAnimator.setTimeListener(this);

            final Canvas tileCanvas = new Canvas(mTile);
            final float w = tileCanvas.getWidth();
            final float h = tileCanvas.getHeight();

            final Path path = new Path();
            path.moveTo(0, 0);
            path.lineTo(w / 2, 0);
            path.lineTo(w, h / 2);
            path.lineTo(w, h);
            path.close();

            path.moveTo(0, h / 2);
            path.lineTo(w / 2, h);
            path.lineTo(0, h);
            path.close();

            final Paint slashPaint = new Paint();
            slashPaint.setAntiAlias(true);
            slashPaint.setStyle(Paint.Style.FILL);
            slashPaint.setColor(0xFF000000);
            tileCanvas.drawPath(path, slashPaint);

            //mPaint.setColor(0xFF0000FF);
            mShader = new BitmapShader(mTile, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
            mPaint.setShader(mShader);
        }

        public void startAnimating() {
            if (!mAnimator.isStarted()) {
                mAnimator.start();
            }
        }

        public void stopAnimating() {
            if (mAnimator.isStarted()) {
                mAnimator.cancel();
            }
        }

        @Override
        public void setAlpha(int alpha) {
            mPaint.setAlpha(alpha);
        }

        @Override
        public void setColorFilter(ColorFilter colorFilter) {
            mPaint.setColorFilter(colorFilter);
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }

        @Override
        public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
            if (mShader != null) {
                mMatrix.postTranslate(deltaTime / 4f, 0);
                mShader.setLocalMatrix(mMatrix);
                invalidateSelf();
            }
        }
    }
}
Loading