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