SendUi.java revision 4dd3c020b434aec0ccca030afeb57a861bc9a2f3
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 195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport com.android.nfc3.R; 205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.Animator; 2269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.animation.AnimatorSet; 235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.ObjectAnimator; 245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.PropertyValuesHolder; 250c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.ActivityManager; 260c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.StatusBarManager; 275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.content.Context; 2869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.pm.ActivityInfo; 2969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.res.Configuration; 305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Bitmap; 315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Canvas; 325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Matrix; 335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.PixelFormat; 34217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.graphics.SurfaceTexture; 355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.os.Binder; 365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.util.DisplayMetrics; 370c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.util.Log; 385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Display; 395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.LayoutInflater; 40b2112cff553c3b6658440bf06060c7a08f82df5cNick Pellyimport android.view.MotionEvent; 415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Surface; 42217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.view.TextureView; 435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.View; 445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.ViewGroup; 455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.WindowManager; 460c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.view.animation.AccelerateDecelerateInterpolator; 4769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.view.animation.AccelerateInterpolator; 4869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.view.animation.DecelerateInterpolator; 495438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.widget.ImageView; 50be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenenimport android.widget.TextView; 515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/** 535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * All methods must be called on UI thread 545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 55217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenpublic class SendUi implements Animator.AnimatorListener, View.OnTouchListener, 56217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen TextureView.SurfaceTextureListener { 570c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen private static final String LOG_TAG = "SendUI"; 585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 5969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float INTERMEDIATE_SCALE = 0.6f; 605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 6169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] PRE_SCREENSHOT_SCALE = {1.0f, INTERMEDIATE_SCALE}; 62674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int PRE_DURATION_MS = 350; 6369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 64674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final float[] CLONE_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 0.2f}; 65674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int SLOW_SEND_DURATION_MS = 8000; // Stretch out sending over 8s 66674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FAST_CLONE_DURATION_MS = 350; 6769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 6869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] SCALE_UP_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 1.0f}; 6969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final int SCALE_UP_DURATION_MS = 300; 705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 71674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_DURATION_MS = 250; 72674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_START_DELAY_MS = 350; 73674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 740c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int SLIDE_OUT_DURATION_MS = 300; 750c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 76be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final float[] TEXT_HINT_ALPHA_RANGE = {0.0f, 1.0f}; 77be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final int TEXT_HINT_ALPHA_DURATION_MS = 500; 78674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int TEXT_HINT_ALPHA_START_DELAY_MS = 300; 79be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 80674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final float[] BACKGROUND_SCALE_RANGE = {2.0f, 1.0f}; 81217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen static final int BACKGROUND_SCALE_DURATION_MS = 5000; 82217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 830c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int FINISH_SCALE_UP = 0; 840c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int FINISH_SLIDE_OUT = 1; 850c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // all members are only used on UI thread 875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final WindowManager mWindowManager; 885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Context mContext; 895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Display mDisplay; 905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final DisplayMetrics mDisplayMetrics; 915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Matrix mDisplayMatrix; 925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final WindowManager.LayoutParams mWindowLayoutParams; 935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final LayoutInflater mLayoutInflater; 940c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen final StatusBarManager mStatusBarManager; 955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final View mScreenshotLayout; 965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final ImageView mScreenshotView; 97217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen final ImageView mBackgroundImage; 98217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen final TextureView mTextureView; 99be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen final TextView mTextHint; 1005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Callback mCallback; 1015438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final ObjectAnimator mPreAnimator; 102217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen final ObjectAnimator mSlowSendAnimator; 10369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen final ObjectAnimator mFastCloneAnimator; 104674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely final ObjectAnimator mFadeInAnimator; 105be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen final ObjectAnimator mHintAnimator; 10669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen final AnimatorSet mSuccessAnimatorSet; 107217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen final ObjectAnimator mBackgroundAnimator; 1080c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen final boolean mHardwareAccelerated; 1095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap mScreenshotBitmap; 1110c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen ObjectAnimator mSlideoutAnimator; 112674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely ObjectAnimator mScaleUpAnimator; 113217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen FireflyRenderThread mFireflyRenderThread; 1140c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly boolean mAttached; 1165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly interface Callback { 118b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly public void onSendConfirmed(); 1195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 1205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public SendUi(Context context, Callback callback) { 1225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mContext = context; 1235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mCallback = callback; 1245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics = new DisplayMetrics(); 1265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix = new Matrix(); 1275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 1280c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); 1290c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay = mWindowManager.getDefaultDisplay(); 1315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mLayoutInflater = (LayoutInflater) 1335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 1345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout = mLayoutInflater.inflate(R.layout.screenshot, null); 1355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.screenshot); 1365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout.setFocusable(true); 1375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 138be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint = (TextView) mScreenshotLayout.findViewById(R.id.calltoaction); 1390c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 140217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView = (TextureView) mScreenshotLayout.findViewById(R.id.fireflies); 141217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView.setSurfaceTextureListener(this); 142217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 143217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mBackgroundImage = (ImageView) mScreenshotLayout.findViewById(R.id.back); 1440c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // We're only allowed to use hardware acceleration if 1450c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // isHighEndGfx() returns true - otherwise, we're too limited 1460c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // on resources to do it. 1470c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mHardwareAccelerated = ActivityManager.isHighEndGfx(mDisplay); 1480c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen int hwAccelerationFlags = mHardwareAccelerated ? 149f7966d1dadff2d78f01bbdb134e8252b53343179Dianne Hackborn WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED : 0; 1500c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 151217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (!mHardwareAccelerated) { 152217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Only show background in case we're not hw-accelerated 153217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mBackgroundImage.setVisibility(View.VISIBLE); 154217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 155217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 1565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1570c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen ViewGroup.LayoutParams.MATCH_PARENT, 0, 0, 1580c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 1595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly WindowManager.LayoutParams.FLAG_FULLSCREEN 1600c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen | hwAccelerationFlags 1615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING 162b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, 1635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PixelFormat.OPAQUE); 1645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams.token = new Binder(); 1655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preX = PropertyValuesHolder.ofFloat("scaleX", PRE_SCREENSHOT_SCALE); 1675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preY = PropertyValuesHolder.ofFloat("scaleY", PRE_SCREENSHOT_SCALE); 1685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, preX, preY); 16969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mPreAnimator.setInterpolator(new DecelerateInterpolator()); 1705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.setDuration(PRE_DURATION_MS); 1715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.addListener(this); 1725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 17369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", CLONE_SCREENSHOT_SCALE); 17469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", CLONE_SCREENSHOT_SCALE); 1754dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", 1764dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen new float[]{1.0f, 0.0f}); 1774dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 178217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, postY); 179674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mSlowSendAnimator.setInterpolator(new DecelerateInterpolator()); 180217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.setDuration(SLOW_SEND_DURATION_MS); 18169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 1824dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mFastCloneAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, 1834dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen postY, alphaDown); 184674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFastCloneAnimator.setInterpolator(new DecelerateInterpolator()); 18569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mFastCloneAnimator.setDuration(FAST_CLONE_DURATION_MS); 1864dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mFastCloneAnimator.addListener(this); 18769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 18869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", SCALE_UP_SCREENSHOT_SCALE); 18969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", SCALE_UP_SCREENSHOT_SCALE); 1904dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 19169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, scaleUpX, scaleUpY); 192674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setInterpolator(new DecelerateInterpolator()); 19369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.setDuration(SCALE_UP_DURATION_MS); 19469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.addListener(this); 19569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 196674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 1.0f); 197674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, fadeIn); 198674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 199674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setDuration(FADE_IN_DURATION_MS); 200674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setStartDelay(FADE_IN_START_DELAY_MS); 201674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.addListener(this); 202674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 203be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", TEXT_HINT_ALPHA_RANGE); 204be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextHint, alphaUp); 205be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setInterpolator(null); 206be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setDuration(TEXT_HINT_ALPHA_DURATION_MS); 207674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mHintAnimator.setStartDelay(TEXT_HINT_ALPHA_START_DELAY_MS); 208be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 20969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet = new AnimatorSet(); 210674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mSuccessAnimatorSet.playSequentially(mFastCloneAnimator, mFadeInAnimator); 2115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 212217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen scaleUpX = PropertyValuesHolder.ofFloat("scaleX", BACKGROUND_SCALE_RANGE); 213217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen scaleUpY = PropertyValuesHolder.ofFloat("scaleY", BACKGROUND_SCALE_RANGE); 214217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mBackgroundAnimator = ObjectAnimator.ofPropertyValuesHolder(mBackgroundImage, scaleUpX, scaleUpY); 215217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mBackgroundAnimator.setInterpolator(new DecelerateInterpolator(2.0f)); 216217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mBackgroundAnimator.setDuration(BACKGROUND_SCALE_DURATION_MS); 217217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 2185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mAttached = false; 2195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 2205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void takeScreenshot() { 2225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotBitmap = createScreenshot(); 2235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 2245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 22569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show pre-send animation */ 226e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly public void showPreSend() { 22790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Update display metrics 22890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mDisplay.getRealMetrics(mDisplayMetrics); 22990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 23090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 23190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 23290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 2335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (mScreenshotBitmap == null || mAttached) { 2345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return; 2355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 23669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScreenshotView.setOnTouchListener(this); 2375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView.setImageBitmap(mScreenshotBitmap); 2380c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setTranslationX(0f); 2390c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setAlpha(1.0f); 24090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotView.setPadding(0, statusBarHeight, 0, 0); 24169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 24290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotLayout.requestFocus(); 24369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 244e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setAlpha(0.0f); 245e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setVisibility(View.VISIBLE); 246e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mHintAnimator.start(); 247be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 24869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Lock the orientation. 24969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // The orientation from the configuration does not specify whether 25069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // the orientation is reverse or not (ie landscape or reverse landscape). 25169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // So we have to use SENSOR_LANDSCAPE or SENSOR_PORTRAIT to make sure 25269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // we lock in portrait / landscape and have the sensor determine 25369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // which way is up. 25469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen int orientation = mContext.getResources().getConfiguration().orientation; 25569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 25669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen switch (orientation) { 25769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_LANDSCAPE: 25869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 25969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; 26069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 26169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_PORTRAIT: 26269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 26369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 26469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 26569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen default: 26669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 26769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 26869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 26969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 27069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 2715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams); 2720c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // Disable statusbar pull-down 2730c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND); 2740c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 2755438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mAttached = true; 2765438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.start(); 277217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 278217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (!mHardwareAccelerated) { 279217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mBackgroundAnimator.start(); 280217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 28169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 2825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 28369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show starting send animation */ 28469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen public void showStartSend() { 28569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen if (!mAttached) { 28669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen return; 28769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 288217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.start(); 2895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 2905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** Show post-send animation */ 2925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void showPostSend() { 2935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (!mAttached) { 2945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return; 2955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 29669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 297217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.cancel(); 298be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint.setVisibility(View.GONE); 29969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 300217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 30190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen float currentScale = mScreenshotView.getScaleX(); 302217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 303217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Modify the fast clone parameters to match the current scale 304217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", 305217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen new float[] {currentScale, 0.0f}); 306217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", 307217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen new float[] {currentScale, 0.0f}); 3084dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 3094dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen new float[] {1.0f, 0.0f}); 3104dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mFastCloneAnimator.setValues(postX, postY, alpha); 311674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 312674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely // Modify the fadeIn parameters to match the current scale 313674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 314674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {0.0f, 1.0f}); 315674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setValues(fadeIn); 316217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 317217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (mFireflyRenderThread != null) { 318217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.fadeOut(); 319217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 32069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 32169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet.start(); 32269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 32369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 32469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Return to initial state */ 3250c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen public void finish(int finishMode) { 32669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen if (!mAttached) { 32769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen return; 32869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 329be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint.setVisibility(View.GONE); 3300c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen if (finishMode == FINISH_SLIDE_OUT) { 3310c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen PropertyValuesHolder slideX = PropertyValuesHolder.ofFloat("translationX", 3320c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen new float[]{0.0f, mScreenshotView.getWidth()}); 3330c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, slideX); 3340c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.setInterpolator(new AccelerateInterpolator()); 3350c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.setDuration(SLIDE_OUT_DURATION_MS); 3360c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.addListener(this); 3370c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.start(); 3380c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen } else { 339674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely float currentScale = mScreenshotView.getScaleX(); 340674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely float currentAlpha = mScreenshotView.getAlpha(); 341674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", 342674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {currentScale, 1.0f}); 343674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", 344674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {currentScale, 1.0f}); 345674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpAlpha = PropertyValuesHolder.ofFloat("alpha", 346674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {currentAlpha, 1.0f}); 347674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, scaleUpX, scaleUpY, scaleUpAlpha); 348674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setInterpolator(new DecelerateInterpolator()); 349674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setDuration(SCALE_UP_DURATION_MS); 350674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.addListener(this); 3510c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScaleUpAnimator.start(); 3520c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen } 3535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3555438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void dismiss() { 3565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (!mAttached) { 3575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return; 3585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.cancel(); 360217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.cancel(); 36169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mFastCloneAnimator.cancel(); 36269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet.cancel(); 36369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.cancel(); 3645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowManager.removeView(mScreenshotLayout); 3650c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); 3665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mAttached = false; 3675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly releaseScreenshot(); 3685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void releaseScreenshot() { 3715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotBitmap = null; 3725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3735438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3745438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 3755438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * @return the current display rotation in degrees 3765438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 3775438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly static float getDegreesForRotation(int value) { 3785438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly switch (value) { 3795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_90: 3805438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 90f; 3815438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_180: 3825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 180f; 3835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_270: 3845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 270f; 3855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 0f; 3875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 3905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Returns a screenshot of the current display contents. 3915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 3925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap createScreenshot() { 3935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // We need to orient the screenshot correctly (and the Surface api seems to 3945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // take screenshots only in the natural orientation of the device :!) 3950c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 3965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay.getRealMetrics(mDisplayMetrics); 3970c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 3985438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels}; 3995438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly float degrees = getDegreesForRotation(mDisplay.getRotation()); 40090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 40190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 40290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Navbar has different sizes, depending on orientation 40390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen final int navBarHeight = mContext.getResources().getDimensionPixelSize( 40490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.navigation_bar_height); 40590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen final int navBarWidth = mContext.getResources().getDimensionPixelSize( 40690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.navigation_bar_width); 40790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 4085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly boolean requiresRotation = (degrees > 0); 4095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 4105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Get the dimensions of the device in its native orientation 4115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.reset(); 4125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.preRotate(-degrees); 4135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.mapPoints(dims); 4145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[0] = Math.abs(dims[0]); 4155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[1] = Math.abs(dims[1]); 4165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap bitmap = Surface.screenshot((int) dims[0], (int) dims[1]); 4195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Bail if we couldn't take the screenshot 4205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (bitmap == null) { 4215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return null; 4225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 42490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 4255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 4265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Rotate the screenshot to the current orientation 4275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, 4285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); 4295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Canvas c = new Canvas(ss); 4305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(ss.getWidth() / 2, ss.getHeight() / 2); 4315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.rotate(360f - degrees); 4325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(-dims[0] / 2, -dims[1] / 2); 4335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.drawBitmap(bitmap, 0, 0, null); 4345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly bitmap = ss; 4365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 43890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // TODO this is somewhat device-specific; need generic solution. 43990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Crop off the status bar and the nav bar 44090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait: 0, statusBarHeight, width, height - status - nav 44190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Landscape: 0, statusBarHeight, width - navBar, height - status 44290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newLeft = 0; 44390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newTop = statusBarHeight; 44490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newWidth = bitmap.getWidth(); 44590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newHeight = bitmap.getHeight(); 44690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen if (bitmap.getWidth() < bitmap.getHeight()) { 44790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait mode: status bar is at the top, navbar bottom, width unchanged 44890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newHeight = bitmap.getHeight() - statusBarHeight - navBarHeight; 44990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } else { 45090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Landscape mode: status bar is at the top, navbar right 45190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newHeight = bitmap.getHeight() - statusBarHeight; 45290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newWidth = bitmap.getWidth() - navBarWidth; 45390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } 45490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen bitmap = Bitmap.createBitmap(bitmap, newLeft, newTop, newWidth, newHeight); 45590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 4565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return bitmap; 4575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationStart(Animator animation) { } 4615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationEnd(Animator animation) { 4640c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen if (animation == mScaleUpAnimator || animation == mSuccessAnimatorSet || 465674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely animation == mSlideoutAnimator || animation == mFadeInAnimator) { 4665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dismiss(); 4674dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen } else if (animation == mFastCloneAnimator) { 4684dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen // After cloning is done and we've faded out, reset the scale to 1 4694dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen // so we can fade it back in. 4704dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleX(1.0f); 4714dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleY(1.0f); 4725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4735438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4745438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4755438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4765438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationCancel(Animator animation) { } 4775438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4785438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationRepeat(Animator animation) { } 480b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly 481b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly @Override 482b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly public boolean onTouch(View v, MotionEvent event) { 483b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly if (!mAttached) { 484b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return false; 485b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 48669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Ignore future touches 48769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScreenshotView.setOnTouchListener(null); 48869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 489b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly mPreAnimator.end(); 490b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly mCallback.onSendConfirmed(); 491b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return true; 492b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 493217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 494217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 495217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 496217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (mHardwareAccelerated) { 497217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread = new FireflyRenderThread(mContext, surface, width, height); 498217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.start(); 499217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 500217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 501217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 502217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 503217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 504217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Since we've disabled orientation changes, we can safely ignore this 505217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 506217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 507217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 508217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 509217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (mFireflyRenderThread != null) { 510217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.finish(); 511217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen try { 512217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.join(); 513217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } catch (InterruptedException e) { 514217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen Log.e(LOG_TAG, "Couldn't wait for FireflyRenderThread."); 515217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 516217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread = null; 517217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 518217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen return true; 519217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 520217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 521217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 522217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureUpdated(SurfaceTexture surface) { 523217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 5245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly} 525