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;
33a896306c38c4d11c43b967a21db6d74c251b2520John Reckimport android.view.ThreadedRenderer;
344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.View;
354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.WindowManager;
364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.view.TextureView.SurfaceTextureListener;
374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.widget.TextView;
384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport java.io.PrintWriter;
404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown/**
424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Manages an overlay window on behalf of {@link OverlayDisplayAdapter}.
434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * <p>
444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * This object must only be accessed on the UI thread.
454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * No locks are held by this object and locks must not be held while making called into it.
464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * </p>
474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown */
48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class OverlayDisplayWindow implements DumpUtils.Dump {
494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private static final String TAG = "OverlayDisplayWindow";
504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private static final boolean DEBUG = false;
514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float INITIAL_SCALE = 0.5f;
534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float MIN_SCALE = 0.3f;
544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float MAX_SCALE = 1.0f;
554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final float WINDOW_ALPHA = 0.8f;
564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // When true, disables support for moving and resizing the overlay.
584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // The window is made non-touchable, which makes it possible to
594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // directly interact with the content underneath.
604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final boolean DISABLE_MOVE_AND_RESIZE = false;
614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Context mContext;
634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final String mName;
64af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    private int mWidth;
65af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    private int mHeight;
66af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    private int mDensityDpi;
674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final int mGravity;
68040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown    private final boolean mSecure;
694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Listener mListener;
70040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown    private String mTitle;
714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayManager mDisplayManager;
734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final WindowManager mWindowManager;
744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Display mDefaultDisplay;
774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private View mWindowContent;
804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private WindowManager.LayoutParams mWindowParams;
814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private TextureView mTextureView;
824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private TextView mTitleTextView;
834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private GestureDetector mGestureDetector;
854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private ScaleGestureDetector mScaleGestureDetector;
864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean mWindowVisible;
884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mWindowX;
894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mWindowY;
904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mWindowScale;
914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveTranslationX;
934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveTranslationY;
944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private float mLiveScale = 1.0f;
954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public OverlayDisplayWindow(Context context, String name,
97040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            int width, int height, int densityDpi, int gravity, boolean secure,
98040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            Listener listener) {
99a896306c38c4d11c43b967a21db6d74c251b2520John Reck        // Workaround device freeze (b/38372997)
100a896306c38c4d11c43b967a21db6d74c251b2520John Reck        ThreadedRenderer.disableVsync();
1014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mContext = context;
1024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mName = name;
1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mGravity = gravity;
104040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        mSecure = secure;
1054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mListener = listener;
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
115af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        resize(width, height, densityDpi, false /* doLayout */);
116af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand
1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        createWindow();
1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void show() {
1214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mWindowVisible) {
1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayManager.registerDisplayListener(mDisplayListener, null);
1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (!updateDefaultDisplayInfo()) {
1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mDisplayManager.unregisterDisplayListener(mDisplayListener);
1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return;
1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            clearLiveState();
1294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateWindowParams();
1304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.addView(mWindowContent, mWindowParams);
1314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowVisible = true;
1324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void dismiss() {
1364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mWindowVisible) {
1374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayManager.unregisterDisplayListener(mDisplayListener);
1384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.removeView(mWindowContent);
1394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowVisible = false;
1404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
143af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    public void resize(int width, int height, int densityDpi) {
144af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        resize(width, height, densityDpi, true /* doLayout */);
145af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    }
146af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand
147af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    private void resize(int width, int height, int densityDpi, boolean doLayout) {
148af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        mWidth = width;
149af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        mHeight = height;
150af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        mDensityDpi = densityDpi;
151af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        mTitle = mContext.getResources().getString(
152af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand                com.android.internal.R.string.display_manager_overlay_display_title,
153af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand                mName, mWidth, mHeight, mDensityDpi);
154af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        if (mSecure) {
155af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand            mTitle += mContext.getResources().getString(
156af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand                    com.android.internal.R.string.display_manager_overlay_display_secure_suffix);
157af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        }
158af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        if (doLayout) {
159af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand            relayout();
160af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand        }
161af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand    }
162af9c52eb45d772301bf96dd6c54455ffa954ead5P.Y. Laligand
1634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void relayout() {
1644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mWindowVisible) {
1654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateWindowParams();
1664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
1674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
170d5523dc7b7318f2774109dd30716ff7b74560e61Craig Mautner    @Override
171ae6688b09649447e57468b3e7935691bc09ec9b9Dianne Hackborn    public void dump(PrintWriter pw, String prefix) {
172cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowVisible=" + mWindowVisible);
173cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowX=" + mWindowX);
174cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowY=" + mWindowY);
175cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowScale=" + mWindowScale);
176cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mWindowParams=" + mWindowParams);
1774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (mTextureView != null) {
178cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mTextureView.getScaleX()=" + mTextureView.getScaleX());
179cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mTextureView.getScaleY()=" + mTextureView.getScaleY());
1804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
181cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveTranslationX=" + mLiveTranslationX);
182cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveTranslationY=" + mLiveTranslationY);
183cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        pw.println("mLiveScale=" + mLiveScale);
1844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean updateDefaultDisplayInfo() {
1874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
1884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.w(TAG, "Cannot show overlay display because there is no "
1894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + "default display upon which to show it.");
1904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return false;
1914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return true;
1934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
1944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void createWindow() {
1964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        LayoutInflater inflater = LayoutInflater.from(mContext);
1974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowContent = inflater.inflate(
1994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.layout.overlay_display_window, null);
2004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowContent.setOnTouchListener(mOnTouchListener);
2014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView = (TextureView)mWindowContent.findViewById(
2034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.id.overlay_display_window_texture);
2044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setPivotX(0);
2054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setPivotY(0);
2064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.getLayoutParams().width = mWidth;
2074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.getLayoutParams().height = mHeight;
2084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setOpaque(false);
2094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
2104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitleTextView = (TextView)mWindowContent.findViewById(
2124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                com.android.internal.R.id.overlay_display_window_title);
2134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTitleTextView.setText(mTitle);
2144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams = new WindowManager.LayoutParams(
2164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);
2174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
2184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
2194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
2214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
222040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        if (mSecure) {
223040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_SECURE;
224040f44d0ebdd3a50c59ba0cbc0b023fd2d71039dJeff Brown        }
2254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (DISABLE_MOVE_AND_RESIZE) {
2264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.privateFlags |=
2294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.alpha = WINDOW_ALPHA;
2314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
2324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.setTitle(mTitle);
2334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mGestureDetector = new GestureDetector(mContext, mOnGestureListener);
2354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);
2364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Set the initial position and scale.
2384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // The position and scale will be clamped when the display is first shown.
2394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?
2404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                0 : mDefaultDisplayInfo.logicalWidth;
2414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?
2424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                0 : mDefaultDisplayInfo.logicalHeight;
2434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowScale = INITIAL_SCALE;
2444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void updateWindowParams() {
2474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        float scale = mWindowScale * mLiveScale;
2484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalWidth / mWidth);
2494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalHeight / mHeight);
2504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
2514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        float offsetScale = (scale / mWindowScale - 1.0f) * 0.5f;
2534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int width = (int)(mWidth * scale);
2544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int height = (int)(mHeight * scale);
2554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int x = (int)(mWindowX + mLiveTranslationX - width * offsetScale);
2564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        int y = (int)(mWindowY + mLiveTranslationY - height * offsetScale);
2574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        x = Math.max(0, Math.min(x, mDefaultDisplayInfo.logicalWidth - width));
2584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        y = Math.max(0, Math.min(y, mDefaultDisplayInfo.logicalHeight - height));
2594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (DEBUG) {
2614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.d(TAG, "updateWindowParams: scale=" + scale
2624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", offsetScale=" + offsetScale
2634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", x=" + x + ", y=" + y
2644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + ", width=" + width + ", height=" + height);
2654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setScaleX(scale);
2684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mTextureView.setScaleY(scale);
2694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.x = x;
2714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.y = y;
2724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.width = width;
2734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowParams.height = height;
2744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void saveWindowParams() {
2774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowX = mWindowParams.x;
2784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowY = mWindowParams.y;
2794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mWindowScale = mTextureView.getScaleX();
2804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        clearLiveState();
2814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void clearLiveState() {
2844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveTranslationX = 0f;
2854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveTranslationY = 0f;
2864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLiveScale = 1.0f;
2874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayManager.DisplayListener mDisplayListener =
2904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new DisplayManager.DisplayListener() {
2914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayAdded(int displayId) {
2934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
2964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayChanged(int displayId) {
2974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (displayId == mDefaultDisplay.getDisplayId()) {
2984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                if (updateDefaultDisplayInfo()) {
2994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    relayout();
300037c33eae74bee2774897d969d48947f9abe254fJeff Brown                    mListener.onStateChanged(mDefaultDisplayInfo.state);
3014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                } else {
3024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    dismiss();
3034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                }
3044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
3054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onDisplayRemoved(int displayId) {
3094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (displayId == mDefaultDisplay.getDisplayId()) {
3104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                dismiss();
3114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
3124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final SurfaceTextureListener mSurfaceTextureListener =
3164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new SurfaceTextureListener() {
3174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
318cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
319cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height) {
3205c7773d86484aac5737667c604bd8fe8150c2136P.Y. Laligand            mListener.onWindowCreated(surfaceTexture,
3215c7773d86484aac5737667c604bd8fe8150c2136P.Y. Laligand                    mDefaultDisplayInfo.getMode().getRefreshRate(),
322e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden                    mDefaultDisplayInfo.presentationDeadlineNanos, mDefaultDisplayInfo.state);
3234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
326cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
3274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mListener.onWindowDestroyed();
3284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
332cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
333cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height) {
3344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
337cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
3384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
3424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onTouch(View view, MotionEvent event) {
3444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // Work in screen coordinates.
3454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final float oldX = event.getX();
3464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final float oldY = event.getY();
3474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            event.setLocation(event.getRawX(), event.getRawY());
3484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mGestureDetector.onTouchEvent(event);
3504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mScaleGestureDetector.onTouchEvent(event);
3514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            switch (event.getActionMasked()) {
3534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MotionEvent.ACTION_UP:
3544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MotionEvent.ACTION_CANCEL:
3554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    saveWindowParams();
3564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    break;
3574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
3584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // Revert to window coordinates.
3604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            event.setLocation(oldX, oldY);
3614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final GestureDetector.OnGestureListener mOnGestureListener =
3664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new GestureDetector.SimpleOnGestureListener() {
3674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onScroll(MotionEvent e1, MotionEvent e2,
3694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                float distanceX, float distanceY) {
3704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveTranslationX -= distanceX;
3714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveTranslationY -= distanceY;
3724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            relayout();
3734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
3784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new ScaleGestureDetector.SimpleOnScaleGestureListener() {
3794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
3804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public boolean onScale(ScaleGestureDetector detector) {
3814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mLiveScale *= detector.getScaleFactor();
3824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            relayout();
3834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return true;
3844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
3854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
3864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
3884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Watches for significant changes in the overlay display window lifecycle.
3894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
3904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public interface Listener {
391037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public void onWindowCreated(SurfaceTexture surfaceTexture,
392e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden                float refreshRate, long presentationDeadlineNanos, int state);
3934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onWindowDestroyed();
394037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public void onStateChanged(int state);
3954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
3965c7773d86484aac5737667c604bd8fe8150c2136P.Y. Laligand}
397