summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/display/DisplayDeviceInfo.java68
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java265
-rw-r--r--services/java/com/android/server/display/LogicalDisplay.java5
-rw-r--r--services/java/com/android/server/display/VirtualDisplayAdapter.java161
-rw-r--r--services/java/com/android/server/wm/DisplayContent.java7
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java15
6 files changed, 447 insertions, 74 deletions
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
index 247d8a0..11f8d6a 100644
--- a/services/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -61,6 +61,18 @@ final class DisplayDeviceInfo {
public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3;
/**
+ * Flag: Indicates that the display device is owned by a particular application
+ * and that no other application should be able to interact with it.
+ */
+ public static final int FLAG_PRIVATE = 1 << 4;
+
+ /**
+ * Flag: Indicates that the display device is not blanked automatically by
+ * the power manager.
+ */
+ public static final int FLAG_NEVER_BLANK = 1 << 5;
+
+ /**
* Touch attachment: Display does not receive touch.
*/
public static final int TOUCH_NONE = 0;
@@ -150,6 +162,23 @@ final class DisplayDeviceInfo {
*/
public String address;
+ /**
+ * The UID of the application that owns this display, or zero if it is owned by the system.
+ * <p>
+ * If the display is private, then only the owner can use it.
+ * </p>
+ */
+ public int ownerUid;
+
+ /**
+ * The package name of the application that owns this display, or null if it is
+ * owned by the system.
+ * <p>
+ * If the display is private, then only the owner can use it.
+ * </p>
+ */
+ public String ownerPackageName;
+
public void setAssumedDensityForExternalDisplay(int width, int height) {
densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
// Technically, these values should be smaller than the apparent density
@@ -176,7 +205,9 @@ final class DisplayDeviceInfo {
&& touch == other.touch
&& rotation == other.rotation
&& type == other.type
- && Objects.equal(address, other.address);
+ && Objects.equal(address, other.address)
+ && ownerUid == other.ownerUid
+ && Objects.equal(ownerPackageName, other.ownerPackageName);
}
@Override
@@ -197,19 +228,32 @@ final class DisplayDeviceInfo {
rotation = other.rotation;
type = other.type;
address = other.address;
+ ownerUid = other.ownerUid;
+ ownerPackageName = other.ownerPackageName;
}
// For debugging purposes
@Override
public String toString() {
- return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", "
- + refreshRate + " fps, "
- + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"
- + ", touch " + touchToString(touch) + flagsToString(flags)
- + ", rotation " + rotation
- + ", type " + Display.typeToString(type)
- + ", address " + address
- + "}";
+ StringBuilder sb = new StringBuilder();
+ sb.append("DisplayDeviceInfo{\"");
+ sb.append(name).append("\": ").append(width).append(" x ").append(height);
+ sb.append(", ").append(refreshRate).append(" fps, ");
+ sb.append("density ").append(densityDpi);
+ sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
+ sb.append(", touch ").append(touchToString(touch));
+ sb.append(", rotation ").append(rotation);
+ sb.append(", type ").append(Display.typeToString(type));
+ if (address != null) {
+ sb.append(", address ").append(address);
+ }
+ if (ownerUid != 0 || ownerPackageName != null) {
+ sb.append(", owner ").append(ownerPackageName);
+ sb.append(" (uid ").append(ownerUid).append(")");
+ }
+ sb.append(flagsToString(flags));
+ sb.append("}");
+ return sb.toString();
}
private static String touchToString(int touch) {
@@ -239,6 +283,12 @@ final class DisplayDeviceInfo {
if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
}
+ if ((flags & FLAG_PRIVATE) != 0) {
+ msg.append(", FLAG_PRIVATE");
+ }
+ if ((flags & FLAG_NEVER_BLANK) != 0) {
+ msg.append(", FLAG_NEVER_BLANK");
+ }
return msg.toString();
}
}
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index ca85e42..c339c26 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -33,15 +33,19 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
+
import com.android.server.UiThread;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -171,6 +175,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
// The Wifi display adapter, or null if not registered.
private WifiDisplayAdapter mWifiDisplayAdapter;
+ // The virtual display adapter, or null if not registered.
+ private VirtualDisplayAdapter mVirtualDisplayAdapter;
+
// Viewports of the default display and the display that should receive touch
// input from an external source. Used by the input system.
private final DisplayViewport mDefaultViewport = new DisplayViewport();
@@ -363,13 +370,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
synchronized (mSyncRoot) {
if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
-
- final int count = mDisplayDevices.size();
- for (int i = 0; i < count; i++) {
- DisplayDevice device = mDisplayDevices.get(i);
- device.blankLocked();
- }
-
+ updateAllDisplayBlankingLocked();
scheduleTraversalLocked(false);
}
}
@@ -382,13 +383,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
synchronized (mSyncRoot) {
if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
-
- final int count = mDisplayDevices.size();
- for (int i = 0; i < count; i++) {
- DisplayDevice device = mDisplayDevices.get(i);
- device.unblankLocked();
- }
-
+ updateAllDisplayBlankingLocked();
scheduleTraversalLocked(false);
}
}
@@ -403,12 +398,21 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
*/
@Override // Binder call
public DisplayInfo getDisplayInfo(int displayId) {
- synchronized (mSyncRoot) {
- LogicalDisplay display = mLogicalDisplays.get(displayId);
- if (display != null) {
- return display.getDisplayInfoLocked();
+ final int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ DisplayInfo info = display.getDisplayInfoLocked();
+ if (info.hasAccess(callingUid)) {
+ return info;
+ }
+ }
+ return null;
}
- return null;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -417,13 +421,27 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
*/
@Override // Binder call
public int[] getDisplayIds() {
- synchronized (mSyncRoot) {
- final int count = mLogicalDisplays.size();
- int[] displayIds = new int[count];
- for (int i = 0; i < count; i++) {
- displayIds[i] = mLogicalDisplays.keyAt(i);
+ final int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ final int count = mLogicalDisplays.size();
+ int[] displayIds = new int[count];
+ int n = 0;
+ for (int i = 0; i < count; i++) {
+ LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ DisplayInfo info = display.getDisplayInfoLocked();
+ if (info.hasAccess(callingUid)) {
+ displayIds[n++] = mLogicalDisplays.keyAt(i);
+ }
+ }
+ if (n != count) {
+ displayIds = Arrays.copyOfRange(displayIds, 0, n);
+ }
+ return displayIds;
}
- return displayIds;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -570,6 +588,95 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
== PackageManager.PERMISSION_GRANTED;
}
+ @Override // Binder call
+ public int createPrivateVirtualDisplay(IBinder appToken, String packageName,
+ String name, int width, int height, int densityDpi, Surface surface) {
+ final int callingUid = Binder.getCallingUid();
+ if (!validatePackageName(callingUid, packageName)) {
+ throw new SecurityException("packageName must match the calling uid");
+ }
+ if (appToken == null) {
+ throw new IllegalArgumentException("appToken must not be null");
+ }
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must be non-null and non-empty");
+ }
+ if (width <= 0 || height <= 0 || densityDpi <= 0) {
+ throw new IllegalArgumentException("width, height, and densityDpi must be "
+ + "greater than 0");
+ }
+ if (surface == null) {
+ throw new IllegalArgumentException("surface must not be null");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ Slog.w(TAG, "Rejecting request to create private virtual display "
+ + "because the virtual display adapter is not available.");
+ return -1;
+ }
+
+ DisplayDevice device = mVirtualDisplayAdapter.createPrivateVirtualDisplayLocked(
+ appToken, callingUid, packageName, name, width, height, densityDpi,
+ surface);
+ if (device == null) {
+ return -1;
+ }
+
+ handleDisplayDeviceAddedLocked(device);
+ LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
+ if (display != null) {
+ return display.getDisplayIdLocked();
+ }
+
+ // Something weird happened and the logical display was not created.
+ Slog.w(TAG, "Rejecting request to create private virtual display "
+ + "because the logical display was not created.");
+ mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
+ handleDisplayDeviceRemovedLocked(device);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return -1;
+ }
+
+ @Override // Binder call
+ public void releaseVirtualDisplay(IBinder appToken) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ return;
+ }
+
+ DisplayDevice device =
+ mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
+ if (device != null) {
+ handleDisplayDeviceRemovedLocked(device);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private boolean validatePackageName(int uid, String packageName) {
+ if (packageName != null) {
+ String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+ if (packageNames != null) {
+ for (String n : packageNames) {
+ if (n.equals(packageName)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
private void registerDefaultDisplayAdapter() {
// Register default display adapter.
synchronized (mSyncRoot) {
@@ -588,6 +695,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
registerOverlayDisplayAdapterLocked();
registerWifiDisplayAdapterLocked();
+ registerVirtualDisplayAdapterLocked();
}
}
}
@@ -608,6 +716,12 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
}
+ private void registerVirtualDisplayAdapterLocked() {
+ mVirtualDisplayAdapter = new VirtualDisplayAdapter(
+ mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
+ registerDisplayAdapterLocked(mVirtualDisplayAdapter);
+ }
+
private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
// In safe mode, we disable non-essential display adapters to give the user
// an opportunity to fix broken settings or other problems that might affect
@@ -625,29 +739,23 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
private void handleDisplayDeviceAdded(DisplayDevice device) {
synchronized (mSyncRoot) {
- if (mDisplayDevices.contains(device)) {
- Slog.w(TAG, "Attempted to add already added display device: "
- + device.getDisplayDeviceInfoLocked());
- return;
- }
+ handleDisplayDeviceAddedLocked(device);
+ }
+ }
- Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
+ private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
+ if (mDisplayDevices.contains(device)) {
+ Slog.w(TAG, "Attempted to add already added display device: "
+ + device.getDisplayDeviceInfoLocked());
+ return;
+ }
- mDisplayDevices.add(device);
- addLogicalDisplayLocked(device);
- scheduleTraversalLocked(false);
+ Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
- // Blank or unblank the display immediately to match the state requested
- // by the power manager (if known).
- switch (mAllDisplayBlankStateFromPowerManager) {
- case DISPLAY_BLANK_STATE_BLANKED:
- device.blankLocked();
- break;
- case DISPLAY_BLANK_STATE_UNBLANKED:
- device.unblankLocked();
- break;
- }
- }
+ mDisplayDevices.add(device);
+ addLogicalDisplayLocked(device);
+ updateDisplayBlankingLocked(device);
+ scheduleTraversalLocked(false);
}
private void handleDisplayDeviceChanged(DisplayDevice device) {
@@ -669,17 +777,44 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
private void handleDisplayDeviceRemoved(DisplayDevice device) {
synchronized (mSyncRoot) {
- if (!mDisplayDevices.remove(device)) {
- Slog.w(TAG, "Attempted to remove non-existent display device: "
- + device.getDisplayDeviceInfoLocked());
- return;
- }
+ handleDisplayDeviceRemovedLocked(device);
+ }
+ }
+ private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
+ if (!mDisplayDevices.remove(device)) {
+ Slog.w(TAG, "Attempted to remove non-existent display device: "
+ + device.getDisplayDeviceInfoLocked());
+ return;
+ }
- Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
+ Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
- mRemovedDisplayDevices.add(device);
- updateLogicalDisplaysLocked();
- scheduleTraversalLocked(false);
+ mRemovedDisplayDevices.add(device);
+ updateLogicalDisplaysLocked();
+ scheduleTraversalLocked(false);
+ }
+
+ private void updateAllDisplayBlankingLocked() {
+ final int count = mDisplayDevices.size();
+ for (int i = 0; i < count; i++) {
+ DisplayDevice device = mDisplayDevices.get(i);
+ updateDisplayBlankingLocked(device);
+ }
+ }
+
+ private void updateDisplayBlankingLocked(DisplayDevice device) {
+ // Blank or unblank the display immediately to match the state requested
+ // by the power manager (if known).
+ DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
+ if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
+ switch (mAllDisplayBlankStateFromPowerManager) {
+ case DISPLAY_BLANK_STATE_BLANKED:
+ device.blankLocked();
+ break;
+ case DISPLAY_BLANK_STATE_UNBLANKED:
+ device.unblankLocked();
+ break;
+ }
}
}
@@ -812,13 +947,21 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
private void configureDisplayInTransactionLocked(DisplayDevice device) {
+ DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
+ boolean isPrivate = (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0;
+
// Find the logical display that the display device is showing.
+ // Private displays never mirror other displays.
LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
- if (display != null && !display.hasContentLocked()) {
- display = null;
- }
- if (display == null) {
- display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
+ if (!isPrivate) {
+ if (display != null && !display.hasContentLocked()) {
+ // If the display does not have any content of its own, then
+ // automatically mirror the default logical display contents.
+ display = null;
+ }
+ if (display == null) {
+ display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
+ }
}
// Apply the logical display configuration to the display device.
@@ -828,11 +971,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
+ device.getDisplayDeviceInfoLocked());
return;
}
- boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED);
+ boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED)
+ && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0;
display.configureDisplayInTransactionLocked(device, isBlanked);
// Update the viewports if needed.
- DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if (!mDefaultViewport.valid
&& (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
setViewportLocked(mDefaultViewport, display, device);
diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java
index 424ec36..775ebb2 100644
--- a/services/java/com/android/server/display/LogicalDisplay.java
+++ b/services/java/com/android/server/display/LogicalDisplay.java
@@ -202,6 +202,9 @@ final class LogicalDisplay {
if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) {
mBaseDisplayInfo.flags |= Display.FLAG_SECURE;
}
+ if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) {
+ mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE;
+ }
mBaseDisplayInfo.type = deviceInfo.type;
mBaseDisplayInfo.address = deviceInfo.address;
mBaseDisplayInfo.name = deviceInfo.name;
@@ -218,6 +221,8 @@ final class LogicalDisplay {
mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height;
+ mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
+ mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;
mPrimaryDisplayDeviceInfo = deviceInfo;
mInfo = null;
diff --git a/services/java/com/android/server/display/VirtualDisplayAdapter.java b/services/java/com/android/server/display/VirtualDisplayAdapter.java
new file mode 100644
index 0000000..634fba7
--- /dev/null
+++ b/services/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -0,0 +1,161 @@
+/*
+ * 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.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 createPrivateVirtualDisplayLocked(IBinder appToken,
+ int ownerUid, String ownerPackageName,
+ String name, int width, int height, int densityDpi, Surface surface) {
+ IBinder displayToken = SurfaceControl.createDisplay(name, false /*secure*/);
+ VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
+ ownerUid, ownerPackageName, name, width, height, densityDpi, surface);
+
+ try {
+ appToken.linkToDeath(device, 0);
+ } catch (RemoteException ex) {
+ device.releaseLocked();
+ 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) {
+ 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);
+ 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 boolean mReleased;
+ 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) {
+ super(VirtualDisplayAdapter.this, displayToken);
+ mAppToken = appToken;
+ mOwnerUid = ownerUid;
+ mOwnerPackageName = ownerPackageName;
+ mName = name;
+ mWidth = width;
+ mHeight = height;
+ mDensityDpi = densityDpi;
+ mSurface = surface;
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (getSyncRoot()) {
+ if (!mReleased) {
+ handleBinderDiedLocked(mAppToken);
+ }
+ }
+ }
+
+ public void releaseLocked() {
+ mReleased = true;
+ sendTraversalRequestLocked();
+ }
+
+ @Override
+ public void performTraversalInTransactionLocked() {
+ if (mReleased && mSurface != null) {
+ mSurface.destroy();
+ 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 = DisplayDeviceInfo.FLAG_PRIVATE | DisplayDeviceInfo.FLAG_NEVER_BLANK;
+ mInfo.type = Display.TYPE_VIRTUAL;
+ mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+ mInfo.ownerUid = mOwnerUid;
+ mInfo.ownerPackageName = mOwnerPackageName;
+ }
+ return mInfo;
+ }
+ }
+}
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 82e8c7f..feac370 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -140,6 +140,13 @@ class DisplayContent {
return mDisplayInfo;
}
+ /**
+ * Returns true if the specified UID has access to this display.
+ */
+ public boolean hasAccess(int uid) {
+ return mDisplay.hasAccess(uid);
+ }
+
boolean homeOnTop() {
return mStackBoxes.get(0).mStack != mHomeStack;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index faeb37c..afbc4a9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2105,6 +2105,13 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayContent displayContent = getDisplayContentLocked(displayId);
if (displayContent == null) {
+ Slog.w(TAG, "Attempted to add window to a display that does not exist: "
+ + displayId + ". Aborting.");
+ return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+ }
+ if (!displayContent.hasAccess(session.mUid)) {
+ Slog.w(TAG, "Attempted to add window to a display for which the application "
+ + "does not have access: " + displayId + ". Aborting.");
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
@@ -7521,7 +7528,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void getInitialDisplaySize(int displayId, Point size) {
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
+ if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
synchronized(displayContent.mDisplaySizeLock) {
size.x = displayContent.mInitialDisplayWidth;
size.y = displayContent.mInitialDisplayHeight;
@@ -7534,7 +7541,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void getBaseDisplaySize(int displayId, Point size) {
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
+ if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
synchronized(displayContent.mDisplaySizeLock) {
size.x = displayContent.mBaseDisplayWidth;
size.y = displayContent.mBaseDisplayHeight;
@@ -7649,7 +7656,7 @@ public class WindowManagerService extends IWindowManager.Stub
public int getInitialDisplayDensity(int displayId) {
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
+ if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
synchronized(displayContent.mDisplaySizeLock) {
return displayContent.mInitialDisplayDensity;
}
@@ -7662,7 +7669,7 @@ public class WindowManagerService extends IWindowManager.Stub
public int getBaseDisplayDensity(int displayId) {
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
+ if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
synchronized(displayContent.mDisplaySizeLock) {
return displayContent.mBaseDisplayDensity;
}