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