TaskSnapshotSurface.java revision 02886a82d876aa5e31a92444fec70208599c509c
102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi/*
202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Copyright (C) 2016 The Android Open Source Project
302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi *
402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * you may not use this file except in compliance with the License.
602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * You may obtain a copy of the License at
702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi *
802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi *
1002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * Unless required by applicable law or agreed to in writing, software
1102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
1202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * See the License for the specific language governing permissions and
1402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * limitations under the License
1502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi */
1602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
1702886a82d876aa5e31a92444fec70208599c509cJorim Jaggipackage com.android.server.wm;
1802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
1902886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
2002886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
2102886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2202886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2302886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2402886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
2502886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
2602886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
2702886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
2802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
2902886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.content.res.Configuration;
3002886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.Bitmap;
3102886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.Canvas;
3202886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.GraphicBuffer;
3302886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.graphics.Rect;
3402886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.os.Handler;
3502886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.os.Message;
3602886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.os.RemoteException;
3702886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.util.Slog;
3802886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.Display;
3902886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.IWindowSession;
4002886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.Surface;
4102886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.View;
4202886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.ViewGroup.LayoutParams;
4302886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.WindowManager;
4402886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.WindowManagerGlobal;
4502886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport android.view.WindowManagerPolicy.StartingSurface;
4602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
4702886a82d876aa5e31a92444fec70208599c509cJorim Jaggiimport com.android.internal.view.BaseIWindow;
4802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
4902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi/**
5002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * This class represents a starting window that shows a snapshot.
5102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * <p>
5202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS!
5302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi */
5402886a82d876aa5e31a92444fec70208599c509cJorim Jaggiclass TaskSnapshotSurface implements StartingSurface {
5502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
5602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
5702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private static final int MSG_REPORT_DRAW = 0;
5802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
5902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private final Window mWindow;
6002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private final Surface mSurface;
6102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private final IWindowSession mSession;
6202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private final WindowManagerService mService;
6302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private boolean mHasDrawn;
6402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private boolean mReportNextDraw;
6502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
6602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
6702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            GraphicBuffer snapshot) {
6802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
6902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
7002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final Window window = new Window();
7102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final IWindowSession session = WindowManagerGlobal.getWindowSession();
7202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        window.setSession(session);
7302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final Surface surface = new Surface();
7402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final Rect tmpRect = new Rect();
7502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final Rect tmpFrame = new Rect();
7602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final Configuration tmpConfiguration = new Configuration();
7702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        synchronized (service.mWindowMap) {
7802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.type = TYPE_APPLICATION_STARTING;
7902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.format = snapshot.getFormat();
8002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.flags = FLAG_LAYOUT_INSET_DECOR
8102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    | FLAG_LAYOUT_IN_SCREEN
8202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    | FLAG_NOT_FOCUSABLE
8302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    | FLAG_NOT_TOUCHABLE
8402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
8502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
8602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.token = token.token;
8702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.width = LayoutParams.MATCH_PARENT;
8802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.height = LayoutParams.MATCH_PARENT;
8902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
9002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            // TODO: Inherit behavior whether to draw behind status bar/nav bar.
9102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
9202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
9302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            layoutParams.setTitle(String.format(TITLE_FORMAT, token.mTask.mTaskId));
9402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
9502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        try {
9602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            final int res = session.addToDisplay(window, window.mSeq, layoutParams,
9702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    View.VISIBLE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect,
9802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    tmpRect, null);
9902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            if (res < 0) {
10002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
10102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                return null;
10202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            }
10302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        } catch (RemoteException e) {
10402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            // Local call.
10502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
10602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
10702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                surface);
10802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        window.setOuter(snapshotSurface);
10902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        try {
11002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
11102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpConfiguration,
11202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    surface);
11302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        } catch (RemoteException e) {
11402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            // Local call.
11502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
11602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        snapshotSurface.drawSnapshot(snapshot);
11702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        return snapshotSurface;
11802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    }
11902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
12002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface) {
12102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        mService = service;
12202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        mSession = WindowManagerGlobal.getWindowSession();
12302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        mWindow = window;
12402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        mSurface = surface;
12502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    }
12602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
12702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    @Override
12802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    public void remove() {
12902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        try {
13002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            mSession.remove(mWindow);
13102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        } catch (RemoteException e) {
13202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            // Local call.
13302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
13402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    }
13502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
13602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private void drawSnapshot(GraphicBuffer snapshot) {
13702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
13802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        // TODO: Just wrap the buffer here without any copying.
13902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final Canvas c = mSurface.lockHardwareCanvas();
14002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        c.drawBitmap(Bitmap.createHardwareBitmap(snapshot), 0, 0, null);
14102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        mSurface.unlockCanvasAndPost(c);
14202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        final boolean reportNextDraw;
14302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        synchronized (mService.mWindowMap) {
14402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            mHasDrawn = true;
14502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            reportNextDraw = mReportNextDraw;
14602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
14702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        if (reportNextDraw) {
14802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            reportDrawn();
14902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
15002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    }
15102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
15202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private void reportDrawn() {
15302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        synchronized (mService.mWindowMap) {
15402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            mReportNextDraw = false;
15502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
15602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        try {
15702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            mSession.finishDrawing(mWindow);
15802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        } catch (RemoteException e) {
15902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            // Local call.
16002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
16102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    }
16202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
16302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private static Handler sHandler = new Handler() {
16402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
16502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        @Override
16602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        public void handleMessage(Message msg) {
16702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            switch (msg.what) {
16802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                case MSG_REPORT_DRAW:
16902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    final boolean hasDrawn;
17002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
17102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    synchronized (surface.mService.mWindowMap) {
17202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                        hasDrawn = surface.mHasDrawn;
17302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                        if (!hasDrawn) {
17402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                            surface.mReportNextDraw = true;
17502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                        }
17602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    }
17702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    if (hasDrawn) {
17802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                        surface.reportDrawn();
17902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    }
18002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                    break;
18102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            }
18202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
18302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    };
18402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
18502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    private static class Window extends BaseIWindow {
18602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
18702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        private TaskSnapshotSurface mOuter;
18802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
18902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        public void setOuter(TaskSnapshotSurface outer) {
19002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            mOuter = outer;
19102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
19202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi
19302886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        @Override
19402886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
19502886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
19602886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar) {
19702886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            if (reportDraw) {
19802886a82d876aa5e31a92444fec70208599c509cJorim Jaggi                sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
19902886a82d876aa5e31a92444fec70208599c509cJorim Jaggi            }
20002886a82d876aa5e31a92444fec70208599c509cJorim Jaggi        }
20102886a82d876aa5e31a92444fec70208599c509cJorim Jaggi    }
20202886a82d876aa5e31a92444fec70208599c509cJorim Jaggi}
203