186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock/*
286b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * Copyright (C) 2012 The Android Open Source Project
386b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock *
486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * you may not use this file except in compliance with the License.
686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * You may obtain a copy of the License at
786b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock *
886b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
986b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock *
1086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * Unless required by applicable law or agreed to in writing, software
1186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
1286b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1386b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * See the License for the specific language governing permissions and
1486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock * limitations under the License.
1586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock */
1686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
175ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard;
1886b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
1986b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.content.Context;
2086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.content.pm.PackageManager.NameNotFoundException;
2186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.graphics.Color;
22737798271e6e5b9466acef26ead061ecf6d0f292John Spurlockimport android.graphics.Point;
230552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlockimport android.graphics.Rect;
2486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.os.Handler;
2586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.os.SystemClock;
2686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.util.Log;
2726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandlerimport android.view.Gravity;
2886b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.view.LayoutInflater;
294b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlockimport android.view.MotionEvent;
3086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlockimport android.view.View;
31737798271e6e5b9466acef26ead061ecf6d0f292John Spurlockimport android.view.ViewGroup;
32e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlockimport android.view.WindowManager;
33dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.widget.FrameLayout;
34dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.widget.ImageView;
35dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.widget.ImageView.ScaleType;
3686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
375ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerimport com.android.keyguard.KeyguardActivityLauncher.CameraWidgetInfo;
3886b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
394b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlockpublic class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
4086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    private static final String TAG = CameraWidgetFrame.class.getSimpleName();
415cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi    private static final boolean DEBUG = KeyguardConstants.DEBUG;
4257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private static final int WIDGET_ANIMATION_DURATION = 250; // ms
43aa89847f4e808548edfdb949c217683206ab19ceJim Miller    private static final int WIDGET_WAIT_DURATION = 400; // ms
4457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private static final int RECOVERY_DELAY = 1000; // ms
4586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
4686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    interface Callbacks {
4786b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        void onLaunchingCamera();
4857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        void onCameraLaunchedSuccessfully();
4957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        void onCameraLaunchedUnsuccessfully();
5086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
5186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
5286b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    private final Handler mHandler = new Handler();
53dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private final KeyguardActivityLauncher mActivityLauncher;
5486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    private final Callbacks mCallbacks;
550552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private final CameraWidgetInfo mWidgetInfo;
56e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock    private final WindowManager mWindowManager;
57737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock    private final Point mRenderedSize = new Point();
580552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private final int[] mTmpLoc = new int[2];
5986b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
6086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    private long mLaunchCameraStart;
614b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    private boolean mActive;
624b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    private boolean mTransitioning;
634b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    private boolean mDown;
6486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
6526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler    private final Rect mInsets = new Rect();
6626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler
670552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private FixedSizeFrameLayout mPreview;
680552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private View mFullscreenPreview;
6926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler    private View mFakeNavBar;
70c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller    private boolean mUseFastTransition;
710552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
7257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private final Runnable mTransitionToCameraRunnable = new Runnable() {
7357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        @Override
7457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        public void run() {
7557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            transitionToCamera();
7657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        }};
7757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock
7857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private final Runnable mTransitionToCameraEndAction = new Runnable() {
7986b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        @Override
8086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        public void run() {
81dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock            if (!mTransitioning)
82dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock                return;
8357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            Handler worker =  getWorkerHandler() != null ? getWorkerHandler() : mHandler;
8447cde77bc7ac5c3a1e486691596a7534ad855ff2John Spurlock            mLaunchCameraStart = SystemClock.uptimeMillis();
85dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock            if (DEBUG) Log.d(TAG, "Launching camera at " + mLaunchCameraStart);
8657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
8757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        }};
8857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock
890552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
9057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        @Override
9157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        public void run() {
920552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mHandler.post(mTransitionToCameraEndAction);
9357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        }};
9457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock
950552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private final Runnable mRecoverRunnable = new Runnable() {
9657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        @Override
9757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        public void run() {
980552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            recover();
99dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }};
100dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
101dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private final Runnable mRenderRunnable = new Runnable() {
102dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        @Override
103dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        public void run() {
104dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            render();
10586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        }};
10686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
10757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private final Runnable mSecureCameraActivityStartedRunnable = new Runnable() {
1084b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        @Override
1094b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        public void run() {
11057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            onSecureCameraActivityStarted();
11157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        }
11257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    };
1134b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock
1146275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
1156275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        private boolean mShowing;
1165cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi
1175cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi        @Override
1185cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi        public void onKeyguardVisibilityChanged(boolean showing) {
1196275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock            if (mShowing == showing)
1206275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock                return;
1216275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock            mShowing = showing;
1226275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock            CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
1235cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi        }
1246275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    };
1256275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock
1260552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private static final class FixedSizeFrameLayout extends FrameLayout {
1270552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        int width;
1280552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        int height;
1290552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
1300552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        FixedSizeFrameLayout(Context context) {
1310552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            super(context);
1320552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        }
1330552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
1340552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        @Override
1350552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1360552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            measureChildren(
1370552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
1380552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
1390552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            setMeasuredDimension(width, height);
1400552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        }
1410552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    }
1420552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
143dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private CameraWidgetFrame(Context context, Callbacks callbacks,
1440552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            KeyguardActivityLauncher activityLauncher,
1450552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            CameraWidgetInfo widgetInfo, View previewWidget) {
14686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        super(context);
14786b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        mCallbacks = callbacks;
148dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        mActivityLauncher = activityLauncher;
1490552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mWidgetInfo = widgetInfo;
150e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
1516275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
1520552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
1530552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview = new FixedSizeFrameLayout(context);
1540552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.addView(previewWidget);
1550552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        addView(mPreview);
1560552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
1570552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        View clickBlocker = new View(context);
1580552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        clickBlocker.setBackgroundColor(Color.TRANSPARENT);
1590552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        clickBlocker.setOnClickListener(this);
1600552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        addView(clickBlocker);
1610552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
1620552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
1636275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
164dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
16586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
166dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    public static CameraWidgetFrame create(Context context, Callbacks callbacks,
167dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            KeyguardActivityLauncher launcher) {
168dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (context == null || callbacks == null || launcher == null)
169dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return null;
170dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
171dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
172dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (widgetInfo == null)
173dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return null;
1740552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        View previewWidget = getPreviewWidget(context, widgetInfo);
1750552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (previewWidget == null)
176dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return null;
177dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
1780552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
1790552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    }
1800552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
1810552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
1820552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        return widgetInfo.layoutId > 0 ?
1830552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                inflateWidgetView(context, widgetInfo) :
1840552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                inflateGenericWidgetView(context);
18586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
18686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
187dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
1884b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (DEBUG) Log.d(TAG, "inflateWidgetView: " + widgetInfo.contextPackage);
189dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        View widgetView = null;
19086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        Exception exception = null;
19186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        try {
192dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            Context cameraContext = context.createPackageContext(
193dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                    widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED);
19486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock            LayoutInflater cameraInflater = (LayoutInflater)
19586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock                    cameraContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
19686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock            cameraInflater = cameraInflater.cloneInContext(cameraContext);
197dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            widgetView = cameraInflater.inflate(widgetInfo.layoutId, null, false);
19886b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        } catch (NameNotFoundException e) {
19986b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock            exception = e;
20086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        } catch (RuntimeException e) {
20186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock            exception = e;
20286b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        }
20386b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        if (exception != null) {
20486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock            Log.w(TAG, "Error creating camera widget view", exception);
20586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        }
206dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        return widgetView;
207dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
208dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
209dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static View inflateGenericWidgetView(Context context) {
2104b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (DEBUG) Log.d(TAG, "inflateGenericWidgetView");
211dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        ImageView iv = new ImageView(context);
2125ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller        iv.setImageResource(R.drawable.ic_lockscreen_camera);
213dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        iv.setScaleType(ScaleType.CENTER);
214dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        iv.setBackgroundColor(Color.argb(127, 0, 0, 0));
215dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        return iv;
21686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
21786b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
2180552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private void render() {
2190552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final View root = getRootView();
22026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final int width = root.getWidth() - mInsets.right;    // leave room
22126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final int height = root.getHeight() - mInsets.bottom; // for bars
2220552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (mRenderedSize.x == width && mRenderedSize.y == height) {
22326b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s %d%%",
22426b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                    width, height, (int)(100*mPreview.getScaleX())));
2250552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            return;
2260552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        }
2270552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (width == 0 || height == 0) {
2280552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            return;
22947cde77bc7ac5c3a1e486691596a7534ad855ff2John Spurlock        }
23037d84ae6051ab6d2add1e0ef51cf2aa2605c3225John Spurlock
2310552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.width = width;
2320552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.height = height;
2330552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.requestLayout();
234cf69c56b8336e2bd5c8e20f948cc80ca53e0c25aJohn Spurlock
2350552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
2360552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();
237dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
2380552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvScaleX = (float) thisWidth / width;
2390552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvScaleY = (float) thisHeight / height;
2400552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvScale = Math.min(pvScaleX, pvScaleY);
241cf69c56b8336e2bd5c8e20f948cc80ca53e0c25aJohn Spurlock
2420552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final int pvWidth = (int) (pvScale * width);
2430552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final int pvHeight = (int) (pvScale * height);
244dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
2450552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
2460552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;
247dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
248b6c3b20d7150f725d638c620affd521145fe8f90John Spurlock        final boolean isRtl = mPreview.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
249b6c3b20d7150f725d638c620affd521145fe8f90John Spurlock        mPreview.setPivotX(isRtl ? mPreview.width : 0);
2500552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.setPivotY(0);
2510552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.setScaleX(pvScale);
2520552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.setScaleY(pvScale);
253b6c3b20d7150f725d638c620affd521145fe8f90John Spurlock        mPreview.setTranslationX((isRtl ? -1 : 1) * pvTransX);
2540552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.setTranslationY(pvTransY);
255cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powell
2560552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mRenderedSize.set(width, height);
25726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s %d%% instance=%s",
25826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                width, height, (int)(100*mPreview.getScaleX()), instanceId()));
2590552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    }
260cf69c56b8336e2bd5c8e20f948cc80ca53e0c25aJohn Spurlock
2610552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private void transitionToCamera() {
2620552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (mTransitioning || mDown) return;
263cf69c56b8336e2bd5c8e20f948cc80ca53e0c25aJohn Spurlock
2640552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mTransitioning = true;
265cf69c56b8336e2bd5c8e20f948cc80ca53e0c25aJohn Spurlock
266e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock        enableWindowExitAnimation(false);
267cf69c56b8336e2bd5c8e20f948cc80ca53e0c25aJohn Spurlock
26826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final int navHeight = mInsets.bottom;
26926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final int navWidth = mInsets.right;
27026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler
2710552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.getLocationInWindow(mTmpLoc);
2720552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
2730552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float pvCenter = mTmpLoc[1] + pvHeight / 2f;
27486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
2750552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final ViewGroup root = (ViewGroup) getRootView();
27626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler
27726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        if (DEBUG) {
27826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            Log.d(TAG, "root = " + root.getLeft() + "," + root.getTop() + " "
27926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                    + root.getWidth() + "x" + root.getHeight());
28026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        }
28126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler
2820552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (mFullscreenPreview == null) {
2830552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
2840552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mFullscreenPreview.setClickable(false);
28526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            root.addView(mFullscreenPreview, new FrameLayout.LayoutParams(
28626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                        root.getWidth() - navWidth,
28726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                        root.getHeight() - navHeight));
2880552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        }
2890552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
29026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final float fsHeight = root.getHeight() - navHeight;
29126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final float fsCenter = root.getTop() + fsHeight / 2;
2920552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
29326b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final float fsScaleY = mPreview.getScaleY();
2940552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        final float fsTransY = pvCenter - fsCenter;
29526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        final float fsScaleX = fsScaleY;
2960552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
2970552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.setVisibility(View.GONE);
2980552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mFullscreenPreview.setVisibility(View.VISIBLE);
2990552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mFullscreenPreview.setTranslationY(fsTransY);
3000552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mFullscreenPreview.setScaleX(fsScaleX);
3010552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mFullscreenPreview.setScaleY(fsScaleY);
3020552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mFullscreenPreview
3030552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            .animate()
30457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            .scaleX(1)
30557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            .scaleY(1)
3060552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            .translationX(0)
30757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            .translationY(0)
30857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            .setDuration(WIDGET_ANIMATION_DURATION)
3090552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            .withEndAction(mPostTransitionToCameraEndAction)
31057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            .start();
31126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler
31226b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        if (navHeight > 0 || navWidth > 0) {
31326b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            final boolean atBottom = navHeight > 0;
31426b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            if (mFakeNavBar == null) {
31526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                mFakeNavBar = new View(mContext);
31626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                mFakeNavBar.setBackgroundColor(Color.BLACK);
31726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                root.addView(mFakeNavBar, new FrameLayout.LayoutParams(
31826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                            atBottom ? FrameLayout.LayoutParams.MATCH_PARENT
31926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                                     : navWidth,
32026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                            atBottom ? navHeight
32126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                                     : FrameLayout.LayoutParams.MATCH_PARENT,
32226b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                            atBottom ? Gravity.BOTTOM|Gravity.FILL_HORIZONTAL
32326b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                                     : Gravity.RIGHT|Gravity.FILL_VERTICAL));
32426b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                mFakeNavBar.setPivotY(navHeight);
32526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                mFakeNavBar.setPivotX(navWidth);
32626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            }
32726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            mFakeNavBar.setAlpha(0f);
32826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            if (atBottom) {
32926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                mFakeNavBar.setScaleY(0.5f);
33026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            } else {
33126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                mFakeNavBar.setScaleX(0.5f);
33226b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            }
33326b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            mFakeNavBar.setVisibility(View.VISIBLE);
33426b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            mFakeNavBar.animate()
33526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                .alpha(1f)
33626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                .scaleY(1f)
33726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                .scaleY(1f)
33826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                .setDuration(WIDGET_ANIMATION_DURATION)
33926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler                .start();
34026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        }
3410552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mCallbacks.onLaunchingCamera();
3420552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    }
3430552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
3440552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    private void recover() {
3450552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
3460552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mCallbacks.onCameraLaunchedUnsuccessfully();
3470552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        reset();
3480552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    }
3490552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
3500552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    @Override
3510552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    public void setOnLongClickListener(OnLongClickListener l) {
3520552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        // ignore
35357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    }
35457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock
35586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    @Override
3564b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    public void onClick(View v) {
3574b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (DEBUG) Log.d(TAG, "clicked");
3584b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (mTransitioning) return;
359bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        if (mActive) {
3604b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock            cancelTransitionToCamera();
3614b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock            transitionToCamera();
3624b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        }
3634b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    }
3644b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock
3654b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    @Override
3666275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    protected void onDetachedFromWindow() {
3676275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        if (DEBUG) Log.d(TAG, "onDetachedFromWindow: instance " + instanceId()
3686275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock                + " at " + SystemClock.uptimeMillis());
3696275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        super.onDetachedFromWindow();
3706275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
37157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        cancelTransitionToCamera();
37257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        mHandler.removeCallbacks(mRecoverRunnable);
37386b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
37486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
37586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    @Override
37686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    public void onActive(boolean isActive) {
3774b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mActive = isActive;
3784b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (mActive) {
3794b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock            rescheduleTransitionToCamera();
38086b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        } else {
38186b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock            reset();
38286b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock        }
38386b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
38486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
3854b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    @Override
386bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock    public boolean onUserInteraction(MotionEvent event) {
387bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        if (mTransitioning) {
388bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: mTransitioning");
389bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock            return true;
390bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        }
391bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock
3920552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        getLocationOnScreen(mTmpLoc);
3930552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        int rawBottom = mTmpLoc[1] + getHeight();
394bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        if (event.getRawY() > rawBottom) {
395bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
396bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock            return true;
397bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        }
398bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock
399bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        int action = event.getAction();
4004b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mDown = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE;
401bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        if (mActive) {
4024b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock            rescheduleTransitionToCamera();
4034b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        }
404bb5c941149b66c0192736468bb60f47984dd5e1fJohn Spurlock        if (DEBUG) Log.d(TAG, "onUserInteraction observed, not eaten");
4054b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        return false;
4064b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    }
4074b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock
4084b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    @Override
4094b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    protected void onFocusLost() {
41057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        if (DEBUG) Log.d(TAG, "onFocusLost at " + SystemClock.uptimeMillis());
4114b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        cancelTransitionToCamera();
4124b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        super.onFocusLost();
4134b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    }
4144b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock
415dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock    public void onScreenTurnedOff() {
416dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock        if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
417dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock        reset();
418dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock    }
419dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock
4204b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    private void rescheduleTransitionToCamera() {
4214b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (DEBUG) Log.d(TAG, "rescheduleTransitionToCamera at " + SystemClock.uptimeMillis());
4224b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mHandler.removeCallbacks(mTransitionToCameraRunnable);
423c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller        final long duration = mUseFastTransition ? 0 : WIDGET_WAIT_DURATION;
424c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller        mHandler.postDelayed(mTransitionToCameraRunnable, duration);
4254b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    }
4264b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock
4274b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    private void cancelTransitionToCamera() {
4284b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        if (DEBUG) Log.d(TAG, "cancelTransitionToCamera at " + SystemClock.uptimeMillis());
4294b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mHandler.removeCallbacks(mTransitionToCameraRunnable);
4304b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock    }
4314b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock
43286b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    private void onCameraLaunched() {
43357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        mCallbacks.onCameraLaunchedSuccessfully();
4344b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        reset();
43586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
43686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
43786b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    private void reset() {
43857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
4394b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mLaunchCameraStart = 0;
4404b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mTransitioning = false;
4414b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        mDown = false;
4424b976ea1af04f8c340ef7e0d79f73d7cdb5eb72eJohn Spurlock        cancelTransitionToCamera();
44357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        mHandler.removeCallbacks(mRecoverRunnable);
4440552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mPreview.setVisibility(View.VISIBLE);
4450552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (mFullscreenPreview != null) {
4460552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mFullscreenPreview.animate().cancel();
4470552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mFullscreenPreview.setVisibility(View.GONE);
4480552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        }
44926b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        if (mFakeNavBar != null) {
45026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            mFakeNavBar.animate().cancel();
45126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            mFakeNavBar.setVisibility(View.GONE);
45226b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        }
453e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock        enableWindowExitAnimation(true);
45486b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
45586b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock
456dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    @Override
457737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
458737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock        if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
459737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock                w, h, oldw, oldh, SystemClock.uptimeMillis()));
46026b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        if ((w != oldw && oldw > 0) || (h != oldh && oldh > 0)) {
46126b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            // we can't trust the old geometry anymore; force a re-render
46226b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler            mRenderedSize.x = mRenderedSize.y = -1;
46326b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        }
4640552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        mHandler.post(mRenderRunnable);
465737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock        super.onSizeChanged(w, h, oldw, oldh);
46686b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock    }
467e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock
4680552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    @Override
4690552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    public void onBouncerShowing(boolean showing) {
4700552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        if (showing) {
4710552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mTransitioning = false;
4720552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mHandler.post(mRecoverRunnable);
4730552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock        }
4740552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock    }
4750552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock
476e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock    private void enableWindowExitAnimation(boolean isEnabled) {
477e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock        View root = getRootView();
478737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock        ViewGroup.LayoutParams lp = root.getLayoutParams();
479737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock        if (!(lp instanceof WindowManager.LayoutParams))
480737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock            return;
481737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock        WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp;
4825ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller        int newWindowAnimations = isEnabled ? R.style.Animation_LockScreen : 0;
483737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock        if (newWindowAnimations != wlp.windowAnimations) {
48457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations
48557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    + " at " + SystemClock.uptimeMillis());
486737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock            wlp.windowAnimations = newWindowAnimations;
487737798271e6e5b9466acef26ead061ecf6d0f292John Spurlock            mWindowManager.updateViewLayout(root, wlp);
488e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock        }
489e2ac5207f204ee26ba43c033d9ffb51f7daee2bdJohn Spurlock    }
4906275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock
4916275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    private void onKeyguardVisibilityChanged(boolean showing) {
4926275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
4936275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock                + " at " + SystemClock.uptimeMillis());
4946275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        if (mTransitioning && !showing) {
4950552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mTransitioning = false;
4960552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            mHandler.removeCallbacks(mRecoverRunnable);
4970552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            if (mLaunchCameraStart > 0) {
4980552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
4990552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
5000552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                mLaunchCameraStart = 0;
5010552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock                onCameraLaunched();
5020552c5d75ab4b6d0644e239f130b687a6047d1a7John Spurlock            }
5036275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        }
5046275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    }
5056275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock
50657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private void onSecureCameraActivityStarted() {
50757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        if (DEBUG) Log.d(TAG, "onSecureCameraActivityStarted at " + SystemClock.uptimeMillis());
50857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        mHandler.postDelayed(mRecoverRunnable, RECOVERY_DELAY);
50957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    }
51057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock
5116275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    private String instanceId() {
5126275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock        return Integer.toHexString(hashCode());
5136275b3f1f3de7b0ca285e8f57a6d6014b0fa95b3John Spurlock    }
51426b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler
51526b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler    public void setInsets(Rect insets) {
51626b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        if (DEBUG) Log.d(TAG, "setInsets: " + insets);
51726b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler        mInsets.set(insets);
51826b7bf6e3cf6be009cd4baf59e083bce37633a4aDaniel Sandler    }
519c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller
520c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller    public void setUseFastTransition(boolean useFastTransition) {
521c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller        mUseFastTransition = useFastTransition;
522c816b8eedb4197cd68077f58988581ef6fae6dd1Jim Miller    }
52386b6357e5eb91950eac7de7ffe29e5a4ad32903bJohn Spurlock}
524