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 17 package com.android.server.display; 18 19 import android.content.Context; 20 import android.hardware.display.DisplayManager; 21 import android.os.Handler; 22 import android.os.IBinder; 23 import android.os.IBinder.DeathRecipient; 24 import android.os.RemoteException; 25 import android.util.ArrayMap; 26 import android.util.Slog; 27 import android.view.Display; 28 import android.view.Surface; 29 import 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 */ 37 final 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