VirtualDisplayAdapter.java revision a767d762d8f70fbce0d8bb8d2bacde55de2504b5
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 void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
73        VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
74        if (device != null) {
75            device.setSurfaceLocked(surface);
76        }
77    }
78
79    public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
80        VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
81        if (device != null) {
82            device.destroyLocked();
83            appToken.unlinkToDeath(device, 0);
84        }
85
86        // Return the display device that was removed without actually sending the
87        // event indicating that it was removed.  The caller will handle it.
88        return device;
89    }
90
91    private void handleBinderDiedLocked(IBinder appToken) {
92        VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
93        if (device != null) {
94            Slog.i(TAG, "Virtual display device released because application token died: "
95                    + device.mOwnerPackageName);
96            device.destroyLocked();
97            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
98        }
99    }
100
101    private final class VirtualDisplayDevice extends DisplayDevice
102            implements DeathRecipient {
103        private final IBinder mAppToken;
104        private final int mOwnerUid;
105        final String mOwnerPackageName;
106        private final String mName;
107        private final int mWidth;
108        private final int mHeight;
109        private final int mDensityDpi;
110        private final int mFlags;
111
112        private Surface mSurface;
113        private DisplayDeviceInfo mInfo;
114
115        public VirtualDisplayDevice(IBinder displayToken,
116                IBinder appToken, int ownerUid, String ownerPackageName,
117                String name, int width, int height, int densityDpi, Surface surface, int flags) {
118            super(VirtualDisplayAdapter.this, displayToken);
119            mAppToken = appToken;
120            mOwnerUid = ownerUid;
121            mOwnerPackageName = ownerPackageName;
122            mName = name;
123            mWidth = width;
124            mHeight = height;
125            mDensityDpi = densityDpi;
126            mSurface = surface;
127            mFlags = flags;
128        }
129
130        @Override
131        public void binderDied() {
132            synchronized (getSyncRoot()) {
133                if (mSurface != null) {
134                    handleBinderDiedLocked(mAppToken);
135                }
136            }
137        }
138
139        public void destroyLocked() {
140            if (mSurface != null) {
141                mSurface.release();
142                mSurface = null;
143            }
144            SurfaceControl.destroyDisplay(getDisplayTokenLocked());
145        }
146
147        @Override
148        public void performTraversalInTransactionLocked() {
149            setSurfaceInTransactionLocked(mSurface);
150        }
151
152        public void setSurfaceLocked(Surface surface) {
153            if (mSurface != surface) {
154                if ((mSurface != null) != (surface != null)) {
155                    sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
156                }
157                sendTraversalRequestLocked();
158                mSurface = surface;
159                mInfo = null;
160            }
161        }
162
163        @Override
164        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
165            if (mInfo == null) {
166                mInfo = new DisplayDeviceInfo();
167                mInfo.name = mName;
168                mInfo.width = mWidth;
169                mInfo.height = mHeight;
170                mInfo.refreshRate = 60;
171                mInfo.densityDpi = mDensityDpi;
172                mInfo.xDpi = mDensityDpi;
173                mInfo.yDpi = mDensityDpi;
174                mInfo.flags = 0;
175                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
176                    mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
177                            | DisplayDeviceInfo.FLAG_NEVER_BLANK
178                            | DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
179                } else if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
180                    mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
181                }
182                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
183                    mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
184                }
185                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
186                    mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
187                }
188                mInfo.type = Display.TYPE_VIRTUAL;
189                mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
190                mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;
191                mInfo.ownerUid = mOwnerUid;
192                mInfo.ownerPackageName = mOwnerPackageName;
193            }
194            return mInfo;
195        }
196    }
197}
198