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;
67040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown    private final boolean mSecure;
684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Listener mListener;
69040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown    private String mTitle;
704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayManager mDisplayManager;
724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final WindowManager mWindowManager;
734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Display mDefaultDisplay;
764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private View mWindowContent;
794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private WindowManager.LayoutParams mWindowParams;
804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private TextureView mTextureView;
814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private TextView mTitleTextView;
824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private GestureDetector mGestureDetector;
844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private ScaleGestureDetector mScaleGestureDetector;
854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean mWindowVisible;
874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mWindowX;
884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mWindowY;
894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mWindowScale;
904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveTranslationX;
924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveTranslationY;
934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveScale = 1.0f;
944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public OverlayDisplayWindow(Context context, String name,
96040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            int width, int height, int densityDpi, int gravity, boolean secure,
97040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            Listener listener) {
984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mContext = context;
994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mName = name;
1004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWidth = width;
1014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mHeight = height;
1024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDensityDpi = densityDpi;
1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mGravity = gravity;
104040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        mSecure = secure;
1054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mListener = listener;
1064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitle = context.getResources().getString(
1074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.string.display_manager_overlay_display_title,
1084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mName, mWidth, mHeight, mDensityDpi);
109040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        if (secure) {
110040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            mTitle += context.getResources().getString(
111040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown                    com.android.internal.R.string.display_manager_overlay_display_secure_suffix);
112040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        }
1134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDisplayManager = (DisplayManager)context.getSystemService(
1154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Context.DISPLAY_SERVICE);
1164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowManager = (WindowManager)context.getSystemService(
1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Context.WINDOW_SERVICE);
1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDefaultDisplay = mWindowManager.getDefaultDisplay();
1204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        updateDefaultDisplayInfo();
1214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        createWindow();
1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void show() {
1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mWindowVisible) {
1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayManager.registerDisplayListener(mDisplayListener, null);
1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (!updateDefaultDisplayInfo()) {
1294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mDisplayManager.unregisterDisplayListener(mDisplayListener);
1304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return;
1314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
1324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            clearLiveState();
1344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateWindowParams();
1354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.addView(mWindowContent, mWindowParams);
1364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowVisible = true;
1374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void dismiss() {
1414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mWindowVisible) {
1424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayManager.unregisterDisplayListener(mDisplayListener);
1434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.removeView(mWindowContent);
1444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowVisible = false;
1454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void relayout() {
1494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mWindowVisible) {
1504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateWindowParams();
1514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
1524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
155d5523dc7b7318f2774109dd30716ff7b74560e61Craig Mautner    @Override
1564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void dump(PrintWriter pw) {
157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowVisible=" + mWindowVisible);
158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowX=" + mWindowX);
159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowY=" + mWindowY);
160cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowScale=" + mWindowScale);
161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowParams=" + mWindowParams);
1624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mTextureView != null) {
163cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mTextureView.getScaleX()=" + mTextureView.getScaleX());
164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mTextureView.getScaleY()=" + mTextureView.getScaleY());
1654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
166cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveTranslationX=" + mLiveTranslationX);
167cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveTranslationY=" + mLiveTranslationY);
168cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveScale=" + mLiveScale);
1694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean updateDefaultDisplayInfo() {
1724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
1734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.w(TAG, "Cannot show overlay display because there is no "
1744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + "default display upon which to show it.");
1754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return false;
1764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return true;
1784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void createWindow() {
1814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        LayoutInflater inflater = LayoutInflater.from(mContext);
1824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowContent = inflater.inflate(
1844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.layout.overlay_display_window, null);
1854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowContent.setOnTouchListener(mOnTouchListener);
1864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView = (TextureView)mWindowContent.findViewById(
1884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.id.overlay_display_window_texture);
1894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setPivotX(0);
1904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setPivotY(0);
1914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.getLayoutParams().width = mWidth;
1924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.getLayoutParams().height = mHeight;
1934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setOpaque(false);
1944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
1954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitleTextView = (TextView)mWindowContent.findViewById(
1974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.id.overlay_display_window_title);
1984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitleTextView.setText(mTitle);
1994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams = new WindowManager.LayoutParams(
2014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);
2024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
2034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
2044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
2064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
207040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        if (mSecure) {
208040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_SECURE;
209040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        }
2104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (DISABLE_MOVE_AND_RESIZE) {
2114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.privateFlags |=
2144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.alpha = WINDOW_ALPHA;
2164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
2174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.setTitle(mTitle);
2184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mGestureDetector = new GestureDetector(mContext, mOnGestureListener);
2204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);
2214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Set the initial position and scale.
2234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // The position and scale will be clamped when the display is first shown.
2244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?
2254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                0 : mDefaultDisplayInfo.logicalWidth;
2264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?
2274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                0 : mDefaultDisplayInfo.logicalHeight;
2284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowScale = INITIAL_SCALE;
2294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void updateWindowParams() {
2324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        float scale = mWindowScale * mLiveScale;
2334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalWidth / mWidth);
2344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalHeight / mHeight);
2354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
2364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        float offsetScale = (scale / mWindowScale - 1.0f) * 0.5f;
2384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int width = (int)(mWidth * scale);
2394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int height = (int)(mHeight * scale);
2404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int x = (int)(mWindowX + mLiveTranslationX - width * offsetScale);
2414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int y = (int)(mWindowY + mLiveTranslationY - height * offsetScale);
2424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        x = Math.max(0, Math.min(x, mDefaultDisplayInfo.logicalWidth - width));
2434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        y = Math.max(0, Math.min(y, mDefaultDisplayInfo.logicalHeight - height));
2444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (DEBUG) {
2464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.d(TAG, "updateWindowParams: scale=" + scale
2474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", offsetScale=" + offsetScale
2484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", x=" + x + ", y=" + y
2494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", width=" + width + ", height=" + height);
2504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setScaleX(scale);
2534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setScaleY(scale);
2544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.x = x;
2564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.y = y;
2574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.width = width;
2584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.height = height;
2594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void saveWindowParams() {
2624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowX = mWindowParams.x;
2634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowY = mWindowParams.y;
2644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowScale = mTextureView.getScaleX();
2654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        clearLiveState();
2664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void clearLiveState() {
2694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveTranslationX = 0f;
2704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveTranslationY = 0f;
2714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveScale = 1.0f;
2724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayManager.DisplayListener mDisplayListener =
2754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new DisplayManager.DisplayListener() {
2764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayAdded(int displayId) {
2784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayChanged(int displayId) {
2824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (displayId == mDefaultDisplay.getDisplayId()) {
2834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                if (updateDefaultDisplayInfo()) {
2844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    relayout();
285037c33eae74bee2774897d969d48947f9abe254fJeff Brown                    mListener.onStateChanged(mDefaultDisplayInfo.state);
2864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                } else {
2874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    dismiss();
2884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                }
2894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
2904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayRemoved(int displayId) {
2944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (displayId == mDefaultDisplay.getDisplayId()) {
2954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                dismiss();
2964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
2974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
2994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final SurfaceTextureListener mSurfaceTextureListener =
3014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new SurfaceTextureListener() {
3024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
303cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
304cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height) {
305037c33eae74bee2774897d969d48947f9abe254fJeff Brown            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate,
306e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden                    mDefaultDisplayInfo.presentationDeadlineNanos, mDefaultDisplayInfo.state);
3074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
310cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
3114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mListener.onWindowDestroyed();
3124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
316cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
317cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height) {
3184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
321cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
3224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
3264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onTouch(View view, MotionEvent event) {
3284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // Work in screen coordinates.
3294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final float oldX = event.getX();
3304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final float oldY = event.getY();
3314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            event.setLocation(event.getRawX(), event.getRawY());
3324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mGestureDetector.onTouchEvent(event);
3344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mScaleGestureDetector.onTouchEvent(event);
3354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            switch (event.getActionMasked()) {
3374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MotionEvent.ACTION_UP:
3384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MotionEvent.ACTION_CANCEL:
3394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    saveWindowParams();
3404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    break;
3414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
3424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // Revert to window coordinates.
3444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            event.setLocation(oldX, oldY);
3454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final GestureDetector.OnGestureListener mOnGestureListener =
3504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new GestureDetector.SimpleOnGestureListener() {
3514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onScroll(MotionEvent e1, MotionEvent e2,
3534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                float distanceX, float distanceY) {
3544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveTranslationX -= distanceX;
3554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveTranslationY -= distanceY;
3564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            relayout();
3574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
3624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new ScaleGestureDetector.SimpleOnScaleGestureListener() {
3634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onScale(ScaleGestureDetector detector) {
3654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveScale *= detector.getScaleFactor();
3664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            relayout();
3674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
3724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Watches for significant changes in the overlay display window lifecycle.
3734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
3744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public interface Listener {
375037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public void onWindowCreated(SurfaceTexture surfaceTexture,
376e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden                float refreshRate, long presentationDeadlineNanos, int state);
3774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onWindowDestroyed();
378037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public void onStateChanged(int state);
3794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
3804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown}