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 17b82d80d891077ccd74729e4143925a66eb89eef2Andres Moralespackage com.android.nfc.beam; 185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 19b82d80d891077ccd74729e4143925a66eb89eef2Andres Moralesimport com.android.nfc.R; 20b82d80d891077ccd74729e4143925a66eb89eef2Andres Moralesimport com.android.nfc.beam.FireflyRenderer; 2165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales 225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.Animator; 2369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.animation.AnimatorSet; 245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.ObjectAnimator; 255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.PropertyValuesHolder; 26f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.animation.TimeAnimator; 270c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.ActivityManager; 280c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.StatusBarManager; 295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.content.Context; 3069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.pm.ActivityInfo; 3169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.res.Configuration; 325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Bitmap; 335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Canvas; 345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Matrix; 355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.PixelFormat; 36217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.graphics.SurfaceTexture; 3757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenenimport android.os.AsyncTask; 385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.os.Binder; 395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.util.DisplayMetrics; 40595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenenimport android.util.Log; 419340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.ActionMode; 425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Display; 439340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.KeyEvent; 445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.LayoutInflater; 459340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.Menu; 469340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.MenuItem; 47b2112cff553c3b6658440bf06060c7a08f82df5cNick Pellyimport android.view.MotionEvent; 48c88594c35808ab286ce68d09d6725e44be3bbc96Adam Powellimport com.android.internal.policy.PhoneWindow; 4986bd05f00c88427e988aa57c0fbbddcb7bd278c6Tim Kilbournimport android.view.SearchEvent; 505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Surface; 5182792d9a73138f209d1f46f156604c4c65f69c0bMathias Agopianimport android.view.SurfaceControl; 52217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.view.TextureView; 535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.View; 545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.ViewGroup; 559340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.Window; 565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.WindowManager; 579340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.WindowManager.LayoutParams; 589340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.view.accessibility.AccessibilityEvent; 590c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.view.animation.AccelerateDecelerateInterpolator; 6069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.view.animation.DecelerateInterpolator; 615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.widget.ImageView; 62be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenenimport android.widget.TextView; 63a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenenimport android.widget.Toast; 645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/** 66f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * This class is responsible for handling the UI animation 67f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * around Android Beam. The animation consists of the following 68f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * animators: 69f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 70f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator: scales the screenshot down to INTERMEDIATE_SCALE 71f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mSlowSendAnimator: scales the screenshot down to 0.2f (used as a "send in progress" animation) 72f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mFastSendAnimator: quickly scales the screenshot down to 0.0f (used for send success) 73f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mFadeInAnimator: fades the current activity back in (used after mFastSendAnimator completes) 74f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mScaleUpAnimator: scales the screenshot back up to full screen (used for failure or receiving) 75f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mHintAnimator: Slowly turns up the alpha of the "Touch to Beam" hint 76f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 77f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Possible sequences are: 78f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 79f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator => mSlowSendAnimator => mFastSendAnimator => mFadeInAnimator (send success) 80f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator => mSlowSendAnimator => mScaleUpAnimator (send failure) 81f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * mPreAnimator => mScaleUpAnimator (p2p link broken, or data received) 82f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 83f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Note that mFastSendAnimator and mFadeInAnimator are combined in a set, as they 84f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * are an atomic animation that cannot be interrupted. 85f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 86f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * All methods of this class must be called on the UI thread 875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 8865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralespublic class SendUi implements Animator.AnimatorListener, View.OnTouchListener, 8965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales TimeAnimator.TimeListener, TextureView.SurfaceTextureListener, android.view.Window.Callback { 9065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales static final String TAG = "SendUi"; 91595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen 9269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float INTERMEDIATE_SCALE = 0.6f; 935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 9469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] PRE_SCREENSHOT_SCALE = {1.0f, INTERMEDIATE_SCALE}; 95674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int PRE_DURATION_MS = 350; 9669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 97f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float[] SEND_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 0.2f}; 98674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int SLOW_SEND_DURATION_MS = 8000; // Stretch out sending over 8s 99f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final int FAST_SEND_DURATION_MS = 350; 10069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 10169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] SCALE_UP_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 1.0f}; 10269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final int SCALE_UP_DURATION_MS = 300; 1035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 104674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_DURATION_MS = 250; 105674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_START_DELAY_MS = 350; 106674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 1070c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int SLIDE_OUT_DURATION_MS = 300; 1080c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1091a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen static final float[] BLACK_LAYER_ALPHA_DOWN_RANGE = {0.9f, 0.0f}; 1101a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen static final float[] BLACK_LAYER_ALPHA_UP_RANGE = {0.0f, 0.9f}; 1111a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 112be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final float[] TEXT_HINT_ALPHA_RANGE = {0.0f, 1.0f}; 113be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final int TEXT_HINT_ALPHA_DURATION_MS = 500; 114674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int TEXT_HINT_ALPHA_START_DELAY_MS = 300; 115be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 116b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales public static final int FINISH_SCALE_UP = 0; 117b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales public static final int FINISH_SEND_SUCCESS = 1; 1180c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 11957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen static final int STATE_IDLE = 0; 120595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen static final int STATE_W4_SCREENSHOT = 1; 121595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen static final int STATE_W4_SCREENSHOT_PRESEND_REQUESTED = 2; 1229340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED = 3; 1239340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_SCREENSHOT_THEN_STOP = 4; 1249340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_PRESEND = 5; 1259340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_TOUCH = 6; 1269340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_W4_NFC_TAP = 7; 1279340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_SENDING = 8; 1289340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen static final int STATE_COMPLETE = 9; 12957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 1305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // all members are only used on UI thread 13165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final WindowManager mWindowManager; 13265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Context mContext; 13365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Display mDisplay; 13465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final DisplayMetrics mDisplayMetrics; 13565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Matrix mDisplayMatrix; 13665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final WindowManager.LayoutParams mWindowLayoutParams; 13765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final LayoutInflater mLayoutInflater; 13865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final StatusBarManager mStatusBarManager; 13965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final View mScreenshotLayout; 14065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ImageView mScreenshotView; 14165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ImageView mBlackLayer; 14265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TextureView mTextureView; 14365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TextView mTextHint; 14465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TextView mTextRetry; 14565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final Callback mCallback; 146f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 147f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // The mFrameCounter animation is purely used to count down a certain 148f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // number of (vsync'd) frames. This is needed because the first 3 149f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // times the animation internally calls eglSwapBuffers(), large buffers 150f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // are allocated by the graphics drivers. This causes the animation 151f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // to look janky. So on platforms where we can use hardware acceleration, 152f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // the animation order is: 153f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Wait for hw surface => start frame counter => start pre-animation after 3 frames 154f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // For platforms where no hw acceleration can be used, the pre-animation 155f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // is started immediately. 15665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final TimeAnimator mFrameCounterAnimator; 15765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales 15865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mPreAnimator; 15965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mSlowSendAnimator; 16065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mFastSendAnimator; 16165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mFadeInAnimator; 16265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mHintAnimator; 16365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mScaleUpAnimator; 16465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mAlphaDownAnimator; 16565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final ObjectAnimator mAlphaUpAnimator; 16665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final AnimatorSet mSuccessAnimatorSet; 167f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 168f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Besides animating the screenshot, the Beam UI also renders 169f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // fireflies on platforms where we can do hardware-acceleration. 170f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Firefly rendering is only started once the initial 171f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // "pre-animation" has scaled down the screenshot, to avoid 172f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // that animation becoming janky. Likewise, the fireflies are 173f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // stopped in their tracks as soon as we finish the animation, 174f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // to make the finishing animation smooth. 17565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final boolean mHardwareAccelerated; 17665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final FireflyRenderer mFireflyRenderer; 1775438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 178a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen String mToastString; 1795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap mScreenshotBitmap; 1800c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 18157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen int mState; 182f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mRenderedFrames; 183f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 1849340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen View mDecor; 1859340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 186f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Used for holding the surface 187f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen SurfaceTexture mSurface; 188f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mSurfaceWidth; 189f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mSurfaceHeight; 1905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 191b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales public interface Callback { 19265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales public void onSendConfirmed(); 19365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales public void onCanceled(); 1945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 1955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 19665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales public SendUi(Context context, Callback callback) { 19765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mContext = context; 19865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mCallback = callback; 1995438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics = new DisplayMetrics(); 2015438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix = new Matrix(); 20265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 20365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); 2040c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 2055438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay = mWindowManager.getDefaultDisplay(); 2065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 20765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mLayoutInflater = (LayoutInflater) 20865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout = mLayoutInflater.inflate(R.layout.screenshot, null); 210f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 2115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.screenshot); 2125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout.setFocusable(true); 2135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 214be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint = (TextView) mScreenshotLayout.findViewById(R.id.calltoaction); 2151a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry = (TextView) mScreenshotLayout.findViewById(R.id.retrytext); 2161a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer = (ImageView) mScreenshotLayout.findViewById(R.id.blacklayer); 217217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView = (TextureView) mScreenshotLayout.findViewById(R.id.fireflies); 218217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView.setSurfaceTextureListener(this); 219217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 2200c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // We're only allowed to use hardware acceleration if 2210c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // isHighEndGfx() returns true - otherwise, we're too limited 2220c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // on resources to do it. 223525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mHardwareAccelerated = ActivityManager.isHighEndGfx(); 2240c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen int hwAccelerationFlags = mHardwareAccelerated ? 225f7966d1dadff2d78f01bbdb134e8252b53343179Dianne Hackborn WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED : 0; 2260c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 2275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 2280c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen ViewGroup.LayoutParams.MATCH_PARENT, 0, 0, 2290c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 2305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly WindowManager.LayoutParams.FLAG_FULLSCREEN 23165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales | hwAccelerationFlags 23265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, 2335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PixelFormat.OPAQUE); 234525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mWindowLayoutParams.privateFlags |= 235525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 2365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams.token = new Binder(); 2375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 238f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator = new TimeAnimator(); 239f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.setTimeListener(this); 240f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 2415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preX = PropertyValuesHolder.ofFloat("scaleX", PRE_SCREENSHOT_SCALE); 2425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preY = PropertyValuesHolder.ofFloat("scaleY", PRE_SCREENSHOT_SCALE); 2435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, preX, preY); 24469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mPreAnimator.setInterpolator(new DecelerateInterpolator()); 2455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.setDuration(PRE_DURATION_MS); 2465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.addListener(this); 2475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 248f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", SEND_SCREENSHOT_SCALE); 249f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", SEND_SCREENSHOT_SCALE); 25065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", 25165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[]{1.0f, 0.0f}); 2524dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 253217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, postY); 254674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mSlowSendAnimator.setInterpolator(new DecelerateInterpolator()); 255217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.setDuration(SLOW_SEND_DURATION_MS); 25669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 257f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, 2584dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen postY, alphaDown); 259f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.setInterpolator(new DecelerateInterpolator()); 260f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.setDuration(FAST_SEND_DURATION_MS); 261f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.addListener(this); 26269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 26365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", SCALE_UP_SCREENSHOT_SCALE); 26465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", SCALE_UP_SCREENSHOT_SCALE); 2654dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 26665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mScaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, scaleUpX, scaleUpY); 267674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setInterpolator(new DecelerateInterpolator()); 26869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.setDuration(SCALE_UP_DURATION_MS); 26969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.addListener(this); 27069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 271674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 1.0f); 272674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, fadeIn); 273674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 274674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setDuration(FADE_IN_DURATION_MS); 275674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setStartDelay(FADE_IN_START_DELAY_MS); 276674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.addListener(this); 277674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 278be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", TEXT_HINT_ALPHA_RANGE); 279be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextHint, alphaUp); 280be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setInterpolator(null); 281be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setDuration(TEXT_HINT_ALPHA_DURATION_MS); 282674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mHintAnimator.setStartDelay(TEXT_HINT_ALPHA_START_DELAY_MS); 283be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 2841a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen alphaDown = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_DOWN_RANGE); 2851a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaDown); 2861a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.setInterpolator(new DecelerateInterpolator()); 2871a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.setDuration(400); 2881a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 2891a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen alphaUp = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_UP_RANGE); 2901a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaUp); 2911a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.setInterpolator(new DecelerateInterpolator()); 2921a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.setDuration(200); 2931a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 29469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet = new AnimatorSet(); 295f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSuccessAnimatorSet.playSequentially(mFastSendAnimator, mFadeInAnimator); 2965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2979340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen // Create a Window with a Decor view; creating a window allows us to get callbacks 2989340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen // on key events (which require a decor view to be dispatched). 29965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mContext.setTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen); 300f42c2eba6ba6e6dae07ea617ab1be7f6f18f220dJorim Jaggi Window window = new PhoneWindow(mContext); 3019340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen window.setCallback(this); 3029340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen window.requestFeature(Window.FEATURE_NO_TITLE); 3039340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mDecor = window.getDecorView(); 3049340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen window.setContentView(mScreenshotLayout, mWindowLayoutParams); 3059340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 306f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mHardwareAccelerated) { 30765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mFireflyRenderer = new FireflyRenderer(context); 308f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else { 309f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderer = null; 310f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 31157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_IDLE; 3125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void takeScreenshot() { 31557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // There's no point in taking the screenshot if 31657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // we're still finishing the previous animation. 3179340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mState >= STATE_W4_TOUCH) { 31857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen return; 31957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 320595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_SCREENSHOT; 32157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen new ScreenshotTask().execute(); 3225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 32469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show pre-send animation */ 3259340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void showPreSend(boolean promptToNfcTap) { 326595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen switch (mState) { 327595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_IDLE: 328595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected showPreSend() in STATE_IDLE"); 329595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 330595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT: 331595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Still waiting for screenshot, store request in state 332595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // and wait for screenshot completion. 3339340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (promptToNfcTap) { 3349340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState = STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED; 3359340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else { 3369340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState = STATE_W4_SCREENSHOT_PRESEND_REQUESTED; 3379340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 338595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 339595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_REQUESTED: 3409340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED: 341595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected showPreSend() in STATE_W4_SCREENSHOT_PRESEND_REQUESTED"); 342595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 343595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_PRESEND: 344595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Expected path, continue below 345595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen break; 346595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen default: 347595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected showPreSend() in state " + Integer.toString(mState)); 348595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 34957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 35090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Update display metrics 35190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mDisplay.getRealMetrics(mDisplayMetrics); 35290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 35365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 35490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 35590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 3561a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setVisibility(View.GONE); 3571a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setAlpha(0f); 358595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mScreenshotLayout.setOnTouchListener(this); 3595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView.setImageBitmap(mScreenshotBitmap); 3600c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setTranslationX(0f); 3610c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setAlpha(1.0f); 36290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotView.setPadding(0, statusBarHeight, 0, 0); 36369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 36490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotLayout.requestFocus(); 36569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 3669340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (promptToNfcTap) { 36765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mTextHint.setText(mContext.getResources().getString(R.string.ask_nfc_tap)); 3689340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else { 36965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mTextHint.setText(mContext.getResources().getString(R.string.touch)); 3709340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 371e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setAlpha(0.0f); 372e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setVisibility(View.VISIBLE); 373e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mHintAnimator.start(); 374be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 37569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Lock the orientation. 37669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // The orientation from the configuration does not specify whether 37769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // the orientation is reverse or not (ie landscape or reverse landscape). 37869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // So we have to use SENSOR_LANDSCAPE or SENSOR_PORTRAIT to make sure 37969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // we lock in portrait / landscape and have the sensor determine 38069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // which way is up. 38165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales int orientation = mContext.getResources().getConfiguration().orientation; 38269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 38369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen switch (orientation) { 38469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_LANDSCAPE: 38569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 38669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; 38769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 38869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_PORTRAIT: 38969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 39069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 39169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 39269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen default: 39369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 39469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 39569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 39669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 39769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 3989340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mWindowManager.addView(mDecor, mWindowLayoutParams); 3990c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // Disable statusbar pull-down 4000c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND); 4010c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 402a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen mToastString = null; 403f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 404f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mHardwareAccelerated) { 405f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mPreAnimator.start(); 406f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } // else, we will start the animation once we get the hardware surface 4079340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState = promptToNfcTap ? STATE_W4_NFC_TAP : STATE_W4_TOUCH; 40869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 4095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 41069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show starting send animation */ 41169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen public void showStartSend() { 41257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen if (mState < STATE_SENDING) return; 413217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 4141a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry.setVisibility(View.GONE); 415f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Update the starting scale - touchscreen-mashers may trigger 416f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // this before the pre-animation completes. 41790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen float currentScale = mScreenshotView.getScaleX(); 41865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", 41965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 42065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", 42165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 422217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 423f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSlowSendAnimator.setValues(postX, postY); 4241a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 4251a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen float currentAlpha = mBlackLayer.getAlpha(); 4261a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen if (mBlackLayer.isShown() && currentAlpha > 0.0f) { 42765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", 42865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentAlpha, 0.0f}); 4291a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.setValues(alphaDown); 4301a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.start(); 4311a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 432f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSlowSendAnimator.start(); 43369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 43469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 435a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen public void finishAndToast(int finishMode, String toast) { 436a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen mToastString = toast; 437a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen 438a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen finish(finishMode); 439a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen } 440a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen 44169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Return to initial state */ 4420c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen public void finish(int finishMode) { 443595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen switch (mState) { 444595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_IDLE: 445595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 446595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT: 447595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_REQUESTED: 4489340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen case STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED: 449595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Screenshot is still being captured on a separate thread. 450595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Update state, and stop everything when the capture is done. 451595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_SCREENSHOT_THEN_STOP; 452595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 453595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_SCREENSHOT_THEN_STOP: 454595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Unexpected call to finish() in STATE_W4_SCREENSHOT_THEN_STOP"); 455595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 456595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen case STATE_W4_PRESEND: 457595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // We didn't build up any animation state yet, but 458595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // did store the bitmap. Clear out the bitmap, reset 459595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // state and bail. 460595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mScreenshotBitmap = null; 461595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_IDLE; 462595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen return; 463595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen default: 464595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // We've started animations and attached a view; tear stuff down below. 465595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen break; 466595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } 467f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 468f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Stop rendering the fireflies 469f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mFireflyRenderer != null) { 470f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderer.stop(); 47169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 472f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 473be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint.setVisibility(View.GONE); 4741a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry.setVisibility(View.GONE); 475f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 476f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float currentScale = mScreenshotView.getScaleX(); 477f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float currentAlpha = mScreenshotView.getAlpha(); 478f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 479f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (finishMode == FINISH_SCALE_UP) { 4801a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setVisibility(View.GONE); 481674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", 48265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 1.0f}); 483674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", 48465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 1.0f}); 485674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpAlpha = PropertyValuesHolder.ofFloat("alpha", 48665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentAlpha, 1.0f}); 487f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mScaleUpAnimator.setValues(scaleUpX, scaleUpY, scaleUpAlpha); 488f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 4890c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScaleUpAnimator.start(); 490f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (finishMode == FINISH_SEND_SUCCESS){ 491f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Modify the fast send parameters to match the current scale 492f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", 49365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 494f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", 49565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentScale, 0.0f}); 496f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 49765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {currentAlpha, 0.0f}); 498f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.setValues(postX, postY, alpha); 499f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 500f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Reset the fadeIn parameters to start from alpha 1 501f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 50265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {0.0f, 1.0f}); 503f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFadeInAnimator.setValues(fadeIn); 504f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 505f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSlowSendAnimator.cancel(); 506f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSuccessAnimatorSet.start(); 5070c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen } 50857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_COMPLETE; 5095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 511595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen void dismiss() { 5129340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mState < STATE_W4_TOUCH) return; 51357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // Immediately set to IDLE, to prevent .cancel() calls 5144e0ab3174beafb4915388d8c11286a48e362ed7cMartijn Coenen // below from immediately calling into dismiss() again. 51557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen // (They can do so on the same thread). 51657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_IDLE; 517f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = null; 518f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.cancel(); 5195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.cancel(); 520217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.cancel(); 521f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFastSendAnimator.cancel(); 52269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet.cancel(); 52369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.cancel(); 5241a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.cancel(); 5251a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.cancel(); 5269340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mWindowManager.removeView(mDecor); 5270c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); 52857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mScreenshotBitmap = null; 529a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen if (mToastString != null) { 53065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales Toast.makeText(mContext, mToastString, Toast.LENGTH_LONG).show(); 531a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen } 532a3715d12aeba988c1104726e935462ea4f39eca7Martijn Coenen mToastString = null; 5335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 5355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 5365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * @return the current display rotation in degrees 5375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 5385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly static float getDegreesForRotation(int value) { 5395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly switch (value) { 5405438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_90: 5415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 90f; 5425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_180: 5435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 180f; 5445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_270: 5455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 270f; 5465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 0f; 5485438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 5495438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 55057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen final class ScreenshotTask extends AsyncTask<Void, Void, Bitmap> { 55157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 55257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen protected Bitmap doInBackground(Void... params) { 55357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen return createScreenshot(); 55457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 55557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 55657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 55757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen protected void onPostExecute(Bitmap result) { 558595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen if (mState == STATE_W4_SCREENSHOT) { 559595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Screenshot done, wait for request to start preSend anim 560ddefd2afcd6b09c3a48db4b2f69377dbc3a8a282Martijn Coenen mScreenshotBitmap = result; 561595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_PRESEND; 562595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } else if (mState == STATE_W4_SCREENSHOT_THEN_STOP) { 563595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // We were asked to finish, move to idle state and exit 564595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_IDLE; 5659340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else if (mState == STATE_W4_SCREENSHOT_PRESEND_REQUESTED || 5669340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mState == STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED) { 567595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen if (result != null) { 568595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mScreenshotBitmap = result; 5699340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen boolean requestTap = (mState == STATE_W4_SCREENSHOT_PRESEND_NFC_TAP_REQUESTED); 570595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_W4_PRESEND; 5719340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen showPreSend(requestTap); 572595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } else { 573595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // Failed to take screenshot; reset state to idle 574595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen // and don't do anything 575595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Failed to create screenshot"); 576595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen mState = STATE_IDLE; 577595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } 578595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen } else { 579595ab7e9788f61125fa14d1ff2768f995ac7b7e7Martijn Coenen Log.e(TAG, "Invalid state on screenshot completion: " + Integer.toString(mState)); 58057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 58157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 58265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales }; 58357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 5845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 5855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Returns a screenshot of the current display contents. 5865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 5875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap createScreenshot() { 5885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // We need to orient the screenshot correctly (and the Surface api seems to 5895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // take screenshots only in the natural orientation of the device :!) 5905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay.getRealMetrics(mDisplayMetrics); 59165ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales boolean hasNavBar = mContext.getResources().getBoolean( 592e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.bool.config_showNavigationBar); 5930c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 5945443a8f5b786bfc03633ea5821d95dffc856e3e8Martijn Coenen float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels}; 5955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly float degrees = getDegreesForRotation(mDisplay.getRotation()); 59665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 59790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 598e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen 59990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Navbar has different sizes, depending on orientation 60065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int navBarHeight = hasNavBar ? mContext.getResources().getDimensionPixelSize( 601e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.dimen.navigation_bar_height) : 0; 60265ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int navBarHeightLandscape = hasNavBar ? mContext.getResources().getDimensionPixelSize( 603525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project com.android.internal.R.dimen.navigation_bar_height_landscape) : 0; 604525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 60565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales final int navBarWidth = hasNavBar ? mContext.getResources().getDimensionPixelSize( 606e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.dimen.navigation_bar_width) : 0; 60790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 6085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly boolean requiresRotation = (degrees > 0); 6095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 6105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Get the dimensions of the device in its native orientation 6115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.reset(); 6125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.preRotate(-degrees); 6135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.mapPoints(dims); 6145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[0] = Math.abs(dims[0]); 6155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[1] = Math.abs(dims[1]); 6165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 61882792d9a73138f209d1f46f156604c4c65f69c0bMathias Agopian Bitmap bitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]); 6195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Bail if we couldn't take the screenshot 6205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (bitmap == null) { 6215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return null; 6225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 6255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Rotate the screenshot to the current orientation 6265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, 6275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); 6285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Canvas c = new Canvas(ss); 6295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(ss.getWidth() / 2, ss.getHeight() / 2); 6305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.rotate(360f - degrees); 6315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(-dims[0] / 2, -dims[1] / 2); 6325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.drawBitmap(bitmap, 0, 0, null); 6335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly bitmap = ss; 6355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 63790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // TODO this is somewhat device-specific; need generic solution. 63890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Crop off the status bar and the nav bar 63990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait: 0, statusBarHeight, width, height - status - nav 64090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Landscape: 0, statusBarHeight, width - navBar, height - status 64190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newLeft = 0; 64290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newTop = statusBarHeight; 64390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newWidth = bitmap.getWidth(); 64490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newHeight = bitmap.getHeight(); 645525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project float smallestWidth = (float)Math.min(newWidth, newHeight); 646525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project float smallestWidthDp = smallestWidth / (mDisplayMetrics.densityDpi / 160f); 64790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen if (bitmap.getWidth() < bitmap.getHeight()) { 64890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait mode: status bar is at the top, navbar bottom, width unchanged 64990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newHeight = bitmap.getHeight() - statusBarHeight - navBarHeight; 65090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } else { 651525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Landscape mode: status bar is at the top 652525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Navbar: bottom on >599dp width devices, otherwise to the side 653525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (smallestWidthDp > 599) { 654525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project newHeight = bitmap.getHeight() - statusBarHeight - navBarHeightLandscape; 655525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else { 656525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project newHeight = bitmap.getHeight() - statusBarHeight; 657525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project newWidth = bitmap.getWidth() - navBarWidth; 658525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 65990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } 66090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen bitmap = Bitmap.createBitmap(bitmap, newLeft, newTop, newWidth, newHeight); 66190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 6625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return bitmap; 6635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationStart(Animator animation) { } 6675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationEnd(Animator animation) { 6700c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen if (animation == mScaleUpAnimator || animation == mSuccessAnimatorSet || 671f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen animation == mFadeInAnimator) { 672f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // These all indicate the end of the animation 6735438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dismiss(); 674f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (animation == mFastSendAnimator) { 675f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // After sending is done and we've faded out, reset the scale to 1 6764dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen // so we can fade it back in. 6774dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleX(1.0f); 6784dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleY(1.0f); 679f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (animation == mPreAnimator) { 6809340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mHardwareAccelerated && (mState == STATE_W4_TOUCH || mState == STATE_W4_NFC_TAP)) { 681f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderer.start(mSurface, mSurfaceWidth, mSurfaceHeight); 682f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 6835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 6855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationCancel(Animator animation) { } 6885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 6905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationRepeat(Animator animation) { } 691b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly 692b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly @Override 693f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { 694f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // This gets called on animation vsync 695f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (++mRenderedFrames < 4) { 696f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // For the first 3 frames, call invalidate(); this calls eglSwapBuffers 697f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // on the surface, which will allocate large buffers the first three calls 698f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // as Android uses triple buffering. 699f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mScreenshotLayout.invalidate(); 700f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else { 701f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Buffers should be allocated, start the real animation 702f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.cancel(); 703f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mPreAnimator.start(); 704f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 705f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 706f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 707f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen @Override 708b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly public boolean onTouch(View v, MotionEvent event) { 7099340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen if (mState != STATE_W4_TOUCH) { 710b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return false; 711b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 71257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mState = STATE_SENDING; 71369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Ignore future touches 71469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScreenshotView.setOnTouchListener(null); 71569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 716f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Cancel any ongoing animations 717f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.cancel(); 718f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mPreAnimator.cancel(); 719f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 72065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mCallback.onSendConfirmed(); 721b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return true; 722b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 723217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 724217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 725217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 72657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen if (mHardwareAccelerated && mState < STATE_COMPLETE) { 727f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mRenderedFrames = 0; 728f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 729f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFrameCounterAnimator.start(); 730f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = surface; 731f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurfaceWidth = width; 732f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurfaceHeight = height; 733217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 734217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 735217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 736217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 737217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 738217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Since we've disabled orientation changes, we can safely ignore this 739217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 740217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 741217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 742217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 743f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = null; 744f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 745217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen return true; 746217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 747217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 748217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 749f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void onSurfaceTextureUpdated(SurfaceTexture surface) { } 750f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 7511a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen public void showSendHint() { 7521a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen if (mAlphaDownAnimator.isRunning()) { 7531a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaDownAnimator.cancel(); 7541a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 7551a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen if (mSlowSendAnimator.isRunning()) { 7561a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mSlowSendAnimator.cancel(); 7571a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 7581a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setScaleX(mScreenshotView.getScaleX()); 7591a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setScaleY(mScreenshotView.getScaleY()); 7601a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mBlackLayer.setVisibility(View.VISIBLE); 7611a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextHint.setVisibility(View.GONE); 7621a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 76365ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mTextRetry.setText(mContext.getResources().getString(R.string.beam_try_again)); 7641a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mTextRetry.setVisibility(View.VISIBLE); 7651a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen 7661a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", 76765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales new float[] {mBlackLayer.getAlpha(), 0.9f}); 7681a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.setValues(alphaUp); 7691a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen mAlphaUpAnimator.start(); 7701a158c7f354d1e1b031fba88928dbaa022e0d0dfMartijn Coenen } 7719340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7729340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7739340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchKeyEvent(KeyEvent event) { 77427382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen int keyCode = event.getKeyCode(); 77527382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen if (keyCode == KeyEvent.KEYCODE_BACK) { 77665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales mCallback.onCanceled(); 77727382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen return true; 77827382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || 77927382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 78027382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen // Treat as if it's a touch event 78127382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen return onTouch(mScreenshotView, null); 78227382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen } else { 78327382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen return false; 78427382be352460d4d73fffcebe364e71a4a6e4e75Martijn Coenen } 7859340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7869340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7879340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7889340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7899340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 7909340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7919340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7929340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7939340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchTouchEvent(MotionEvent event) { 7949340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return mScreenshotLayout.dispatchTouchEvent(event); 7959340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 7969340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 7979340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 7989340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchTrackballEvent(MotionEvent event) { 7999340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8009340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8019340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8029340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8039340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchGenericMotionEvent(MotionEvent event) { 8049340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8059340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8069340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8079340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8089340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 8099340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8109340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8119340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8129340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8139340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public View onCreatePanelView(int featureId) { 8149340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return null; 8159340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8169340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8179340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8189340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onCreatePanelMenu(int featureId, Menu menu) { 8199340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8209340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8219340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8229340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8239340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onPreparePanel(int featureId, View view, Menu menu) { 8249340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8259340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8269340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8279340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8289340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onMenuOpened(int featureId, Menu menu) { 8299340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8309340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8319340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8329340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8339340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onMenuItemSelected(int featureId, MenuItem item) { 8349340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8359340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8369340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8379340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8389340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onWindowAttributesChanged(LayoutParams attrs) { 8399340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8409340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8419340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8429340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onContentChanged() { 8439340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8449340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8459340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8469340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onWindowFocusChanged(boolean hasFocus) { 8479340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8489340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8499340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8509340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onAttachedToWindow() { 8519340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8529340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8539340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8549340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8559340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onDetachedFromWindow() { 8569340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8579340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8589340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8599340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onPanelClosed(int featureId, Menu menu) { 8609340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8619340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8629340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8639340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 86486bd05f00c88427e988aa57c0fbbddcb7bd278c6Tim Kilbourn public boolean onSearchRequested(SearchEvent searchEvent) { 86586bd05f00c88427e988aa57c0fbbddcb7bd278c6Tim Kilbourn return onSearchRequested(); 86686bd05f00c88427e988aa57c0fbbddcb7bd278c6Tim Kilbourn } 86786bd05f00c88427e988aa57c0fbbddcb7bd278c6Tim Kilbourn 86886bd05f00c88427e988aa57c0fbbddcb7bd278c6Tim Kilbourn @Override 8699340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public boolean onSearchRequested() { 8709340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return false; 8719340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8729340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8739340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8749340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public ActionMode onWindowStartingActionMode( 8759340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen android.view.ActionMode.Callback callback) { 8769340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen return null; 8779340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8789340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 879e5231ecfada2ade90483dc48ff188fc2082f616bClara Bayarri public ActionMode onWindowStartingActionMode( 880e5231ecfada2ade90483dc48ff188fc2082f616bClara Bayarri android.view.ActionMode.Callback callback, int type) { 881e5231ecfada2ade90483dc48ff188fc2082f616bClara Bayarri return null; 882e5231ecfada2ade90483dc48ff188fc2082f616bClara Bayarri } 883e5231ecfada2ade90483dc48ff188fc2082f616bClara Bayarri 8849340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8859340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onActionModeStarted(ActionMode mode) { 8869340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8879340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8889340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 8899340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void onActionModeFinished(ActionMode mode) { 8909340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly} 892