diff options
Diffstat (limited to 'services/java/com/android/server/display/DisplayManagerService.java')
-rw-r--r-- | services/java/com/android/server/display/DisplayManagerService.java | 1312 |
1 files changed, 0 insertions, 1312 deletions
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java deleted file mode 100644 index 73040d5..0000000 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * Copyright (C) 2012 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 com.android.internal.util.IndentingPrintWriter; - -import android.Manifest; -import android.content.Context; -import android.content.pm.PackageManager; -import android.hardware.display.DisplayManager; -import android.hardware.display.DisplayManagerGlobal; -import android.hardware.display.IDisplayManager; -import android.hardware.display.IDisplayManagerCallback; -import android.hardware.display.WifiDisplayStatus; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.text.TextUtils; -import android.util.Log; -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; - -/** - * Manages attached displays. - * <p> - * The {@link DisplayManagerService} manages the global lifecycle of displays, - * decides how to configure logical displays based on the physical display devices currently - * attached, sends notifications to the system and to applications when the state - * changes, and so on. - * </p><p> - * The display manager service relies on a collection of {@link DisplayAdapter} components, - * for discovering and configuring physical display devices attached to the system. - * There are separate display adapters for each manner that devices are attached: - * one display adapter for built-in local displays, one for simulated non-functional - * displays when the system is headless, one for simulated overlay displays used for - * development, one for wifi displays, etc. - * </p><p> - * Display adapters are only weakly coupled to the display manager service. - * Display adapters communicate changes in display device state to the display manager - * service asynchronously via a {@link DisplayAdapter.Listener} registered - * by the display manager service. This separation of concerns is important for - * two main reasons. First, it neatly encapsulates the responsibilities of these - * two classes: display adapters handle individual display devices whereas - * the display manager service handles the global state. Second, it eliminates - * the potential for deadlocks resulting from asynchronous display device discovery. - * </p> - * - * <h3>Synchronization</h3> - * <p> - * Because the display manager may be accessed by multiple threads, the synchronization - * story gets a little complicated. In particular, the window manager may call into - * the display manager while holding a surface transaction with the expectation that - * it can apply changes immediately. Unfortunately, that means we can't just do - * everything asynchronously (*grump*). - * </p><p> - * To make this work, all of the objects that belong to the display manager must - * use the same lock. We call this lock the synchronization root and it has a unique - * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are - * named with the "Locked" suffix. - * </p><p> - * Where things get tricky is that the display manager is not allowed to make - * any potentially reentrant calls, especially into the window manager. We generally - * avoid this by making all potentially reentrant out-calls asynchronous. - * </p> - */ -public final class DisplayManagerService extends IDisplayManager.Stub { - private static final String TAG = "DisplayManagerService"; - private static final boolean DEBUG = false; - - // When this system property is set to 0, WFD is forcibly disabled on boot. - // When this system property is set to 1, WFD is forcibly enabled on boot. - // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. - private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; - - private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; - - private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1; - private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; - private static final int MSG_DELIVER_DISPLAY_EVENT = 3; - private static final int MSG_REQUEST_TRAVERSAL = 4; - private static final int MSG_UPDATE_VIEWPORT = 5; - - private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0; - private static final int DISPLAY_BLANK_STATE_BLANKED = 1; - private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2; - - private final Context mContext; - private final DisplayManagerHandler mHandler; - private final Handler mUiHandler; - private final DisplayAdapterListener mDisplayAdapterListener; - private WindowManagerFuncs mWindowManagerFuncs; - private InputManagerFuncs mInputManagerFuncs; - - // The synchronization root for the display manager. - // This lock guards most of the display manager's state. - // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call - // into WindowManagerService methods that require mWindowMap while holding this unless you are - // very very sure that no deadlock can occur. - private final SyncRoot mSyncRoot = new SyncRoot(); - - // True if in safe mode. - // This option may disable certain display adapters. - public boolean mSafeMode; - - // True if we are in a special boot mode where only core applications and - // services should be started. This option may disable certain display adapters. - public boolean mOnlyCore; - - // True if the display manager service should pretend there is only one display - // and only tell applications about the existence of the default logical display. - // The display manager can still mirror content to secondary displays but applications - // cannot present unique content on those displays. - // Used for demonstration purposes only. - private final boolean mSingleDisplayDemoMode; - - // All callback records indexed by calling process id. - public final SparseArray<CallbackRecord> mCallbacks = - new SparseArray<CallbackRecord>(); - - // List of all currently registered display adapters. - private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); - - // List of all currently connected display devices. - private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>(); - - // List of all logical displays indexed by logical display id. - private final SparseArray<LogicalDisplay> mLogicalDisplays = - new SparseArray<LogicalDisplay>(); - private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; - - // List of all display transaction listeners. - private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = - new CopyOnWriteArrayList<DisplayTransactionListener>(); - - // Set to true if all displays have been blanked by the power manager. - private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN; - - // Set to true when there are pending display changes that have yet to be applied - // to the surface flinger state. - private boolean mPendingTraversal; - - // The Wifi display adapter, or null if not registered. - private WifiDisplayAdapter mWifiDisplayAdapter; - - // The number of active wifi display scan requests. - private int mWifiDisplayScanRequestCount; - - // 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(); - private final DisplayViewport mExternalTouchViewport = new DisplayViewport(); - - // Persistent data store for all internal settings maintained by the display manager service. - private final PersistentDataStore mPersistentDataStore = new PersistentDataStore(); - - // Temporary callback list, used when sending display events to applications. - // May be used outside of the lock but only on the handler thread. - private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); - - // Temporary display info, used for comparing display configurations. - private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); - - // Temporary viewports, used when sending new viewport information to the - // input system. May be used outside of the lock but only on the handler thread. - private final DisplayViewport mTempDefaultViewport = new DisplayViewport(); - private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport(); - - public DisplayManagerService(Context context, Handler mainHandler) { - mContext = context; - mHandler = new DisplayManagerHandler(mainHandler.getLooper()); - mUiHandler = UiThread.getHandler(); - mDisplayAdapterListener = new DisplayAdapterListener(); - mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); - - mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); - } - - /** - * Pauses the boot process to wait for the first display to be initialized. - */ - public boolean waitForDefaultDisplay() { - synchronized (mSyncRoot) { - long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; - while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) { - long delay = timeout - SystemClock.uptimeMillis(); - if (delay <= 0) { - return false; - } - if (DEBUG) { - Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); - } - try { - mSyncRoot.wait(delay); - } catch (InterruptedException ex) { - } - } - } - return true; - } - - /** - * Called during initialization to associate the display manager with the - * window manager. - */ - public void setWindowManager(WindowManagerFuncs windowManagerFuncs) { - synchronized (mSyncRoot) { - mWindowManagerFuncs = windowManagerFuncs; - scheduleTraversalLocked(false); - } - } - - /** - * Called during initialization to associate the display manager with the - * input manager. - */ - public void setInputManager(InputManagerFuncs inputManagerFuncs) { - synchronized (mSyncRoot) { - mInputManagerFuncs = inputManagerFuncs; - scheduleTraversalLocked(false); - } - } - - /** - * Called when the system is ready to go. - */ - public void systemReady(boolean safeMode, boolean onlyCore) { - synchronized (mSyncRoot) { - mSafeMode = safeMode; - mOnlyCore = onlyCore; - } - - mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); - } - - /** - * Registers a display transaction listener to provide the client a chance to - * update its surfaces within the same transaction as any display layout updates. - * - * @param listener The listener to register. - */ - public void registerDisplayTransactionListener(DisplayTransactionListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - - // List is self-synchronized copy-on-write. - mDisplayTransactionListeners.add(listener); - } - - /** - * Unregisters a display transaction listener to provide the client a chance to - * update its surfaces within the same transaction as any display layout updates. - * - * @param listener The listener to unregister. - */ - public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - - // List is self-synchronized copy-on-write. - mDisplayTransactionListeners.remove(listener); - } - - /** - * Overrides the display information of a particular logical display. - * This is used by the window manager to control the size and characteristics - * of the default display. It is expected to apply the requested change - * to the display information synchronously so that applications will immediately - * observe the new state. - * - * NOTE: This method must be the only entry point by which the window manager - * influences the logical configuration of displays. - * - * @param displayId The logical display id. - * @param info The new data to be stored. - */ - public void setDisplayInfoOverrideFromWindowManager( - int displayId, DisplayInfo info) { - synchronized (mSyncRoot) { - LogicalDisplay display = mLogicalDisplays.get(displayId); - if (display != null) { - if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { - sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); - scheduleTraversalLocked(false); - } - } - } - } - - /** - * Called by the window manager to perform traversals while holding a - * surface flinger transaction. - */ - public void performTraversalInTransactionFromWindowManager() { - synchronized (mSyncRoot) { - if (!mPendingTraversal) { - return; - } - mPendingTraversal = false; - - performTraversalInTransactionLocked(); - } - - // List is self-synchronized copy-on-write. - for (DisplayTransactionListener listener : mDisplayTransactionListeners) { - listener.onDisplayTransaction(); - } - } - - /** - * Called by the power manager to blank all displays. - */ - public void blankAllDisplaysFromPowerManager() { - synchronized (mSyncRoot) { - if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) { - mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED; - updateAllDisplayBlankingLocked(); - scheduleTraversalLocked(false); - } - } - } - - /** - * Called by the power manager to unblank all displays. - */ - public void unblankAllDisplaysFromPowerManager() { - synchronized (mSyncRoot) { - if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) { - mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED; - updateAllDisplayBlankingLocked(); - scheduleTraversalLocked(false); - } - } - } - - /** - * Returns information about the specified logical display. - * - * @param displayId The logical display id. - * @return The logical display info, or null if the display does not exist. The - * returned object must be treated as immutable. - */ - @Override // Binder call - public DisplayInfo getDisplayInfo(int displayId) { - 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; - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** - * Returns the list of all display ids. - */ - @Override // Binder call - public int[] getDisplayIds() { - 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; - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public void registerCallback(IDisplayManagerCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("listener must not be null"); - } - - synchronized (mSyncRoot) { - int callingPid = Binder.getCallingPid(); - if (mCallbacks.get(callingPid) != null) { - throw new SecurityException("The calling process has already " - + "registered an IDisplayManagerCallback."); - } - - CallbackRecord record = new CallbackRecord(callingPid, callback); - try { - IBinder binder = callback.asBinder(); - binder.linkToDeath(record, 0); - } catch (RemoteException ex) { - // give up - throw new RuntimeException(ex); - } - - mCallbacks.put(callingPid, record); - } - } - - private void onCallbackDied(CallbackRecord record) { - synchronized (mSyncRoot) { - mCallbacks.remove(record.mPid); - stopWifiDisplayScanLocked(record); - } - } - - @Override // Binder call - public void startWifiDisplayScan() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to start wifi display scans"); - - final int callingPid = Binder.getCallingPid(); - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - CallbackRecord record = mCallbacks.get(callingPid); - if (record == null) { - throw new IllegalStateException("The calling process has not " - + "registered an IDisplayManagerCallback."); - } - startWifiDisplayScanLocked(record); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private void startWifiDisplayScanLocked(CallbackRecord record) { - if (!record.mWifiDisplayScanRequested) { - record.mWifiDisplayScanRequested = true; - if (mWifiDisplayScanRequestCount++ == 0) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestStartScanLocked(); - } - } - } - } - - @Override // Binder call - public void stopWifiDisplayScan() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to stop wifi display scans"); - - final int callingPid = Binder.getCallingPid(); - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - CallbackRecord record = mCallbacks.get(callingPid); - if (record == null) { - throw new IllegalStateException("The calling process has not " - + "registered an IDisplayManagerCallback."); - } - stopWifiDisplayScanLocked(record); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private void stopWifiDisplayScanLocked(CallbackRecord record) { - if (record.mWifiDisplayScanRequested) { - record.mWifiDisplayScanRequested = false; - if (--mWifiDisplayScanRequestCount == 0) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestStopScanLocked(); - } - } else if (mWifiDisplayScanRequestCount < 0) { - Log.wtf(TAG, "mWifiDisplayScanRequestCount became negative: " - + mWifiDisplayScanRequestCount); - mWifiDisplayScanRequestCount = 0; - } - } - } - - @Override // Binder call - public void connectWifiDisplay(String address) { - if (address == null) { - throw new IllegalArgumentException("address must not be null"); - } - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to connect to a wifi display"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestConnectLocked(address); - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void pauseWifiDisplay() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to pause a wifi display session"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestPauseLocked(); - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void resumeWifiDisplay() { - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to resume a wifi display session"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestResumeLocked(); - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public void disconnectWifiDisplay() { - // This request does not require special permissions. - // Any app can request disconnection from the currently active wifi display. - // This exception should no longer be needed once wifi display control moves - // to the media router service. - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestDisconnectLocked(); - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public void renameWifiDisplay(String address, String alias) { - if (address == null) { - throw new IllegalArgumentException("address must not be null"); - } - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to rename to a wifi display"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestRenameLocked(address, alias); - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public void forgetWifiDisplay(String address) { - if (address == null) { - throw new IllegalArgumentException("address must not be null"); - } - mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, - "Permission required to forget to a wifi display"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestForgetLocked(address); - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public WifiDisplayStatus getWifiDisplayStatus() { - // This request does not require special permissions. - // Any app can get information about available wifi displays. - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mSyncRoot) { - if (mWifiDisplayAdapter != null) { - return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); - } - return new WifiDisplayStatus(); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public int createVirtualDisplay(IBinder appToken, String packageName, - String name, int width, int height, int densityDpi, Surface surface, int flags) { - 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"); - } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { - if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) - != PackageManager.PERMISSION_GRANTED - && mContext.checkCallingPermission( - android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " - + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a " - + "public virtual display."); - } - } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { - if (mContext.checkCallingPermission( - android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " - + "to create a secure virtual display."); - } - } - - 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.createVirtualDisplayLocked( - appToken, callingUid, packageName, name, width, height, densityDpi, - surface, flags); - 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 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) { - registerDisplayAdapterLocked(new LocalDisplayAdapter( - mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); - } - } - - private void registerAdditionalDisplayAdapters() { - synchronized (mSyncRoot) { - if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { - registerOverlayDisplayAdapterLocked(); - registerWifiDisplayAdapterLocked(); - registerVirtualDisplayAdapterLocked(); - } - } - } - - private void registerOverlayDisplayAdapterLocked() { - registerDisplayAdapterLocked(new OverlayDisplayAdapter( - mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler)); - } - - private void registerWifiDisplayAdapterLocked() { - if (mContext.getResources().getBoolean( - com.android.internal.R.bool.config_enableWifiDisplay) - || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { - mWifiDisplayAdapter = new WifiDisplayAdapter( - mSyncRoot, mContext, mHandler, mDisplayAdapterListener, - mPersistentDataStore); - registerDisplayAdapterLocked(mWifiDisplayAdapter); - } - } - - 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 - // system stability. - // In only-core mode, we disable non-essential display adapters to minimize - // the number of dependencies that are started while in this mode and to - // prevent problems that might occur due to the device being encrypted. - return !mSafeMode && !mOnlyCore; - } - - private void registerDisplayAdapterLocked(DisplayAdapter adapter) { - mDisplayAdapters.add(adapter); - adapter.registerLocked(); - } - - private void handleDisplayDeviceAdded(DisplayDevice device) { - synchronized (mSyncRoot) { - handleDisplayDeviceAddedLocked(device); - } - } - - private void handleDisplayDeviceAddedLocked(DisplayDevice device) { - if (mDisplayDevices.contains(device)) { - Slog.w(TAG, "Attempted to add already added display device: " - + device.getDisplayDeviceInfoLocked()); - return; - } - - Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); - - mDisplayDevices.add(device); - addLogicalDisplayLocked(device); - updateDisplayBlankingLocked(device); - scheduleTraversalLocked(false); - } - - private void handleDisplayDeviceChanged(DisplayDevice device) { - synchronized (mSyncRoot) { - if (!mDisplayDevices.contains(device)) { - Slog.w(TAG, "Attempted to change non-existent display device: " - + device.getDisplayDeviceInfoLocked()); - return; - } - - Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); - - device.applyPendingDisplayDeviceInfoChangesLocked(); - if (updateLogicalDisplaysLocked()) { - scheduleTraversalLocked(false); - } - } - } - - private void handleDisplayDeviceRemoved(DisplayDevice device) { - synchronized (mSyncRoot) { - 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()); - - 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; - } - } - } - - // Adds a new logical display based on the given display device. - // Sends notifications if needed. - private void addLogicalDisplayLocked(DisplayDevice device) { - DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); - boolean isDefault = (deviceInfo.flags - & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; - if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { - Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); - isDefault = false; - } - - if (!isDefault && mSingleDisplayDemoMode) { - Slog.i(TAG, "Not creating a logical display for a secondary display " - + " because single display demo mode is enabled: " + deviceInfo); - return; - } - - final int displayId = assignDisplayIdLocked(isDefault); - final int layerStack = assignLayerStackLocked(displayId); - - LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); - display.updateLocked(mDisplayDevices); - if (!display.isValidLocked()) { - // This should never happen currently. - Slog.w(TAG, "Ignoring display device because the logical display " - + "created from it was not considered valid: " + deviceInfo); - return; - } - - mLogicalDisplays.put(displayId, display); - - // Wake up waitForDefaultDisplay. - if (isDefault) { - mSyncRoot.notifyAll(); - } - - sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); - } - - private int assignDisplayIdLocked(boolean isDefault) { - return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; - } - - private int assignLayerStackLocked(int displayId) { - // Currently layer stacks and display ids are the same. - // This need not be the case. - return displayId; - } - - // Updates all existing logical displays given the current set of display devices. - // Removes invalid logical displays. - // Sends notifications if needed. - private boolean updateLogicalDisplaysLocked() { - boolean changed = false; - for (int i = mLogicalDisplays.size(); i-- > 0; ) { - final int displayId = mLogicalDisplays.keyAt(i); - LogicalDisplay display = mLogicalDisplays.valueAt(i); - - mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); - display.updateLocked(mDisplayDevices); - if (!display.isValidLocked()) { - mLogicalDisplays.removeAt(i); - sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); - changed = true; - } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { - sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); - changed = true; - } - } - return changed; - } - - private void performTraversalInTransactionLocked() { - // Clear all viewports before configuring displays so that we can keep - // track of which ones we have configured. - clearViewportsLocked(); - - // Configure each display device. - final int count = mDisplayDevices.size(); - for (int i = 0; i < count; i++) { - DisplayDevice device = mDisplayDevices.get(i); - configureDisplayInTransactionLocked(device); - device.performTraversalInTransactionLocked(); - } - - // Tell the input system about these new viewports. - if (mInputManagerFuncs != null) { - mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); - } - } - - /** - * Tells the display manager whether there is interesting unique content on the - * specified logical display. This is used to control automatic mirroring. - * <p> - * If the display has unique content, then the display manager arranges for it - * to be presented on a physical display if appropriate. Otherwise, the display manager - * may choose to make the physical display mirror some other logical display. - * </p> - * - * @param displayId The logical display id to update. - * @param hasContent True if the logical display has content. - * @param inTraversal True if called from WindowManagerService during a window traversal prior - * to call to performTraversalInTransactionFromWindowManager. - */ - public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) { - synchronized (mSyncRoot) { - LogicalDisplay display = mLogicalDisplays.get(displayId); - if (display != null && display.hasContentLocked() != hasContent) { - if (DEBUG) { - Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " - + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); - } - - display.setHasContentLocked(hasContent); - scheduleTraversalLocked(inTraversal); - } - } - } - - private void clearViewportsLocked() { - mDefaultViewport.valid = false; - mExternalTouchViewport.valid = false; - } - - 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 (!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. - if (display == null) { - // TODO: no logical display for the device, blank it - Slog.w(TAG, "Missing logical display to use for physical display device: " - + device.getDisplayDeviceInfoLocked()); - return; - } - boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED) - && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0; - display.configureDisplayInTransactionLocked(device, isBlanked); - - // Update the viewports if needed. - if (!mDefaultViewport.valid - && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { - setViewportLocked(mDefaultViewport, display, device); - } - if (!mExternalTouchViewport.valid - && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { - setViewportLocked(mExternalTouchViewport, display, device); - } - } - - private static void setViewportLocked(DisplayViewport viewport, - LogicalDisplay display, DisplayDevice device) { - viewport.valid = true; - viewport.displayId = display.getDisplayIdLocked(); - device.populateViewportLocked(viewport); - } - - private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { - final int count = mLogicalDisplays.size(); - for (int i = 0; i < count; i++) { - LogicalDisplay display = mLogicalDisplays.valueAt(i); - if (display.getPrimaryDisplayDeviceLocked() == device) { - return display; - } - } - return null; - } - - private void sendDisplayEventLocked(int displayId, int event) { - Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); - mHandler.sendMessage(msg); - } - - // Requests that performTraversalsInTransactionFromWindowManager be called at a - // later time to apply changes to surfaces and displays. - private void scheduleTraversalLocked(boolean inTraversal) { - if (!mPendingTraversal && mWindowManagerFuncs != null) { - mPendingTraversal = true; - if (!inTraversal) { - mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); - } - } - } - - // Runs on Handler thread. - // Delivers display event notifications to callbacks. - private void deliverDisplayEvent(int displayId, int event) { - if (DEBUG) { - Slog.d(TAG, "Delivering display event: displayId=" - + displayId + ", event=" + event); - } - - // Grab the lock and copy the callbacks. - final int count; - synchronized (mSyncRoot) { - count = mCallbacks.size(); - mTempCallbacks.clear(); - for (int i = 0; i < count; i++) { - mTempCallbacks.add(mCallbacks.valueAt(i)); - } - } - - // After releasing the lock, send the notifications out. - for (int i = 0; i < count; i++) { - mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); - } - mTempCallbacks.clear(); - } - - @Override // Binder call - public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { - if (mContext == null - || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DisplayManager from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); - return; - } - - pw.println("DISPLAY MANAGER (dumpsys display)"); - - synchronized (mSyncRoot) { - pw.println(" mOnlyCode=" + mOnlyCore); - pw.println(" mSafeMode=" + mSafeMode); - pw.println(" mPendingTraversal=" + mPendingTraversal); - pw.println(" mAllDisplayBlankStateFromPowerManager=" - + mAllDisplayBlankStateFromPowerManager); - pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); - pw.println(" mDefaultViewport=" + mDefaultViewport); - pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); - pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); - pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); - - IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); - ipw.increaseIndent(); - - pw.println(); - pw.println("Display Adapters: size=" + mDisplayAdapters.size()); - for (DisplayAdapter adapter : mDisplayAdapters) { - pw.println(" " + adapter.getName()); - adapter.dumpLocked(ipw); - } - - pw.println(); - pw.println("Display Devices: size=" + mDisplayDevices.size()); - for (DisplayDevice device : mDisplayDevices) { - pw.println(" " + device.getDisplayDeviceInfoLocked()); - device.dumpLocked(ipw); - } - - final int logicalDisplayCount = mLogicalDisplays.size(); - pw.println(); - pw.println("Logical Displays: size=" + logicalDisplayCount); - for (int i = 0; i < logicalDisplayCount; i++) { - int displayId = mLogicalDisplays.keyAt(i); - LogicalDisplay display = mLogicalDisplays.valueAt(i); - pw.println(" Display " + displayId + ":"); - display.dumpLocked(ipw); - } - - final int callbackCount = mCallbacks.size(); - pw.println(); - pw.println("Callbacks: size=" + callbackCount); - for (int i = 0; i < callbackCount; i++) { - CallbackRecord callback = mCallbacks.valueAt(i); - pw.println(" " + i + ": mPid=" + callback.mPid - + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); - } - } - } - - /** - * This is the object that everything in the display manager locks on. - * We make it an inner class within the {@link DisplayManagerService} to so that it is - * clear that the object belongs to the display manager service and that it is - * a unique object with a special purpose. - */ - public static final class SyncRoot { - } - - /** - * Private interface to the window manager. - */ - public interface WindowManagerFuncs { - /** - * Request that the window manager call - * {@link #performTraversalInTransactionFromWindowManager} within a surface - * transaction at a later time. - */ - void requestTraversal(); - } - - /** - * Private interface to the input manager. - */ - public interface InputManagerFuncs { - /** - * Sets information about the displays as needed by the input system. - * The input system should copy this information if required. - */ - void setDisplayViewports(DisplayViewport defaultViewport, - DisplayViewport externalTouchViewport); - } - - private final class DisplayManagerHandler extends Handler { - public DisplayManagerHandler(Looper looper) { - super(looper, null, true /*async*/); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: - registerDefaultDisplayAdapter(); - break; - - case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: - registerAdditionalDisplayAdapters(); - break; - - case MSG_DELIVER_DISPLAY_EVENT: - deliverDisplayEvent(msg.arg1, msg.arg2); - break; - - case MSG_REQUEST_TRAVERSAL: - mWindowManagerFuncs.requestTraversal(); - break; - - case MSG_UPDATE_VIEWPORT: { - synchronized (mSyncRoot) { - mTempDefaultViewport.copyFrom(mDefaultViewport); - mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); - } - mInputManagerFuncs.setDisplayViewports( - mTempDefaultViewport, mTempExternalTouchViewport); - break; - } - } - } - } - - private final class DisplayAdapterListener implements DisplayAdapter.Listener { - @Override - public void onDisplayDeviceEvent(DisplayDevice device, int event) { - switch (event) { - case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: - handleDisplayDeviceAdded(device); - break; - - case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: - handleDisplayDeviceChanged(device); - break; - - case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: - handleDisplayDeviceRemoved(device); - break; - } - } - - @Override - public void onTraversalRequested() { - synchronized (mSyncRoot) { - scheduleTraversalLocked(false); - } - } - } - - private final class CallbackRecord implements DeathRecipient { - public final int mPid; - private final IDisplayManagerCallback mCallback; - - public boolean mWifiDisplayScanRequested; - - public CallbackRecord(int pid, IDisplayManagerCallback callback) { - mPid = pid; - mCallback = callback; - } - - @Override - public void binderDied() { - if (DEBUG) { - Slog.d(TAG, "Display listener for pid " + mPid + " died."); - } - onCallbackDied(this); - } - - public void notifyDisplayEventAsync(int displayId, int event) { - try { - mCallback.onDisplayEvent(displayId, event); - } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify process " - + mPid + " that displays changed, assuming it died.", ex); - binderDied(); - } - } - } -} |