VirtualDisplayAdapter.java revision 92207df753c27b094e9e0ca80d41bc0d54dc6bd5
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 if (mSurface != null) { 150 setSurfaceInTransactionLocked(mSurface); 151 } 152 } 153 154 public void setSurfaceLocked(Surface surface) { 155 if (mSurface != surface) { 156 if ((mSurface != null) != (surface != null)) { 157 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); 158 } 159 sendTraversalRequestLocked(); 160 mSurface = surface; 161 mInfo = null; 162 } 163 } 164 165 @Override 166 public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 167 if (mInfo == null) { 168 mInfo = new DisplayDeviceInfo(); 169 mInfo.name = mName; 170 mInfo.width = mWidth; 171 mInfo.height = mHeight; 172 mInfo.refreshRate = 60; 173 mInfo.densityDpi = mDensityDpi; 174 mInfo.xDpi = mDensityDpi; 175 mInfo.yDpi = mDensityDpi; 176 mInfo.flags = 0; 177 if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { 178 mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE 179 | DisplayDeviceInfo.FLAG_NEVER_BLANK 180 | DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; 181 } else if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { 182 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; 183 } 184 if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 185 mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; 186 } 187 if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { 188 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; 189 } 190 mInfo.type = Display.TYPE_VIRTUAL; 191 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; 192 mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF; 193 mInfo.ownerUid = mOwnerUid; 194 mInfo.ownerPackageName = mOwnerPackageName; 195 } 196 return mInfo; 197 } 198 } 199} 200