Home | History | Annotate | Download | only in display
      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