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

Commit dc3d76f2 authored by John Spurlock's avatar John Spurlock Committed by Android (Google) Code Review
Browse files

Merge "Refactor the lockscreen camera widget, removing the bitmap." into jb-mr1.1-dev

parents 15db00eb 0552c5d7
Loading
Loading
Loading
Loading
+149 −141
Original line number Original line Diff line number Diff line
@@ -18,10 +18,9 @@ package com.android.internal.policy.impl.keyguard;


import android.content.Context;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
@@ -53,17 +52,20 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
    private final Handler mHandler = new Handler();
    private final Handler mHandler = new Handler();
    private final KeyguardActivityLauncher mActivityLauncher;
    private final KeyguardActivityLauncher mActivityLauncher;
    private final Callbacks mCallbacks;
    private final Callbacks mCallbacks;
    private final CameraWidgetInfo mWidgetInfo;
    private final WindowManager mWindowManager;
    private final WindowManager mWindowManager;
    private final Point mRenderedSize = new Point();
    private final Point mRenderedSize = new Point();
    private final int[] mScreenLocation = new int[2];
    private final int[] mTmpLoc = new int[2];
    private final Rect mTmpRect = new Rect();


    private View mWidgetView;
    private long mLaunchCameraStart;
    private long mLaunchCameraStart;
    private boolean mActive;
    private boolean mActive;
    private boolean mTransitioning;
    private boolean mTransitioning;
    private boolean mRecovering;
    private boolean mDown;
    private boolean mDown;


    private FixedSizeFrameLayout mPreview;
    private View mFullscreenPreview;

    private final Runnable mTransitionToCameraRunnable = new Runnable() {
    private final Runnable mTransitionToCameraRunnable = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
@@ -81,19 +83,16 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
            mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
            mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
        }};
        }};


    private final Runnable mRecoverRunnable = new Runnable() {
    private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
            recover();
            mHandler.post(mTransitionToCameraEndAction);
        }};
        }};


    private final Runnable mRecoverEndAction = new Runnable() {
    private final Runnable mRecoverRunnable = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
            if (!mRecovering)
            recover();
                return;
            mCallbacks.onCameraLaunchedUnsuccessfully();
            reset();
        }};
        }};


    private final Runnable mRenderRunnable = new Runnable() {
    private final Runnable mRenderRunnable = new Runnable() {
@@ -119,13 +118,43 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
        };
        };
    };
    };


    private static final class FixedSizeFrameLayout extends FrameLayout {
        int width;
        int height;

        FixedSizeFrameLayout(Context context) {
            super(context);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            measureChildren(
                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
            setMeasuredDimension(width, height);
        }
    }

    private CameraWidgetFrame(Context context, Callbacks callbacks,
    private CameraWidgetFrame(Context context, Callbacks callbacks,
            KeyguardActivityLauncher activityLauncher) {
            KeyguardActivityLauncher activityLauncher,
            CameraWidgetInfo widgetInfo, View previewWidget) {
        super(context);
        super(context);
        mCallbacks = callbacks;
        mCallbacks = callbacks;
        mActivityLauncher = activityLauncher;
        mActivityLauncher = activityLauncher;
        mWidgetInfo = widgetInfo;
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
        KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);

        mPreview = new FixedSizeFrameLayout(context);
        mPreview.addView(previewWidget);
        addView(mPreview);

        View clickBlocker = new View(context);
        clickBlocker.setBackgroundColor(Color.TRANSPARENT);
        clickBlocker.setOnClickListener(this);
        addView(clickBlocker);

        setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
        if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
        if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
    }
    }


@@ -137,24 +166,17 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
        CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
        CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
        if (widgetInfo == null)
        if (widgetInfo == null)
            return null;
            return null;
        View widgetView = widgetInfo.layoutId > 0 ?
        View previewWidget = getPreviewWidget(context, widgetInfo);
                inflateWidgetView(context, widgetInfo) :
        if (previewWidget == null)
                inflateGenericWidgetView(context);
        if (widgetView == null)
            return null;
            return null;


        ImageView preview = new ImageView(context);
        return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
        preview.setLayoutParams(new FrameLayout.LayoutParams(
    }
                FrameLayout.LayoutParams.MATCH_PARENT,

                FrameLayout.LayoutParams.MATCH_PARENT));
    private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
        preview.setScaleType(ScaleType.FIT_CENTER);
        return widgetInfo.layoutId > 0 ?
        preview.setContentDescription(preview.getContext().getString(
                inflateWidgetView(context, widgetInfo) :
                R.string.keyguard_accessibility_camera));
                inflateGenericWidgetView(context);
        CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher);
        cameraWidgetFrame.addView(preview);
        cameraWidgetFrame.mWidgetView = widgetView;
        preview.setOnClickListener(cameraWidgetFrame);
        return cameraWidgetFrame;
    }
    }


    private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
    private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
@@ -188,63 +210,45 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
        return iv;
        return iv;
    }
    }


    public void render() {
    private void render() {
        final Throwable[] thrown = new Throwable[1];
        final View root = getRootView();
        final Bitmap[] offscreen = new Bitmap[1];
        final int width = root.getWidth();
        try {
        final int height = root.getHeight();
            final int width = getRootView().getWidth();
            final int height = getRootView().getHeight();
        if (mRenderedSize.x == width && mRenderedSize.y == height) {
        if (mRenderedSize.x == width && mRenderedSize.y == height) {
                if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s",
            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height));
                        width, height));
            return;
            return;
        }
        }
        if (width == 0 || height == 0) {
        if (width == 0 || height == 0) {
            return;
            return;
        }
        }
            final long start = SystemClock.uptimeMillis();
            offscreen[0] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            final Canvas c = new Canvas(offscreen[0]);
            mWidgetView.measure(
                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
            mWidgetView.layout(0, 0, width, height);
            mWidgetView.draw(c);

            final long end = SystemClock.uptimeMillis();
            if (DEBUG) Log.d(TAG, String.format(
                    "Rendered camera widget in %sms size=%sx%s instance=%s at %s",
                    end - start,
                    width, height,
                    instanceId(),
                    end));
            mRenderedSize.set(width, height);
        } catch (Throwable t) {
            thrown[0] = t;
        }


        mHandler.post(new Runnable() {
        mPreview.width = width;
            @Override
        mPreview.height = height;
            public void run() {
        mPreview.requestLayout();
                if (thrown[0] == null) {
                    try {
                        ((ImageView) getChildAt(0)).setImageBitmap(offscreen[0]);
                    } catch (Throwable t) {
                        thrown[0] = t;
                    }
                }
                if (thrown[0] == null)
                    return;


                Log.w(TAG, "Error rendering camera widget", thrown[0]);
        final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
                try {
        final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();
                    removeAllViews();

                    final View genericView = inflateGenericWidgetView(mContext);
        final float pvScaleX = (float) thisWidth / width;
                    addView(genericView);
        final float pvScaleY = (float) thisHeight / height;
                } catch (Throwable t) {
        final float pvScale = Math.min(pvScaleX, pvScaleY);
                    Log.w(TAG, "Error inflating generic camera widget", t);

                }
        final int pvWidth = (int) (pvScale * width);
            }});
        final int pvHeight = (int) (pvScale * height);

        final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
        final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;

        mPreview.setPivotX(0);
        mPreview.setPivotY(0);
        mPreview.setScaleX(pvScale);
        mPreview.setScaleY(pvScale);
        mPreview.setTranslationX(pvTransX);
        mPreview.setTranslationY(pvTransY);

        mRenderedSize.set(width, height);
        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s",
                width, height, instanceId()));
    }
    }


    private void transitionToCamera() {
    private void transitionToCamera() {
@@ -252,55 +256,53 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli


        mTransitioning = true;
        mTransitioning = true;


        final View child = getChildAt(0);
        enableWindowExitAnimation(false);
        final View root = getRootView();

        final int startWidth = child.getWidth();
        final int startHeight = child.getHeight();

        final int finishWidth = root.getWidth();
        final int finishHeight = root.getHeight();


        final float scaleX = (float) finishWidth / startWidth;
        mPreview.getLocationInWindow(mTmpLoc);
        final float scaleY = (float) finishHeight / startHeight;
        final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
        final float scale = Math.round( Math.max(scaleX, scaleY) * 100) / 100f;
        final float pvCenter = mTmpLoc[1] + pvHeight / 2f;


        final int[] loc = new int[2];
        final ViewGroup root = (ViewGroup) getRootView();
        root.getLocationInWindow(loc);
        if (mFullscreenPreview == null) {
        final int finishCenter = loc[1] + finishHeight / 2;
            mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
            mFullscreenPreview.setClickable(false);
            root.addView(mFullscreenPreview);
        }


        child.getLocationInWindow(loc);
        root.getWindowVisibleDisplayFrame(mTmpRect);
        final int startCenter = loc[1] + startHeight / 2;
        final float fsHeight = mTmpRect.height();
        final float fsCenter = mTmpRect.top + fsHeight / 2;


        if (DEBUG) Log.d(TAG, String.format("Transitioning to camera. " +
        final float fsScaleY = pvHeight / fsHeight;
                "(start=%sx%s, finish=%sx%s, scale=%s,%s, startCenter=%s, finishCenter=%s)",
        final float fsTransY = pvCenter - fsCenter;
                startWidth, startHeight,
        final float fsScaleX = mPreview.getScaleX();
                finishWidth, finishHeight,
                scaleX, scaleY,
                startCenter, finishCenter));


        enableWindowExitAnimation(false);
        mPreview.setVisibility(View.GONE);
        animate()
        mFullscreenPreview.setVisibility(View.VISIBLE);
            .scaleX(scale)
        mFullscreenPreview.setTranslationY(fsTransY);
            .scaleY(scale)
        mFullscreenPreview.setScaleX(fsScaleX);
            .translationY(finishCenter - startCenter)
        mFullscreenPreview.setScaleY(fsScaleY);
        mFullscreenPreview
            .animate()
            .scaleX(1)
            .scaleY(1)
            .translationX(0)
            .translationY(0)
            .setDuration(WIDGET_ANIMATION_DURATION)
            .setDuration(WIDGET_ANIMATION_DURATION)
            .withEndAction(mTransitionToCameraEndAction)
            .withEndAction(mPostTransitionToCameraEndAction)
            .start();
            .start();

        mCallbacks.onLaunchingCamera();
        mCallbacks.onLaunchingCamera();
    }
    }


    private void recover() {
    private void recover() {
        if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
        if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
        mRecovering = true;
        mCallbacks.onCameraLaunchedUnsuccessfully();
        animate()
        reset();
            .scaleX(1)
    }
            .scaleY(1)

            .translationY(0)
    @Override
            .setDuration(WIDGET_ANIMATION_DURATION)
    public void setOnLongClickListener(OnLongClickListener l) {
            .withEndAction(mRecoverEndAction)
        // ignore
            .start();
    }
    }


    @Override
    @Override
@@ -340,8 +342,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
            return true;
            return true;
        }
        }


        getLocationOnScreen(mScreenLocation);
        getLocationOnScreen(mTmpLoc);
        int rawBottom = mScreenLocation[1] + getHeight();
        int rawBottom = mTmpLoc[1] + getHeight();
        if (event.getRawY() > rawBottom) {
        if (event.getRawY() > rawBottom) {
            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
            return true;
            return true;
@@ -388,14 +390,14 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
        if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
        if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
        mLaunchCameraStart = 0;
        mLaunchCameraStart = 0;
        mTransitioning = false;
        mTransitioning = false;
        mRecovering = false;
        mDown = false;
        mDown = false;
        cancelTransitionToCamera();
        cancelTransitionToCamera();
        mHandler.removeCallbacks(mRecoverRunnable);
        mHandler.removeCallbacks(mRecoverRunnable);
        animate().cancel();
        mPreview.setVisibility(View.VISIBLE);
        setScaleX(1);
        if (mFullscreenPreview != null) {
        setScaleY(1);
            mFullscreenPreview.animate().cancel();
        setTranslationY(0);
            mFullscreenPreview.setVisibility(View.GONE);
        }
        enableWindowExitAnimation(true);
        enableWindowExitAnimation(true);
    }
    }


@@ -403,11 +405,18 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
        if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
                w, h, oldw, oldh, SystemClock.uptimeMillis()));
                w, h, oldw, oldh, SystemClock.uptimeMillis()));
        final Handler worker =  getWorkerHandler();
        mHandler.post(mRenderRunnable);
        (worker != null ? worker : mHandler).post(mRenderRunnable);
        super.onSizeChanged(w, h, oldw, oldh);
        super.onSizeChanged(w, h, oldw, oldh);
    }
    }


    @Override
    public void onBouncerShowing(boolean showing) {
        if (showing) {
            mTransitioning = false;
            mHandler.post(mRecoverRunnable);
        }
    }

    private void enableWindowExitAnimation(boolean isEnabled) {
    private void enableWindowExitAnimation(boolean isEnabled) {
        View root = getRootView();
        View root = getRootView();
        ViewGroup.LayoutParams lp = root.getLayoutParams();
        ViewGroup.LayoutParams lp = root.getLayoutParams();
@@ -428,7 +437,6 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
                + " at " + SystemClock.uptimeMillis());
                + " at " + SystemClock.uptimeMillis());
        if (mTransitioning && !showing) {
        if (mTransitioning && !showing) {
            mTransitioning = false;
            mTransitioning = false;
          mRecovering = false;
            mHandler.removeCallbacks(mRecoverRunnable);
            mHandler.removeCallbacks(mRecoverRunnable);
            if (mLaunchCameraStart > 0) {
            if (mLaunchCameraStart > 0) {
                long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
                long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
+5 −0
Original line number Original line Diff line number Diff line
@@ -512,6 +512,10 @@ public class KeyguardWidgetFrame extends FrameLayout {
        return false;
        return false;
    }
    }


    public void onBouncerShowing(boolean showing) {
        // hook for subclasses
    }

    public void setWorkerHandler(Handler workerHandler) {
    public void setWorkerHandler(Handler workerHandler) {
        mWorkerHandler = workerHandler;
        mWorkerHandler = workerHandler;
    }
    }
@@ -519,4 +523,5 @@ public class KeyguardWidgetFrame extends FrameLayout {
    public Handler getWorkerHandler() {
    public Handler getWorkerHandler() {
        return mWorkerHandler;
        return mWorkerHandler;
    }
    }

}
}
+6 −0
Original line number Original line Diff line number Diff line
@@ -775,6 +775,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
            mZoomInOutAnim.start();
            mZoomInOutAnim.start();
        }
        }
        if (currentPage instanceof KeyguardWidgetFrame) {
            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(false);
        }
    }
    }


    // Zoom out after the bouncer is initiated
    // Zoom out after the bouncer is initiated
@@ -800,6 +803,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
            mZoomInOutAnim.start();
            mZoomInOutAnim.start();
        }
        }
        if (currentPage instanceof KeyguardWidgetFrame) {
            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(true);
        }
    }
    }


    boolean isAddPage(int pageIndex) {
    boolean isAddPage(int pageIndex) {