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 android.animation.Animator; 2069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.animation.AnimatorSet; 215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.ObjectAnimator; 225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.PropertyValuesHolder; 230c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.ActivityManager; 240c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.app.StatusBarManager; 255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.content.Context; 2669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.pm.ActivityInfo; 2769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.content.res.Configuration; 285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Bitmap; 295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Canvas; 305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Matrix; 315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.PixelFormat; 32217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.graphics.SurfaceTexture; 335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.os.Binder; 345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.util.DisplayMetrics; 350c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.util.Log; 365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Display; 375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.LayoutInflater; 38b2112cff553c3b6658440bf06060c7a08f82df5cNick Pellyimport android.view.MotionEvent; 395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Surface; 40217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenimport android.view.TextureView; 415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.View; 425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.ViewGroup; 435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.WindowManager; 440c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenenimport android.view.animation.AccelerateDecelerateInterpolator; 4569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.view.animation.AccelerateInterpolator; 4669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenenimport android.view.animation.DecelerateInterpolator; 475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.widget.ImageView; 48be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenenimport android.widget.TextView; 495438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/** 515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * All methods must be called on UI thread 525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 53217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenenpublic class SendUi implements Animator.AnimatorListener, View.OnTouchListener, 54217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen TextureView.SurfaceTextureListener { 550c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen private static final String LOG_TAG = "SendUI"; 565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 5769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float INTERMEDIATE_SCALE = 0.6f; 585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 5969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] PRE_SCREENSHOT_SCALE = {1.0f, INTERMEDIATE_SCALE}; 60674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int PRE_DURATION_MS = 350; 6169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 62674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final float[] CLONE_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 0.2f}; 63674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int SLOW_SEND_DURATION_MS = 8000; // Stretch out sending over 8s 64674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FAST_CLONE_DURATION_MS = 350; 6569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 6669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final float[] SCALE_UP_SCREENSHOT_SCALE = {INTERMEDIATE_SCALE, 1.0f}; 6769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen static final int SCALE_UP_DURATION_MS = 300; 685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 69674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_DURATION_MS = 250; 70674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int FADE_IN_START_DELAY_MS = 350; 71674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 720c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int SLIDE_OUT_DURATION_MS = 300; 730c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 74be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final float[] TEXT_HINT_ALPHA_RANGE = {0.0f, 1.0f}; 75be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen static final int TEXT_HINT_ALPHA_DURATION_MS = 500; 76674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely static final int TEXT_HINT_ALPHA_START_DELAY_MS = 300; 77be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 780c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int FINISH_SCALE_UP = 0; 790c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen static final int FINISH_SLIDE_OUT = 1; 800c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 815438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // all members are only used on UI thread 825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final WindowManager mWindowManager; 835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Context mContext; 845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Display mDisplay; 855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final DisplayMetrics mDisplayMetrics; 865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Matrix mDisplayMatrix; 875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final WindowManager.LayoutParams mWindowLayoutParams; 885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final LayoutInflater mLayoutInflater; 890c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen final StatusBarManager mStatusBarManager; 905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final View mScreenshotLayout; 915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final ImageView mScreenshotView; 92217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen final TextureView mTextureView; 93be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen final TextView mTextHint; 945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final Callback mCallback; 955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly final ObjectAnimator mPreAnimator; 96217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen final ObjectAnimator mSlowSendAnimator; 9769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen final ObjectAnimator mFastCloneAnimator; 98674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely final ObjectAnimator mFadeInAnimator; 99be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen final ObjectAnimator mHintAnimator; 10069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen final AnimatorSet mSuccessAnimatorSet; 1010c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen final boolean mHardwareAccelerated; 1025438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap mScreenshotBitmap; 1040c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen ObjectAnimator mSlideoutAnimator; 105674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely ObjectAnimator mScaleUpAnimator; 106217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen FireflyRenderThread mFireflyRenderThread; 1070c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly boolean mAttached; 1095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly interface Callback { 111b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly public void onSendConfirmed(); 1125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 1135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public SendUi(Context context, Callback callback) { 1155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mContext = context; 1165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mCallback = callback; 1175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics = new DisplayMetrics(); 1195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix = new Matrix(); 1205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 1210c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE); 1220c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay = mWindowManager.getDefaultDisplay(); 1245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mLayoutInflater = (LayoutInflater) 1265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 1275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout = mLayoutInflater.inflate(R.layout.screenshot, null); 1285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.screenshot); 1295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotLayout.setFocusable(true); 1305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 131be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint = (TextView) mScreenshotLayout.findViewById(R.id.calltoaction); 1320c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 133217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView = (TextureView) mScreenshotLayout.findViewById(R.id.fireflies); 134217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mTextureView.setSurfaceTextureListener(this); 135217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 1360c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // We're only allowed to use hardware acceleration if 1370c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // isHighEndGfx() returns true - otherwise, we're too limited 1380c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // on resources to do it. 1390c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mHardwareAccelerated = ActivityManager.isHighEndGfx(mDisplay); 1400c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen int hwAccelerationFlags = mHardwareAccelerated ? 141f7966d1dadff2d78f01bbdb134e8252b53343179Dianne Hackborn WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED : 0; 1420c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 1435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1440c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen ViewGroup.LayoutParams.MATCH_PARENT, 0, 0, 1450c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 1465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly WindowManager.LayoutParams.FLAG_FULLSCREEN 1470c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen | hwAccelerationFlags 1485438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING 149b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, 1505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PixelFormat.OPAQUE); 1515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowLayoutParams.token = new Binder(); 1525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preX = PropertyValuesHolder.ofFloat("scaleX", PRE_SCREENSHOT_SCALE); 1545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly PropertyValuesHolder preY = PropertyValuesHolder.ofFloat("scaleY", PRE_SCREENSHOT_SCALE); 1555438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, preX, preY); 15669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mPreAnimator.setInterpolator(new DecelerateInterpolator()); 1575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.setDuration(PRE_DURATION_MS); 1585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.addListener(this); 1595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 16069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", CLONE_SCREENSHOT_SCALE); 16169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", CLONE_SCREENSHOT_SCALE); 1624dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", 1634dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen new float[]{1.0f, 0.0f}); 1644dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 165217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, postY); 166674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mSlowSendAnimator.setInterpolator(new DecelerateInterpolator()); 167217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.setDuration(SLOW_SEND_DURATION_MS); 16869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 1694dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mFastCloneAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, 1704dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen postY, alphaDown); 171674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFastCloneAnimator.setInterpolator(new DecelerateInterpolator()); 17269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mFastCloneAnimator.setDuration(FAST_CLONE_DURATION_MS); 1734dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mFastCloneAnimator.addListener(this); 17469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 17569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", SCALE_UP_SCREENSHOT_SCALE); 17669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", SCALE_UP_SCREENSHOT_SCALE); 1774dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen 17869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, scaleUpX, scaleUpY); 179674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setInterpolator(new DecelerateInterpolator()); 18069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.setDuration(SCALE_UP_DURATION_MS); 18169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.addListener(this); 18269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 183674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 1.0f); 184674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, fadeIn); 185674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 186674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setDuration(FADE_IN_DURATION_MS); 187674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setStartDelay(FADE_IN_START_DELAY_MS); 188674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.addListener(this); 189674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 190be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", TEXT_HINT_ALPHA_RANGE); 191be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextHint, alphaUp); 192be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setInterpolator(null); 193be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mHintAnimator.setDuration(TEXT_HINT_ALPHA_DURATION_MS); 194674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mHintAnimator.setStartDelay(TEXT_HINT_ALPHA_START_DELAY_MS); 195be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 19669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet = new AnimatorSet(); 197674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mSuccessAnimatorSet.playSequentially(mFastCloneAnimator, mFadeInAnimator); 1985438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 1995438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mAttached = false; 2005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 2015438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2025438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void takeScreenshot() { 2035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotBitmap = createScreenshot(); 2045438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 2055438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 20669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show pre-send animation */ 207e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly public void showPreSend() { 20890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Update display metrics 20990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mDisplay.getRealMetrics(mDisplayMetrics); 21090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 21190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 21290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 21390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 2145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (mScreenshotBitmap == null || mAttached) { 2155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return; 2165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 21769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScreenshotView.setOnTouchListener(this); 2185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotView.setImageBitmap(mScreenshotBitmap); 2190c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setTranslationX(0f); 2200c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScreenshotView.setAlpha(1.0f); 22190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotView.setPadding(0, statusBarHeight, 0, 0); 22269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 22390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen mScreenshotLayout.requestFocus(); 22469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 225e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setAlpha(0.0f); 226e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mTextHint.setVisibility(View.VISIBLE); 227e31749eae9b242d5019eb5cf5f09069d60df9f71Nick Pelly mHintAnimator.start(); 228be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen 22969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Lock the orientation. 23069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // The orientation from the configuration does not specify whether 23169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // the orientation is reverse or not (ie landscape or reverse landscape). 23269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // So we have to use SENSOR_LANDSCAPE or SENSOR_PORTRAIT to make sure 23369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // we lock in portrait / landscape and have the sensor determine 23469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // which way is up. 23569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen int orientation = mContext.getResources().getConfiguration().orientation; 23669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 23769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen switch (orientation) { 23869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_LANDSCAPE: 23969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 24069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; 24169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 24269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen case Configuration.ORIENTATION_PORTRAIT: 24369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 24469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 24569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 24669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen default: 24769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mWindowLayoutParams.screenOrientation = 24869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; 24969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen break; 25069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 25169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 2525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams); 2530c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen // Disable statusbar pull-down 2540c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND); 2550c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 2565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mAttached = true; 2575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.start(); 25869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 2595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 26069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Show starting send animation */ 26169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen public void showStartSend() { 26269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen if (!mAttached) { 26369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen return; 26469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 265217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.start(); 2665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 2675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 2685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** Show post-send animation */ 2695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void showPostSend() { 2705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (!mAttached) { 2715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return; 2725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 27369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 274217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.cancel(); 275be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint.setVisibility(View.GONE); 27669ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 277217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 27890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen float currentScale = mScreenshotView.getScaleX(); 279217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 280217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Modify the fast clone parameters to match the current scale 281217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", 282217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen new float[] {currentScale, 0.0f}); 283217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", 284217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen new float[] {currentScale, 0.0f}); 2854dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 2864dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen new float[] {1.0f, 0.0f}); 2874dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mFastCloneAnimator.setValues(postX, postY, alpha); 288674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely 289674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely // Modify the fadeIn parameters to match the current scale 290674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder fadeIn = PropertyValuesHolder.ofFloat("alpha", 291674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {0.0f, 1.0f}); 292674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mFadeInAnimator.setValues(fadeIn); 293217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 294217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (mFireflyRenderThread != null) { 295217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.fadeOut(); 296217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 29769ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 29869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet.start(); 29969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 30069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 30169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen /** Return to initial state */ 3020c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen public void finish(int finishMode) { 30369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen if (!mAttached) { 30469ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen return; 30569ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen } 306be7d37a1c6622c8907869fd30e9e6da73fd77290Martijn Coenen mTextHint.setVisibility(View.GONE); 3070c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen if (finishMode == FINISH_SLIDE_OUT) { 3080c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen PropertyValuesHolder slideX = PropertyValuesHolder.ofFloat("translationX", 3090c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen new float[]{0.0f, mScreenshotView.getWidth()}); 3100c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, slideX); 3110c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.setInterpolator(new AccelerateInterpolator()); 3120c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.setDuration(SLIDE_OUT_DURATION_MS); 3130c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.addListener(this); 3140c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mSlideoutAnimator.start(); 3150c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen } else { 316674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely float currentScale = mScreenshotView.getScaleX(); 317674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely float currentAlpha = mScreenshotView.getAlpha(); 318674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", 319674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {currentScale, 1.0f}); 320674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", 321674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {currentScale, 1.0f}); 322674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely PropertyValuesHolder scaleUpAlpha = PropertyValuesHolder.ofFloat("alpha", 323674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely new float[] {currentAlpha, 1.0f}); 324674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, scaleUpX, scaleUpY, scaleUpAlpha); 325674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setInterpolator(new DecelerateInterpolator()); 326674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.setDuration(SCALE_UP_DURATION_MS); 327674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely mScaleUpAnimator.addListener(this); 3280c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mScaleUpAnimator.start(); 3290c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen } 3305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void dismiss() { 3335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (!mAttached) { 3345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return; 3355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3364e0ab3174beafb4915388d8c11286a48e362ed7cMartijn Coenen // Immediately set to false, to prevent .cancel() calls 3374e0ab3174beafb4915388d8c11286a48e362ed7cMartijn Coenen // below from immediately calling into dismiss() again. 3384e0ab3174beafb4915388d8c11286a48e362ed7cMartijn Coenen mAttached = false; 3395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mPreAnimator.cancel(); 340217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mSlowSendAnimator.cancel(); 34169ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mFastCloneAnimator.cancel(); 34269ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mSuccessAnimatorSet.cancel(); 34369ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScaleUpAnimator.cancel(); 3445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mWindowManager.removeView(mScreenshotLayout); 3450c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); 3465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly releaseScreenshot(); 3475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3485438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3495438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void releaseScreenshot() { 3505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mScreenshotBitmap = null; 3515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 3545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * @return the current display rotation in degrees 3555438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 3565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly static float getDegreesForRotation(int value) { 3575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly switch (value) { 3585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_90: 3595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 90f; 3605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_180: 3615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 180f; 3625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly case Surface.ROTATION_270: 3635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 270f; 3645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return 0f; 3665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 3685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly /** 3695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Returns a screenshot of the current display contents. 3705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */ 3715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap createScreenshot() { 3725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // We need to orient the screenshot correctly (and the Surface api seems to 3735438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // take screenshots only in the natural orientation of the device :!) 3740c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 3755438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplay.getRealMetrics(mDisplayMetrics); 376e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen boolean hasNavBar = mContext.getResources().getBoolean( 377e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.bool.config_showNavigationBar); 3780c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen 3795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels}; 3805438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly float degrees = getDegreesForRotation(mDisplay.getRotation()); 38190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen final int statusBarHeight = mContext.getResources().getDimensionPixelSize( 38290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen com.android.internal.R.dimen.status_bar_height); 383e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen 38490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Navbar has different sizes, depending on orientation 385e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen final int navBarHeight = hasNavBar ? mContext.getResources().getDimensionPixelSize( 386e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.dimen.navigation_bar_height) : 0; 387e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen final int navBarWidth = hasNavBar ? mContext.getResources().getDimensionPixelSize( 388e3cfbec7045220294c172d55122daf55ab6cb058Martijn Coenen com.android.internal.R.dimen.navigation_bar_width) : 0; 38990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 3905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly boolean requiresRotation = (degrees > 0); 3915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 3925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Get the dimensions of the device in its native orientation 3935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.reset(); 3945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.preRotate(-degrees); 3955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMatrix.mapPoints(dims); 3965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[0] = Math.abs(dims[0]); 3975438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dims[1] = Math.abs(dims[1]); 3985438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 3995438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap bitmap = Surface.screenshot((int) dims[0], (int) dims[1]); 4015438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Bail if we couldn't take the screenshot 4025438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (bitmap == null) { 4035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return null; 4045438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4055438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 40690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 4075438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly if (requiresRotation) { 4085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly // Rotate the screenshot to the current orientation 4095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, 4105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); 4115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly Canvas c = new Canvas(ss); 4125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(ss.getWidth() / 2, ss.getHeight() / 2); 4135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.rotate(360f - degrees); 4145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.translate(-dims[0] / 2, -dims[1] / 2); 4155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly c.drawBitmap(bitmap, 0, 0, null); 4165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly bitmap = ss; 4185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 42090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // TODO this is somewhat device-specific; need generic solution. 42190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Crop off the status bar and the nav bar 42290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait: 0, statusBarHeight, width, height - status - nav 42390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Landscape: 0, statusBarHeight, width - navBar, height - status 42490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newLeft = 0; 42590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newTop = statusBarHeight; 42690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newWidth = bitmap.getWidth(); 42790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen int newHeight = bitmap.getHeight(); 42890e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen if (bitmap.getWidth() < bitmap.getHeight()) { 42990e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Portrait mode: status bar is at the top, navbar bottom, width unchanged 43090e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newHeight = bitmap.getHeight() - statusBarHeight - navBarHeight; 43190e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } else { 43290e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen // Landscape mode: status bar is at the top, navbar right 43390e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newHeight = bitmap.getHeight() - statusBarHeight; 43490e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen newWidth = bitmap.getWidth() - navBarWidth; 43590e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen } 43690e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen bitmap = Bitmap.createBitmap(bitmap, newLeft, newTop, newWidth, newHeight); 43790e1b000b385d7fa11481ddca4d61d6b425d7579Martijn Coenen 4385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly return bitmap; 4395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4405438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationStart(Animator animation) { } 4435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationEnd(Animator animation) { 4460c4fce176e6acb1a1a74e9248cf83eb0314490aaMartijn Coenen if (animation == mScaleUpAnimator || animation == mSuccessAnimatorSet || 447674cd01fd74b403a4625efbfd2743e179c3d9ecaBrandon Keely animation == mSlideoutAnimator || animation == mFadeInAnimator) { 4485438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly dismiss(); 4494dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen } else if (animation == mFastCloneAnimator) { 4504dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen // After cloning is done and we've faded out, reset the scale to 1 4514dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen // so we can fade it back in. 4524dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleX(1.0f); 4534dd3c020b434aec0ccca030afeb57a861bc9a2f3Martijn Coenen mScreenshotView.setScaleY(1.0f); 4545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4555438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly } 4565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationCancel(Animator animation) { } 4595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly 4605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly @Override 4615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly public void onAnimationRepeat(Animator animation) { } 462b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly 463b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly @Override 464b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly public boolean onTouch(View v, MotionEvent event) { 465b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly if (!mAttached) { 466b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return false; 467b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 46869ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen // Ignore future touches 46969ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen mScreenshotView.setOnTouchListener(null); 47069ca6627125c91c44b9e0d8bfa5df83281c2ebe1Martijn Coenen 471b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly mPreAnimator.end(); 472b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly mCallback.onSendConfirmed(); 473b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly return true; 474b2112cff553c3b6658440bf06060c7a08f82df5cNick Pelly } 475217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 476217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 477217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 478217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (mHardwareAccelerated) { 479217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread = new FireflyRenderThread(mContext, surface, width, height); 480217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.start(); 481217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 482217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 483217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 484217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 485217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 486217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen // Since we've disabled orientation changes, we can safely ignore this 487217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 488217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 489217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 490217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 491217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen if (mFireflyRenderThread != null) { 492217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.finish(); 493217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen try { 494217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread.join(); 495217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } catch (InterruptedException e) { 496217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen Log.e(LOG_TAG, "Couldn't wait for FireflyRenderThread."); 497217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 498217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen mFireflyRenderThread = null; 499217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 500217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen return true; 501217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 502217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen 503217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen @Override 504217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen public void onSurfaceTextureUpdated(SurfaceTexture surface) { 505217edd31f93c3917a8bb02420366b88d27c431c2Martijn Coenen } 5065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly} 507