VirtualDisplayAdapter.java revision 9158825f9c41869689d6b1786d7c7aa8bdd524ce
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.display;
18
19import android.content.Context;
20import android.hardware.display.DisplayManager;
21import android.os.Handler;
22import android.os.IBinder;
23import android.os.IBinder.DeathRecipient;
24import android.os.RemoteException;
25import android.util.ArrayMap;
26import android.util.Slog;
27import android.view.Display;
28import android.view.Surface;
29import android.view.SurfaceControl;
30
31/**
32 * A display adapter that provides virtual displays on behalf of applications.
33 * <p>
34 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
35 * </p>
36 */
37final class VirtualDisplayAdapter extends DisplayAdapter {
38    static final String TAG = "VirtualDisplayAdapter";
39    static final boolean DEBUG = false;
40
41    private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices =
42            new ArrayMap<IBinder, VirtualDisplayDevice>();
43
44    // Called with SyncRoot lock held.
45    public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
46            Context context, Handler handler, Listener listener) {
47        super(syncRoot, context, handler, listener, TAG);
48    }
49
50    public DisplayDevice createVirtualDisplayLocked(IBinder appToken,
51            int ownerUid, String ownerPackageName,
52            String name, int width, int height, int densityDpi, Surface surface, int flags) {
53        boolean secure = (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
54        IBinder displayToken = SurfaceControl.createDisplay(name, secure);
55        VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
56                ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags);
57
58        try {
59            appToken.linkToDeath(device, 0);
60        } catch (RemoteException ex) {
61            device.destroyLocked();
62            return null;
63        }
64
65        mVirtualDisplayDevices.put(appToken, device);
66
67        // Return the display device without actually sending the event indicating
68        // that it was added.  The caller will handle it.
69        return device;
70    }
71
72    public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
73        VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
74        if (device != null) {
75            device.destroyLocked();
76            appToken.unlinkToDeath(device, 0);
77        }
78
79        // Return the display device that was removed without actually sending the
80        // event indicating that it was removed.  The caller will handle it.
81        return device;
82    }
83
84    private void handleBinderDiedLocked(IBinder appToken) {
85        VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
86        if (device != null) {
87            Slog.i(TAG, "Virtual display device released because application token died: "
88                    + device.mOwnerPackageName);
89            device.destroyLocked();
90            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
91        }
92    }
93
94    private final class VirtualDisplayDevice extends DisplayDevice
95            implements DeathRecipient {
96        private final IBinder mAppToken;
97        private final int mOwnerUid;
98        final String mOwnerPackageName;
99        private final String mName;
100        private final int mWidth;
101        private final int mHeight;
102        private final int mDensityDpi;
103        private final int mFlags;
104
105        private Surface mSurface;
106        private DisplayDeviceInfo mInfo;
107
108        public VirtualDisplayDevice(IBinder displayToken,
109                IBinder appToken, int ownerUid, String ownerPackageName,
110                String name, int width, int height, int densityDpi, Surface surface, int flags) {
111            super(VirtualDisplayAdapter.this, displayToken);
112            mAppToken = appToken;
113            mOwnerUid = ownerUid;
114            mOwnerPackageName = ownerPackageName;
115            mName = name;
116            mWidth = width;
117            mHeight = height;
118            mDensityDpi = densityDpi;
119            mSurface = surface;
120            mFlags = flags;
121        }
122
123        @Override
124        public void binderDied() {
125            synchronized (getSyncRoot()) {
126                if (mSurface != null) {
127                    handleBinderDiedLocked(mAppToken);
128                }
129            }
130        }
131
132        public void destroyLocked() {
133            if (mSurface != null) {
134                mSurface.release();
135                mSurface = null;
136            }
137            SurfaceControl.destroyDisplay(getDisplayTokenLocked());
138        }
139
140        @Override
141        public void performTraversalInTransactionLocked() {
142            if (mSurface != null) {
143                setSurfaceInTransactionLocked(mSurface);
144            }
145        }
146
147        @Override
148        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
149            if (mInfo == null) {
150                mInfo = new DisplayDeviceInfo();
151                mInfo.name = mName;
152                mInfo.width = mWidth;
153                mInfo.height = mHeight;
154                mInfo.refreshRate = 60;
155                mInfo.densityDpi = mDensityDpi;
156                mInfo.xDpi = mDensityDpi;
157                mInfo.yDpi = mDensityDpi;
158                mInfo.flags = 0;
159                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
160                    mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE |
161                            DisplayDeviceInfo.FLAG_NEVER_BLANK;
162                }
163                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
164                    mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
165                }
166                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
167                    mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
168                }
169                mInfo.type = Display.TYPE_VIRTUAL;
170                mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
171                mInfo.ownerUid = mOwnerUid;
172                mInfo.ownerPackageName = mOwnerPackageName;
173            }
174            return mInfo;
175        }
176    }
177}
178