15438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/* 25438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Copyright (C) 2011 The Android Open Source Project 35438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * 45438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 55438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * you may not use this file except in compliance with the License. 65438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * You may obtain a copy of the License at 75438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * 85438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 95438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * 105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Unless required by applicable law or agreed to in writing, software 115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * See the License for the specific language governing permissions and 145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * limitations under the License. 155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellypackage com.android.nfc; 185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport com.android.internal.policy.PolicyManager; 2065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales 215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.Animator; 2269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.animation.AnimatorSet; 235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.ObjectAnimator; 245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.PropertyValuesHolder; 25f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.animation.TimeAnimator; 260c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.ActivityManager; 270c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.StatusBarManager; 285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.content.Context; 2969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.pm.ActivityInfo; 3069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.res.Configuration; 315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Bitmap; 325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Canvas; 335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Matrix; 345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.PixelFormat; 35217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.graphics.SurfaceTexture; 3657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenenimport android.os.AsyncTask; 375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.os.Binder; 385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.util.DisplayMetrics; 39595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenenimport android.util.Log; 409340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.ActionMode; 415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Display; 429340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.KeyEvent; 435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.LayoutInflater; 449340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.Menu; 459340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.MenuItem; 46b2112cff553c3b6658440bf06060c7a08f82df5cNick Pellyimport android.view.MotionEvent; 475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Surface; 4882792d9a73138f209d1f46f156604c4c65f69c0bMathias Agopianimport android.view.SurfaceControl; 49217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.view.TextureView; 505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.View; 515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.ViewGroup; 529340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.Window; 535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.WindowManager; 549340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.WindowManager.LayoutParams; 559340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.accessibility.AccessibilityEvent; 560c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.view.animation.AccelerateDecelerateInterpolator; 5769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.view.animation.DecelerateInterpolator; 585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.widget.ImageView; 59be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenenimport android.widget.TextView; 60a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenenimport android.widget.Toast; 615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/** 63f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * This class is responsible for handling the UI animation 64f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * around Android Beam. The animation consists of the following 65f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * animators: 66f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 67f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator: scales the screenshot down to INTERMEDIATE_SCALE 68f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mSlowSendAnimator: scales the screenshot down to 0.2f (used as a "send in progress" animation) 69f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mFastSendAnimator: quickly scales the screenshot down to 0.0f (used for send success) 70f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mFadeInAnimator: fades the current activity back in (used after mFastSendAnimator completes) 71f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mScaleUpAnimator: scales the screenshot back up to full screen (used for failure or receiving) 72f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mHintAnimator: Slowly turns up the alpha of the "Touch to Beam" hint 73f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 74f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Possible sequences are: 75f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 76f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator => mSlowSendAnimator => mFastSendAnimator => mFadeInAnimator (send success) 77f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator => mSlowSendAnimator => mScaleUpAnimator (send failure) 78f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator => mScaleUpAnimator (p2p link broken, or data received) 79f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 80f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Note that mFastSendAnimator and mFadeInAnimator are combined in a set, as they 81f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * are an atomic animation that cannot be interrupted. 82f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 83f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * All methods of this class must be called on the UI thread 845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 8565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralespublic class SendUi implements Animator.AnimatorListener, View.OnTouchListener, 8665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales TimeAnimator.TimeListener, TextureView.SurfaceTextureListener, android.view.Window.Callback { 8765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales static final String TAG = "SendUi"; 88595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen 8969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float INTERMEDIATE_SCALE = 0.6f; 905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 9169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] PRE_SCREENSHOT_SCALE = {1.0f, INTERMEDIATE_SCALE}; 92674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int PRE_DURATION_MS = 350; 9369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 94f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float[] SEND_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 0.2f}; 95674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int SLOW_SEND_DURATION_MS = 8000; // Stretch out sending over 8s 96f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final int FAST_SEND_DURATION_MS = 350; 9769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 9869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] SCALE_UP_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 1.0f}; 9969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final int SCALE_UP_DURATION_MS = 300; 1005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 101674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_DURATION_MS = 250; 102674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_START_DELAY_MS = 350; 103674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 1040c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int SLIDE_OUT_DURATION_MS = 300; 1050c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1061a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen static final float[] BLACK_LAYER_ALPHA_DOWN_RANGE = {0.9f, 0.0f}; 1071a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen static final float[] BLACK_LAYER_ALPHA_UP_RANGE = {0.0f, 0.9f}; 1081a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 109be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final float[] TEXT_HINT_ALPHA_RANGE = {0.0f, 1.0f}; 110be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final int TEXT_HINT_ALPHA_DURATION_MS = 500; 111674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int TEXT_HINT_ALPHA_START_DELAY_MS = 300; 112be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 1130c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int FINISH_SCALE_UP = 0; 114f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final int FINISH_SEND_SUCCESS = 1; 1150c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 11657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen static final int STATE_IDLE = 0; 117595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen static final int STATE_W4_SCREENSHOT = 1; 118595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen static final int STATE_W4_SCREENSHOT_PRESEND_REQUESTED = 2; 1199340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED = 3; 1209340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_SCREENSHOT_THEN_STOP = 4; 1219340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_PRESEND = 5; 1229340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_TOUCH = 6; 1239340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_NFC_TAP = 7; 1249340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_SENDING = 8; 1259340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_COMPLETE = 9; 12657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 1275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // all members are only used on UI thread 12865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final WindowManager mWindowManager; 12965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Context mContext; 13065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Display mDisplay; 13165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final DisplayMetrics mDisplayMetrics; 13265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Matrix mDisplayMatrix; 13365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final WindowManager.LayoutParams mWindowLayoutParams; 13465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final LayoutInflater mLayoutInflater; 13565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final StatusBarManager mStatusBarManager; 13665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final View mScreenshotLayout; 13765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ImageView mScreenshotView; 13865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ImageView mBlackLayer; 13965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TextureView mTextureView; 14065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TextView mTextHint; 14165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TextView mTextRetry; 14265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Callback mCallback; 143f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 144f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // The mFrameCounter animation is purely used to count down a certain 145f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // number of (vsync'd) frames. This is needed because the first 3 146f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // times the animation internally calls eglSwapBuffers(), large buffers 147f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // are allocated by the graphics drivers. This causes the animation 148f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // to look janky. So on platforms where we can use hardware acceleration, 149f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // the animation order is: 150f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Wait for hw surface => start frame counter => start pre-animation after 3 frames 151f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // For platforms where no hw acceleration can be used, the pre-animation 152f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // is started immediately. 15365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TimeAnimator mFrameCounterAnimator; 15465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales 15565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mPreAnimator; 15665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mSlowSendAnimator; 15765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mFastSendAnimator; 15865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mFadeInAnimator; 15965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mHintAnimator; 16065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mScaleUpAnimator; 16165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mAlphaDownAnimator; 16265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mAlphaUpAnimator; 16365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final AnimatorSet mSuccessAnimatorSet; 164f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 165f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Besides animating the screenshot, the Beam UI also renders 166f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // fireflies on platforms where we can do hardware-acceleration. 167f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Firefly rendering is only started once the initial 168f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // "pre-animation" has scaled down the screenshot, to avoid 169f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // that animation becoming janky. Likewise, the fireflies are 170f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // stopped in their tracks as soon as we finish the animation, 171f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // to make the finishing animation smooth. 17265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final boolean mHardwareAccelerated; 17365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final FireflyRenderer mFireflyRenderer; 1745438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 175a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen String mToastString; 1765438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap mScreenshotBitmap; 1770c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 17857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen int mState; 179f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mRenderedFrames; 180f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 1819340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen View mDecor; 1829340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 183f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Used for holding the surface 184f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen SurfaceTexture mSurface; 185f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mSurfaceWidth; 186f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mSurfaceHeight; 1875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 18865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales interface Callback { 18965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales public void onSendConfirmed(); 19065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales public void onCanceled(); 1915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 1925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 19365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales public SendUi(Context context, Callback callback) { 19465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mContext = context; 19565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mCallback = callback; 1965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1975438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics = new DisplayMetrics(); 1985438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix = new Matrix(); 19965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 20065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); 2010c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 2025438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay = mWindowManager.getDefaultDisplay(); 2035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 20465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mLayoutInflater = (LayoutInflater) 20565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout = mLayoutInflater.inflate(R.layout.screenshot, null); 207f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 2085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.screenshot); 2095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout.setFocusable(true); 2105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 211be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint = (TextView) mScreenshotLayout.findViewById(R.id.calltoaction); 2121a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry = (TextView) mScreenshotLayout.findViewById(R.id.retrytext); 2131a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer = (ImageView) mScreenshotLayout.findViewById(R.id.blacklayer); 214217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView = (TextureView) mScreenshotLayout.findViewById(R.id.fireflies); 215217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView.setSurfaceTextureListener(this); 216217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 2170c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // We're only allowed to use hardware acceleration if 2180c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // isHighEndGfx() returns true - otherwise, we're too limited 2190c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // on resources to do it. 220525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mHardwareAccelerated = ActivityManager.isHighEndGfx(); 2210c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen int hwAccelerationFlags = mHardwareAccelerated ? 222f7966d1dadff2d78f01bbdb134e8252b53343179Dianne Hackborn WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED : 0; 2230c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 2245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 2250c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen ViewGroup.LayoutParams.MATCH_PARENT, 0, 0, 2260c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 2275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly WindowManager.LayoutParams.FLAG_FULLSCREEN 22865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales | hwAccelerationFlags 22965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, 2305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PixelFormat.OPAQUE); 231525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mWindowLayoutParams.privateFlags |= 232525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 2335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams.token = new Binder(); 2345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 235f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator = new TimeAnimator(); 236f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.setTimeListener(this); 237f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 2385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preX = PropertyValuesHolder.ofFloat("scaleX", PRE_SCREENSHOT_SCALE); 2395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preY = PropertyValuesHolder.ofFloat("scaleY", PRE_SCREENSHOT_SCALE); 2405438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, preX, preY); 24169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mPreAnimator.setInterpolator(new DecelerateInterpolator()); 2425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.setDuration(PRE_DURATION_MS); 2435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.addListener(this); 2445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 245f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", SEND_SCREENSHOT_SCALE); 246f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", SEND_SCREENSHOT_SCALE); 24765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", 24865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[]{1.0f, 0.0f}); 2494dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 250217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, postY); 251674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mSlowSendAnimator.setInterpolator(new DecelerateInterpolator()); 252217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.setDuration(SLOW_SEND_DURATION_MS); 25369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 254f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, 2554dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen postY, alphaDown); 256f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.setInterpolator(new DecelerateInterpolator()); 257f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.setDuration(FAST_SEND_DURATION_MS); 258f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.addListener(this); 25969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 26065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", SCALE_UP_SCREENSHOT_SCALE); 26165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", SCALE_UP_SCREENSHOT_SCALE); 2624dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 26365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mScaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, scaleUpX, scaleUpY); 264674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setInterpolator(new DecelerateInterpolator()); 26569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.setDuration(SCALE_UP_DURATION_MS); 26669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.addListener(this); 26769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 268674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 1.0f); 269674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, fadeIn); 270674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 271674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setDuration(FADE_IN_DURATION_MS); 272674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setStartDelay(FADE_IN_START_DELAY_MS); 273674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.addListener(this); 274674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 275be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", TEXT_HINT_ALPHA_RANGE); 276be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextHint, alphaUp); 277be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setInterpolator(null); 278be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setDuration(TEXT_HINT_ALPHA_DURATION_MS); 279674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mHintAnimator.setStartDelay(TEXT_HINT_ALPHA_START_DELAY_MS); 280be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 2811a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen alphaDown = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_DOWN_RANGE); 2821a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaDown); 2831a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.setInterpolator(new DecelerateInterpolator()); 2841a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.setDuration(400); 2851a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 2861a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen alphaUp = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_UP_RANGE); 2871a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaUp); 2881a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.setInterpolator(new DecelerateInterpolator()); 2891a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.setDuration(200); 2901a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 29169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet = new AnimatorSet(); 292f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSuccessAnimatorSet.playSequentially(mFastSendAnimator, mFadeInAnimator); 2935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2949340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen // Create a Window with a Decor view; creating a window allows us to get callbacks 2959340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen // on key events (which require a decor view to be dispatched). 29665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mContext.setTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen); 29765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales Window window = PolicyManager.makeNewWindow(mContext); 2989340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen window.setCallback(this); 2999340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen window.requestFeature(Window.FEATURE_NO_TITLE); 3009340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mDecor = window.getDecorView(); 3019340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen window.setContentView(mScreenshotLayout, mWindowLayoutParams); 3029340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 303f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mHardwareAccelerated) { 30465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mFireflyRenderer = new FireflyRenderer(context); 305f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else { 306f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderer = null; 307f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 30857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_IDLE; 3095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void takeScreenshot() { 31257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // There's no point in taking the screenshot if 31357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // we're still finishing the previous animation. 3149340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mState >= STATE_W4_TOUCH) { 31557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen return; 31657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 317595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_SCREENSHOT; 31857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen new ScreenshotTask().execute(); 3195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 32169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show pre-send animation */ 3229340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void showPreSend(boolean promptToNfcTap) { 323595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen switch (mState) { 324595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_IDLE: 325595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected showPreSend() in STATE_IDLE"); 326595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 327595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT: 328595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Still waiting for screenshot, store request in state 329595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // and wait for screenshot completion. 3309340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (promptToNfcTap) { 3319340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState = STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED; 3329340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else { 3339340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState = STATE_W4_SCREENSHOT_PRESEND_REQUESTED; 3349340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 335595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 336595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_REQUESTED: 3379340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED: 338595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected showPreSend() in STATE_W4_SCREENSHOT_PRESEND_REQUESTED"); 339595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 340595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_PRESEND: 341595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Expected path, continue below 342595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen break; 343595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen default: 344595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected showPreSend() in state " + Integer.toString(mState)); 345595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 34657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 34790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Update display metrics 34890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mDisplay.getRealMetrics(mDisplayMetrics); 34990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 35065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 35190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 35290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 3531a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setVisibility(View.GONE); 3541a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setAlpha(0f); 355595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mScreenshotLayout.setOnTouchListener(this); 3565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView.setImageBitmap(mScreenshotBitmap); 3570c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setTranslationX(0f); 3580c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setAlpha(1.0f); 35990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotView.setPadding(0, statusBarHeight, 0, 0); 36069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 36190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotLayout.requestFocus(); 36269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 3639340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (promptToNfcTap) { 36465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mTextHint.setText(mContext.getResources().getString(R.string.ask_nfc_tap)); 3659340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else { 36665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mTextHint.setText(mContext.getResources().getString(R.string.touch)); 3679340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 368e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setAlpha(0.0f); 369e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setVisibility(View.VISIBLE); 370e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mHintAnimator.start(); 371be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 37269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Lock the orientation. 37369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // The orientation from the configuration does not specify whether 37469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // the orientation is reverse or not (ie landscape or reverse landscape). 37569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // So we have to use SENSOR_LANDSCAPE or SENSOR_PORTRAIT to make sure 37669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // we lock in portrait / landscape and have the sensor determine 37769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // which way is up. 37865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales int orientation = mContext.getResources().getConfiguration().orientation; 37969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 38069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen switch (orientation) { 38169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_LANDSCAPE: 38269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 38369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; 38469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 38569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_PORTRAIT: 38669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 38769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 38869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 38969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen default: 39069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 39169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 39269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 39369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 39469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 3959340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mWindowManager.addView(mDecor, mWindowLayoutParams); 3960c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // Disable statusbar pull-down 3970c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND); 3980c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 399a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen mToastString = null; 400f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 401f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mHardwareAccelerated) { 402f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mPreAnimator.start(); 403f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } // else, we will start the animation once we get the hardware surface 4049340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState = promptToNfcTap ? STATE_W4_NFC_TAP : STATE_W4_TOUCH; 40569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 4065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 40769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show starting send animation */ 40869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen public void showStartSend() { 40957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen if (mState < STATE_SENDING) return; 410217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 4111a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry.setVisibility(View.GONE); 412f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Update the starting scale - touchscreen-mashers may trigger 413f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // this before the pre-animation completes. 41490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen float currentScale = mScreenshotView.getScaleX(); 41565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", 41665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 41765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", 41865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 419217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 420f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSlowSendAnimator.setValues(postX, postY); 4211a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 4221a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen float currentAlpha = mBlackLayer.getAlpha(); 4231a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen if (mBlackLayer.isShown() && currentAlpha > 0.0f) { 42465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", 42565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentAlpha, 0.0f}); 4261a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.setValues(alphaDown); 4271a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.start(); 4281a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 429f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSlowSendAnimator.start(); 43069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 43169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 432a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen public void finishAndToast(int finishMode, String toast) { 433a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen mToastString = toast; 434a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen 435a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen finish(finishMode); 436a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen } 437a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen 43869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Return to initial state */ 4390c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen public void finish(int finishMode) { 440595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen switch (mState) { 441595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_IDLE: 442595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 443595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT: 444595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_REQUESTED: 4459340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED: 446595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Screenshot is still being captured on a separate thread. 447595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Update state, and stop everything when the capture is done. 448595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_SCREENSHOT_THEN_STOP; 449595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 450595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT_THEN_STOP: 451595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected call to finish() in STATE_W4_SCREENSHOT_THEN_STOP"); 452595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 453595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_PRESEND: 454595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // We didn't build up any animation state yet, but 455595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // did store the bitmap. Clear out the bitmap, reset 456595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // state and bail. 457595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mScreenshotBitmap = null; 458595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_IDLE; 459595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 460595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen default: 461595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // We've started animations and attached a view; tear stuff down below. 462595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen break; 463595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } 464f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 465f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Stop rendering the fireflies 466f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mFireflyRenderer != null) { 467f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderer.stop(); 46869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 469f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 470be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint.setVisibility(View.GONE); 4711a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry.setVisibility(View.GONE); 472f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 473f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float currentScale = mScreenshotView.getScaleX(); 474f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float currentAlpha = mScreenshotView.getAlpha(); 475f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 476f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (finishMode == FINISH_SCALE_UP) { 4771a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setVisibility(View.GONE); 478674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", 47965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 1.0f}); 480674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", 48165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 1.0f}); 482674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpAlpha = PropertyValuesHolder.ofFloat("alpha", 48365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentAlpha, 1.0f}); 484f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mScaleUpAnimator.setValues(scaleUpX, scaleUpY, scaleUpAlpha); 485f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 4860c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScaleUpAnimator.start(); 487f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (finishMode == FINISH_SEND_SUCCESS){ 488f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Modify the fast send parameters to match the current scale 489f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", 49065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 491f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", 49265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 493f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 49465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentAlpha, 0.0f}); 495f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.setValues(postX, postY, alpha); 496f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 497f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Reset the fadeIn parameters to start from alpha 1 498f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 49965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {0.0f, 1.0f}); 500f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFadeInAnimator.setValues(fadeIn); 501f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 502f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSlowSendAnimator.cancel(); 503f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSuccessAnimatorSet.start(); 5040c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen } 50557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_COMPLETE; 5065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5075438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 508595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen void dismiss() { 5099340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mState < STATE_W4_TOUCH) return; 51057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // Immediately set to IDLE, to prevent .cancel() calls 5114e0ab3174beafb4915388d8c11286a48e362ed7cMartijn Coenen // below from immediately calling into dismiss() again. 51257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // (They can do so on the same thread). 51357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_IDLE; 514f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = null; 515f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.cancel(); 5165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.cancel(); 517217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.cancel(); 518f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.cancel(); 51969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet.cancel(); 52069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.cancel(); 5211a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.cancel(); 5221a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.cancel(); 5239340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mWindowManager.removeView(mDecor); 5240c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); 52557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mScreenshotBitmap = null; 526a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen if (mToastString != null) { 52765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales Toast.makeText(mContext, mToastString, Toast.LENGTH_LONG).show(); 528a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen } 529a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen mToastString = null; 5305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 5325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 5335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * @return the current display rotation in degrees 5345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 5355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly static float getDegreesForRotation(int value) { 5365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly switch (value) { 5375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_90: 5385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 90f; 5395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_180: 5405438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 180f; 5415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_270: 5425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 270f; 5435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 0f; 5455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 54757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen final class ScreenshotTask extends AsyncTask<Void, Void, Bitmap> { 54857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 54957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen protected Bitmap doInBackground(Void... params) { 55057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen return createScreenshot(); 55157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 55257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 55357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 55457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen protected void onPostExecute(Bitmap result) { 555595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen if (mState == STATE_W4_SCREENSHOT) { 556595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Screenshot done, wait for request to start preSend anim 557595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_PRESEND; 558595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } else if (mState == STATE_W4_SCREENSHOT_THEN_STOP) { 559595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // We were asked to finish, move to idle state and exit 560595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_IDLE; 5619340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else if (mState == STATE_W4_SCREENSHOT_PRESEND_REQUESTED || 5629340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState == STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED) { 563595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen if (result != null) { 564595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mScreenshotBitmap = result; 5659340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen boolean requestTap = (mState == STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED); 566595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_PRESEND; 5679340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen showPreSend(requestTap); 568595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } else { 569595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Failed to take screenshot; reset state to idle 570595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // and don't do anything 571595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Failed to create screenshot"); 572595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_IDLE; 573595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } 574595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } else { 575595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Invalid state on screenshot completion: " + Integer.toString(mState)); 57657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 57757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 57865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales }; 57957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 5805438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 5815438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Returns a screenshot of the current display contents. 5825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 5835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap createScreenshot() { 5845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // We need to orient the screenshot correctly (and the Surface api seems to 5855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // take screenshots only in the natural orientation of the device :!) 5865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay.getRealMetrics(mDisplayMetrics); 58765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales boolean hasNavBar = mContext.getResources().getBoolean( 588e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.bool.config_showNavigationBar); 5890c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 5905443a8f5b786bfc03633ea5821d95dffc856e3e8Martijn Coenen float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels}; 5915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly float degrees = getDegreesForRotation(mDisplay.getRotation()); 59265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 59390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 594e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen 59590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Navbar has different sizes, depending on orientation 59665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int navBarHeight = hasNavBar ? mContext.getResources().getDimensionPixelSize( 597e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.dimen.navigation_bar_height) : 0; 59865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int navBarHeightLandscape = hasNavBar ? mContext.getResources().getDimensionPixelSize( 599525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project com.android.internal.R.dimen.navigation_bar_height_landscape) : 0; 600525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 60165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int navBarWidth = hasNavBar ? mContext.getResources().getDimensionPixelSize( 602e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.dimen.navigation_bar_width) : 0; 60390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 6045438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly boolean requiresRotation = (degrees > 0); 6055438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 6065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Get the dimensions of the device in its native orientation 6075438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.reset(); 6085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.preRotate(-degrees); 6095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.mapPoints(dims); 6105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[0] = Math.abs(dims[0]); 6115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[1] = Math.abs(dims[1]); 6125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 61482792d9a73138f209d1f46f156604c4c65f69c0bMathias Agopian Bitmap bitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]); 6155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Bail if we couldn't take the screenshot 6165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (bitmap == null) { 6175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return null; 6185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 6215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Rotate the screenshot to the current orientation 6225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, 6235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); 6245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Canvas c = new Canvas(ss); 6255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(ss.getWidth() / 2, ss.getHeight() / 2); 6265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.rotate(360f - degrees); 6275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(-dims[0] / 2, -dims[1] / 2); 6285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.drawBitmap(bitmap, 0, 0, null); 6295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly bitmap = ss; 6315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 63390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // TODO this is somewhat device-specific; need generic solution. 63490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Crop off the status bar and the nav bar 63590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait: 0, statusBarHeight, width, height - status - nav 63690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Landscape: 0, statusBarHeight, width - navBar, height - status 63790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newLeft = 0; 63890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newTop = statusBarHeight; 63990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newWidth = bitmap.getWidth(); 64090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newHeight = bitmap.getHeight(); 641525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project float smallestWidth = (float)Math.min(newWidth, newHeight); 642525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project float smallestWidthDp = smallestWidth / (mDisplayMetrics.densityDpi / 160f); 64390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen if (bitmap.getWidth() < bitmap.getHeight()) { 64490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait mode: status bar is at the top, navbar bottom, width unchanged 64590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newHeight = bitmap.getHeight() - statusBarHeight - navBarHeight; 64690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } else { 647525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Landscape mode: status bar is at the top 648525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Navbar: bottom on >599dp width devices, otherwise to the side 649525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (smallestWidthDp > 599) { 650525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project newHeight = bitmap.getHeight() - statusBarHeight - navBarHeightLandscape; 651525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else { 652525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project newHeight = bitmap.getHeight() - statusBarHeight; 653525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project newWidth = bitmap.getWidth() - navBarWidth; 654525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 65590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } 65690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen bitmap = Bitmap.createBitmap(bitmap, newLeft, newTop, newWidth, newHeight); 65790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 6585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return bitmap; 6595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationStart(Animator animation) { } 6635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationEnd(Animator animation) { 6660c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen if (animation == mScaleUpAnimator || animation == mSuccessAnimatorSet || 667f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen animation == mFadeInAnimator) { 668f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // These all indicate the end of the animation 6695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dismiss(); 670f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (animation == mFastSendAnimator) { 671f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // After sending is done and we've faded out, reset the scale to 1 6724dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen // so we can fade it back in. 6734dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleX(1.0f); 6744dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleY(1.0f); 675f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (animation == mPreAnimator) { 6769340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mHardwareAccelerated && (mState == STATE_W4_TOUCH || mState == STATE_W4_NFC_TAP)) { 677f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderer.start(mSurface, mSurfaceWidth, mSurfaceHeight); 678f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 6795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6805438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6815438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationCancel(Animator animation) { } 6845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationRepeat(Animator animation) { } 687b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly 688b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly @Override 689f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { 690f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // This gets called on animation vsync 691f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (++mRenderedFrames < 4) { 692f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // For the first 3 frames, call invalidate(); this calls eglSwapBuffers 693f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // on the surface, which will allocate large buffers the first three calls 694f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // as Android uses triple buffering. 695f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mScreenshotLayout.invalidate(); 696f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else { 697f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Buffers should be allocated, start the real animation 698f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.cancel(); 699f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mPreAnimator.start(); 700f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 701f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 702f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 703f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen @Override 704b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly public boolean onTouch(View v, MotionEvent event) { 7059340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mState != STATE_W4_TOUCH) { 706b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return false; 707b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 70857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_SENDING; 70969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Ignore future touches 71069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScreenshotView.setOnTouchListener(null); 71169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 712f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Cancel any ongoing animations 713f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.cancel(); 714f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mPreAnimator.cancel(); 715f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 71665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mCallback.onSendConfirmed(); 717b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return true; 718b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 719217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 720217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 721217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 72257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen if (mHardwareAccelerated && mState < STATE_COMPLETE) { 723f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mRenderedFrames = 0; 724f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 725f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.start(); 726f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = surface; 727f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurfaceWidth = width; 728f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurfaceHeight = height; 729217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 730217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 731217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 732217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 733217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 734217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Since we've disabled orientation changes, we can safely ignore this 735217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 736217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 737217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 738217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 739f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = null; 740f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 741217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen return true; 742217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 743217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 744217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 745f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void onSurfaceTextureUpdated(SurfaceTexture surface) { } 746f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 7471a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen public void showSendHint() { 7481a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen if (mAlphaDownAnimator.isRunning()) { 7491a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.cancel(); 7501a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 7511a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen if (mSlowSendAnimator.isRunning()) { 7521a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mSlowSendAnimator.cancel(); 7531a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 7541a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setScaleX(mScreenshotView.getScaleX()); 7551a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setScaleY(mScreenshotView.getScaleY()); 7561a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setVisibility(View.VISIBLE); 7571a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextHint.setVisibility(View.GONE); 7581a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 75965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mTextRetry.setText(mContext.getResources().getString(R.string.beam_try_again)); 7601a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry.setVisibility(View.VISIBLE); 7611a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 7621a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", 76365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {mBlackLayer.getAlpha(), 0.9f}); 7641a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.setValues(alphaUp); 7651a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.start(); 7661a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 7679340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7689340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7699340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchKeyEvent(KeyEvent event) { 77027382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen int keyCode = event.getKeyCode(); 77127382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen if (keyCode == KeyEvent.KEYCODE_BACK) { 77265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mCallback.onCanceled(); 77327382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen return true; 77427382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || 77527382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 77627382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen // Treat as if it's a touch event 77727382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen return onTouch(mScreenshotView, null); 77827382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen } else { 77927382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen return false; 78027382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen } 7819340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7829340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7839340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7849340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7859340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 7869340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7879340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7889340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7899340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchTouchEvent(MotionEvent event) { 7909340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return mScreenshotLayout.dispatchTouchEvent(event); 7919340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7929340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7939340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7949340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchTrackballEvent(MotionEvent event) { 7959340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 7969340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7979340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7989340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7999340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchGenericMotionEvent(MotionEvent event) { 8009340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8019340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8029340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8039340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8049340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 8059340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8069340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8079340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8089340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8099340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public View onCreatePanelView(int featureId) { 8109340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return null; 8119340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8129340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8139340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8149340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onCreatePanelMenu(int featureId, Menu menu) { 8159340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8169340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8179340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8189340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8199340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onPreparePanel(int featureId, View view, Menu menu) { 8209340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8219340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8229340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8239340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8249340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onMenuOpened(int featureId, Menu menu) { 8259340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8269340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8279340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8289340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8299340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onMenuItemSelected(int featureId, MenuItem item) { 8309340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8319340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8329340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8339340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8349340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onWindowAttributesChanged(LayoutParams attrs) { 8359340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8369340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8379340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8389340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onContentChanged() { 8399340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8409340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8419340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8429340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onWindowFocusChanged(boolean hasFocus) { 8439340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8449340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8459340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8469340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onAttachedToWindow() { 8479340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8489340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8499340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8509340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8519340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onDetachedFromWindow() { 8529340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8539340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8549340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8559340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onPanelClosed(int featureId, Menu menu) { 8569340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8579340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8589340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8599340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8609340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onSearchRequested() { 8619340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8629340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8639340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8649340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8659340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public ActionMode onWindowStartingActionMode( 8669340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen android.view.ActionMode.Callback callback) { 8679340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return null; 8689340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8699340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8709340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8719340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onActionModeStarted(ActionMode mode) { 8729340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8739340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8749340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8759340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onActionModeFinished(ActionMode mode) { 8769340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8775438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly} 878