OverlayDisplayWindow.java revision d5523dc7b7318f2774109dd30716ff7b74560e61
14ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown/*
24ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Copyright (C) 2012 The Android Open Source Project
34ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown *
44ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
54ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * you may not use this file except in compliance with the License.
64ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * You may obtain a copy of the License at
74ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown *
84ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
94ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown *
104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Unless required by applicable law or agreed to in writing, software
114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * See the License for the specific language governing permissions and
144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * limitations under the License.
154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown */
164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownpackage com.android.server.display;
184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
19cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport com.android.internal.util.DumpUtils;
20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.content.Context;
224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.graphics.SurfaceTexture;
234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.hardware.display.DisplayManager;
244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.util.Slog;
254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.Display;
264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.DisplayInfo;
274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.GestureDetector;
284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.Gravity;
294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.LayoutInflater;
304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.MotionEvent;
314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.ScaleGestureDetector;
324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.TextureView;
334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.View;
344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.WindowManager;
354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.TextureView.SurfaceTextureListener;
364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.widget.TextView;
374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport java.io.PrintWriter;
394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown/**
414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Manages an overlay window on behalf of {@link OverlayDisplayAdapter}.
424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * <p>
434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * This object must only be accessed on the UI thread.
444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * No locks are held by this object and locks must not be held while making called into it.
454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * </p>
464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown */
47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class OverlayDisplayWindow implements DumpUtils.Dump {
484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private static final String TAG = "OverlayDisplayWindow";
494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private static final boolean DEBUG = false;
504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float INITIAL_SCALE = 0.5f;
524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float MIN_SCALE = 0.3f;
534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float MAX_SCALE = 1.0f;
544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float WINDOW_ALPHA = 0.8f;
554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // When true, disables support for moving and resizing the overlay.
574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // The window is made non-touchable, which makes it possible to
584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // directly interact with the content underneath.
594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final boolean DISABLE_MOVE_AND_RESIZE = false;
604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Context mContext;
624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final String mName;
634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final int mWidth;
644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final int mHeight;
654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final int mDensityDpi;
664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final int mGravity;
674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Listener mListener;
684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final String mTitle;
694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayManager mDisplayManager;
714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final WindowManager mWindowManager;
724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Display mDefaultDisplay;
754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private View mWindowContent;
784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private WindowManager.LayoutParams mWindowParams;
794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private TextureView mTextureView;
804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private TextView mTitleTextView;
814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private GestureDetector mGestureDetector;
834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private ScaleGestureDetector mScaleGestureDetector;
844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean mWindowVisible;
864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mWindowX;
874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mWindowY;
884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mWindowScale;
894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveTranslationX;
914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveTranslationY;
924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveScale = 1.0f;
934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public OverlayDisplayWindow(Context context, String name,
954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            int width, int height, int densityDpi, int gravity, Listener listener) {
964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mContext = context;
974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mName = name;
984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWidth = width;
994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mHeight = height;
1004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDensityDpi = densityDpi;
1014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mGravity = gravity;
1024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mListener = listener;
1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitle = context.getResources().getString(
1044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.string.display_manager_overlay_display_title,
1054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mName, mWidth, mHeight, mDensityDpi);
1064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDisplayManager = (DisplayManager)context.getSystemService(
1084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Context.DISPLAY_SERVICE);
1094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowManager = (WindowManager)context.getSystemService(
1104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Context.WINDOW_SERVICE);
1114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDefaultDisplay = mWindowManager.getDefaultDisplay();
1134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        updateDefaultDisplayInfo();
1144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        createWindow();
1164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void show() {
1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mWindowVisible) {
1204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayManager.registerDisplayListener(mDisplayListener, null);
1214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (!updateDefaultDisplayInfo()) {
1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mDisplayManager.unregisterDisplayListener(mDisplayListener);
1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return;
1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            clearLiveState();
1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateWindowParams();
1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.addView(mWindowContent, mWindowParams);
1294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowVisible = true;
1304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void dismiss() {
1344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mWindowVisible) {
1354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayManager.unregisterDisplayListener(mDisplayListener);
1364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.removeView(mWindowContent);
1374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowVisible = false;
1384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void relayout() {
1424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mWindowVisible) {
1434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateWindowParams();
1444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
1454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
148d5523dc7b7318f2774109dd30716ff7b74560e61Craig Mautner    @Override
1494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void dump(PrintWriter pw) {
150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowVisible=" + mWindowVisible);
151cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowX=" + mWindowX);
152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowY=" + mWindowY);
153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowScale=" + mWindowScale);
154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowParams=" + mWindowParams);
1554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mTextureView != null) {
156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mTextureView.getScaleX()=" + mTextureView.getScaleX());
157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mTextureView.getScaleY()=" + mTextureView.getScaleY());
1584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveTranslationX=" + mLiveTranslationX);
160cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveTranslationY=" + mLiveTranslationY);
161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveScale=" + mLiveScale);
1624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean updateDefaultDisplayInfo() {
1654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
1664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.w(TAG, "Cannot show overlay display because there is no "
1674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + "default display upon which to show it.");
1684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return false;
1694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return true;
1714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void createWindow() {
1744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        LayoutInflater inflater = LayoutInflater.from(mContext);
1754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowContent = inflater.inflate(
1774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.layout.overlay_display_window, null);
1784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowContent.setOnTouchListener(mOnTouchListener);
1794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView = (TextureView)mWindowContent.findViewById(
1814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.id.overlay_display_window_texture);
1824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setPivotX(0);
1834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setPivotY(0);
1844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.getLayoutParams().width = mWidth;
1854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.getLayoutParams().height = mHeight;
1864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setOpaque(false);
1874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
1884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitleTextView = (TextView)mWindowContent.findViewById(
1904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.id.overlay_display_window_title);
1914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitleTextView.setText(mTitle);
1924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams = new WindowManager.LayoutParams(
1944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);
1954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
1964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
1974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
1994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (DISABLE_MOVE_AND_RESIZE) {
2014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.privateFlags |=
2044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.alpha = WINDOW_ALPHA;
2064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
2074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.setTitle(mTitle);
2084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mGestureDetector = new GestureDetector(mContext, mOnGestureListener);
2104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);
2114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Set the initial position and scale.
2134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // The position and scale will be clamped when the display is first shown.
2144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?
2154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                0 : mDefaultDisplayInfo.logicalWidth;
2164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?
2174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                0 : mDefaultDisplayInfo.logicalHeight;
2184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowScale = INITIAL_SCALE;
2194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void updateWindowParams() {
2224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        float scale = mWindowScale * mLiveScale;
2234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalWidth / mWidth);
2244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalHeight / mHeight);
2254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
2264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        float offsetScale = (scale / mWindowScale - 1.0f) * 0.5f;
2284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int width = (int)(mWidth * scale);
2294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int height = (int)(mHeight * scale);
2304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int x = (int)(mWindowX + mLiveTranslationX - width * offsetScale);
2314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int y = (int)(mWindowY + mLiveTranslationY - height * offsetScale);
2324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        x = Math.max(0, Math.min(x, mDefaultDisplayInfo.logicalWidth - width));
2334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        y = Math.max(0, Math.min(y, mDefaultDisplayInfo.logicalHeight - height));
2344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (DEBUG) {
2364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.d(TAG, "updateWindowParams: scale=" + scale
2374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", offsetScale=" + offsetScale
2384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", x=" + x + ", y=" + y
2394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", width=" + width + ", height=" + height);
2404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setScaleX(scale);
2434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setScaleY(scale);
2444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.x = x;
2464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.y = y;
2474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.width = width;
2484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.height = height;
2494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void saveWindowParams() {
2524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowX = mWindowParams.x;
2534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowY = mWindowParams.y;
2544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowScale = mTextureView.getScaleX();
2554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        clearLiveState();
2564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void clearLiveState() {
2594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveTranslationX = 0f;
2604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveTranslationY = 0f;
2614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveScale = 1.0f;
2624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayManager.DisplayListener mDisplayListener =
2654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new DisplayManager.DisplayListener() {
2664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayAdded(int displayId) {
2684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayChanged(int displayId) {
2724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (displayId == mDefaultDisplay.getDisplayId()) {
2734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                if (updateDefaultDisplayInfo()) {
2744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    relayout();
2754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                } else {
2764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    dismiss();
2774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                }
2784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
2794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayRemoved(int displayId) {
2834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (displayId == mDefaultDisplay.getDisplayId()) {
2844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                dismiss();
2854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
2864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
2884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final SurfaceTextureListener mSurfaceTextureListener =
2904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new SurfaceTextureListener() {
2914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
292cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
293cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height) {
294d5523dc7b7318f2774109dd30716ff7b74560e61Craig Mautner            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate);
2954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
298cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
2994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mListener.onWindowDestroyed();
3004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
304cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
305cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height) {
3064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
309cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
3104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
3144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onTouch(View view, MotionEvent event) {
3164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // Work in screen coordinates.
3174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final float oldX = event.getX();
3184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final float oldY = event.getY();
3194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            event.setLocation(event.getRawX(), event.getRawY());
3204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mGestureDetector.onTouchEvent(event);
3224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mScaleGestureDetector.onTouchEvent(event);
3234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            switch (event.getActionMasked()) {
3254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MotionEvent.ACTION_UP:
3264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MotionEvent.ACTION_CANCEL:
3274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    saveWindowParams();
3284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    break;
3294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
3304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // Revert to window coordinates.
3324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            event.setLocation(oldX, oldY);
3334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final GestureDetector.OnGestureListener mOnGestureListener =
3384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new GestureDetector.SimpleOnGestureListener() {
3394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onScroll(MotionEvent e1, MotionEvent e2,
3414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                float distanceX, float distanceY) {
3424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveTranslationX -= distanceX;
3434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveTranslationY -= distanceY;
3444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            relayout();
3454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
3504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new ScaleGestureDetector.SimpleOnScaleGestureListener() {
3514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onScale(ScaleGestureDetector detector) {
3534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveScale *= detector.getScaleFactor();
3544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            relayout();
3554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
3604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Watches for significant changes in the overlay display window lifecycle.
3614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
3624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public interface Listener {
363d5523dc7b7318f2774109dd30716ff7b74560e61Craig Mautner        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate);
3644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onWindowDestroyed();
3654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
3664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown}