17fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen/*
27fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * Copyright (C) 2014 The Android Open Source Project
37fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen *
47fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * Licensed under the Apache License, Version 2.0 (the "License");
57fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * you may not use this file except in compliance with the License.
67fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * You may obtain a copy of the License at
77fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen *
87fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen *      http://www.apache.org/licenses/LICENSE-2.0
97fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen *
107fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * Unless required by applicable law or agreed to in writing, software
117fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * distributed under the License is distributed on an "AS IS" BASIS,
127fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * See the License for the specific language governing permissions and
147fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen * limitations under the License.
157fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen */
167fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
177fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenpackage com.android.server.wm;
187fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
197fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
200bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynskiimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
210bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynskiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
220bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynskiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
230bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski
247fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.content.Context;
257fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.Canvas;
267fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.Color;
277fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.PixelFormat;
287fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.Point;
297fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.PorterDuff;
307fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.Rect;
317fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.graphics.drawable.Drawable;
327fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.view.Display;
337fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.view.Surface;
347fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.view.Surface.OutOfResourcesException;
357fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.view.SurfaceControl;
367fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenimport android.view.SurfaceSession;
377fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
387fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazenclass EmulatorDisplayOverlay {
390bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski    private static final String TAG = TAG_WITH_CLASS_NAME ? "EmulatorDisplayOverlay" : TAG_WM;
407fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
417fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    // Display dimensions
427fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private Point mScreenSize;
437fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
447fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private final SurfaceControl mSurfaceControl;
457fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private final Surface mSurface = new Surface();
467fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private int mLastDW;
477fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private int mLastDH;
487fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private boolean mDrawNeeded;
497fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private Drawable mOverlay;
507fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private int mRotation;
517fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private boolean mVisible;
527fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
537fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    public EmulatorDisplayOverlay(Context context, Display display, SurfaceSession session,
547fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            int zOrder) {
557fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mScreenSize = new Point();
567fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        display.getSize(mScreenSize);
577fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
587fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        SurfaceControl ctrl = null;
597fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        try {
600bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski            if (DEBUG_SURFACE_TRACE) {
61e6a8351bc715999d1e42dcc1003a6eda6c318dd9Robert Carr                ctrl = new WindowSurfaceController.SurfaceTrace(session, "EmulatorDisplayOverlay",
627fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen                        mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
637fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen                        SurfaceControl.HIDDEN);
647fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            } else {
657fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen                ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
667fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen                        mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
677fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            }
687fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            ctrl.setLayerStack(display.getLayerStack());
697fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            ctrl.setLayer(zOrder);
707fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            ctrl.setPosition(0, 0);
717fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            ctrl.show();
727fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            mSurface.copyFrom(ctrl);
737fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        } catch (OutOfResourcesException e) {
747fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
757fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mSurfaceControl = ctrl;
767fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mDrawNeeded = true;
777fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mOverlay = context.getDrawable(
787fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen                com.android.internal.R.drawable.emulator_circular_window_overlay);
797fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    }
807fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
817fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    private void drawIfNeeded() {
827fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        if (!mDrawNeeded || !mVisible) {
837fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            return;
847fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
857fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mDrawNeeded = false;
867fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
877fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y);
887fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        Canvas c = null;
897fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        try {
907fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            c = mSurface.lockCanvas(dirty);
917fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        } catch (IllegalArgumentException e) {
927fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        } catch (OutOfResourcesException e) {
937fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
947fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        if (c == null) {
957fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            return;
967fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
977fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
987fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mSurfaceControl.setPosition(0, 0);
991ad0fe6c3670f185bddeb0b4d17aba237765ea6bGriff Hazen        // Always draw the overlay with square dimensions
1001ad0fe6c3670f185bddeb0b4d17aba237765ea6bGriff Hazen        int size = Math.max(mScreenSize.x, mScreenSize.y);
1011ad0fe6c3670f185bddeb0b4d17aba237765ea6bGriff Hazen        mOverlay.setBounds(0, 0, size, size);
1027fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mOverlay.draw(c);
1037fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mSurface.unlockCanvasAndPost(c);
1047fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    }
1057fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
1067fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    // Note: caller responsible for being inside
1077fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    // Surface.openTransaction() / closeTransaction()
1087fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    public void setVisibility(boolean on) {
1097fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        if (mSurfaceControl == null) {
1107fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            return;
1117fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
1127fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mVisible = on;
1137fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        drawIfNeeded();
1147fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        if (on) {
1157fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            mSurfaceControl.show();
1167fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        } else {
1177fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            mSurfaceControl.hide();
1187fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
1197fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    }
1207fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
1217fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    void positionSurface(int dw, int dh, int rotation) {
1227fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
1237fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen            return;
1247fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        }
1257fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mLastDW = dw;
1267fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mLastDH = dh;
1277fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mDrawNeeded = true;
1287fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        mRotation = rotation;
1297fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen        drawIfNeeded();
1307fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen    }
1317fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen
1327fb614664707f4c67dbbad8320e7d3cc10750df1Griff Hazen}
133