diff options
Diffstat (limited to 'services/core/java/com/android/server/display/VirtualDisplayAdapter.java')
-rw-r--r-- | services/core/java/com/android/server/display/VirtualDisplayAdapter.java | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java new file mode 100644 index 0000000..46d473c --- /dev/null +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.os.IBinder; +import android.os.IBinder.DeathRecipient; +import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.Slog; +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceControl; + +/** + * A display adapter that provides virtual displays on behalf of applications. + * <p> + * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. + * </p> + */ +final class VirtualDisplayAdapter extends DisplayAdapter { + static final String TAG = "VirtualDisplayAdapter"; + static final boolean DEBUG = false; + + private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices = + new ArrayMap<IBinder, VirtualDisplayDevice>(); + + // Called with SyncRoot lock held. + public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, + Context context, Handler handler, Listener listener) { + super(syncRoot, context, handler, listener, TAG); + } + + public DisplayDevice createVirtualDisplayLocked(IBinder appToken, + int ownerUid, String ownerPackageName, + String name, int width, int height, int densityDpi, Surface surface, int flags) { + boolean secure = (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0; + IBinder displayToken = SurfaceControl.createDisplay(name, secure); + VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken, + ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags); + + try { + appToken.linkToDeath(device, 0); + } catch (RemoteException ex) { + device.destroyLocked(); + return null; + } + + mVirtualDisplayDevices.put(appToken, device); + + // Return the display device without actually sending the event indicating + // that it was added. The caller will handle it. + return device; + } + + public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { + VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); + if (device != null) { + device.destroyLocked(); + appToken.unlinkToDeath(device, 0); + } + + // Return the display device that was removed without actually sending the + // event indicating that it was removed. The caller will handle it. + return device; + } + + private void handleBinderDiedLocked(IBinder appToken) { + VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); + if (device != null) { + Slog.i(TAG, "Virtual display device released because application token died: " + + device.mOwnerPackageName); + device.destroyLocked(); + sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); + } + } + + private final class VirtualDisplayDevice extends DisplayDevice + implements DeathRecipient { + private final IBinder mAppToken; + private final int mOwnerUid; + final String mOwnerPackageName; + private final String mName; + private final int mWidth; + private final int mHeight; + private final int mDensityDpi; + private final int mFlags; + + private Surface mSurface; + private DisplayDeviceInfo mInfo; + + public VirtualDisplayDevice(IBinder displayToken, + IBinder appToken, int ownerUid, String ownerPackageName, + String name, int width, int height, int densityDpi, Surface surface, int flags) { + super(VirtualDisplayAdapter.this, displayToken); + mAppToken = appToken; + mOwnerUid = ownerUid; + mOwnerPackageName = ownerPackageName; + mName = name; + mWidth = width; + mHeight = height; + mDensityDpi = densityDpi; + mSurface = surface; + mFlags = flags; + } + + @Override + public void binderDied() { + synchronized (getSyncRoot()) { + if (mSurface != null) { + handleBinderDiedLocked(mAppToken); + } + } + } + + public void destroyLocked() { + if (mSurface != null) { + mSurface.release(); + mSurface = null; + } + SurfaceControl.destroyDisplay(getDisplayTokenLocked()); + } + + @Override + public void performTraversalInTransactionLocked() { + if (mSurface != null) { + setSurfaceInTransactionLocked(mSurface); + } + } + + @Override + public DisplayDeviceInfo getDisplayDeviceInfoLocked() { + if (mInfo == null) { + mInfo = new DisplayDeviceInfo(); + mInfo.name = mName; + mInfo.width = mWidth; + mInfo.height = mHeight; + mInfo.refreshRate = 60; + mInfo.densityDpi = mDensityDpi; + mInfo.xDpi = mDensityDpi; + mInfo.yDpi = mDensityDpi; + mInfo.flags = 0; + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE | + DisplayDeviceInfo.FLAG_NEVER_BLANK; + } + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; + } + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; + } + mInfo.type = Display.TYPE_VIRTUAL; + mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; + mInfo.ownerUid = mOwnerUid; + mInfo.ownerPackageName = mOwnerPackageName; + } + return mInfo; + } + } +} |