private void dumpInternal(PrintWriter pw) {
    pw.println("DISPLAY MANAGER (dumpsys display)");

    synchronized (mSyncRoot) {
      pw.println("  mOnlyCode=" + mOnlyCore);
      pw.println("  mSafeMode=" + mSafeMode);
      pw.println("  mPendingTraversal=" + mPendingTraversal);
      pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
      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);
      }

      if (mDisplayPowerController != null) {
        mDisplayPowerController.dump(pw);
      }
    }
  }
  private void configureDisplayInTransactionLocked(DisplayDevice device) {
    // Find the logical display that the display device is showing.
    LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
    if (display != null && !display.hasContentLocked()) {
      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;
    } else {
      boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED);
      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);
    }
    if (!mExternalTouchViewport.valid && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
      setViewportLocked(mExternalTouchViewport, display, device);
    }
  }
 /**
  * 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.
  *
  * @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) {
       display.setHasContentLocked(hasContent);
       scheduleTraversalLocked(inTraversal);
     }
   }
 }
 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;
 }
 /**
  * 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) {
   synchronized (mSyncRoot) {
     LogicalDisplay display = mLogicalDisplays.get(displayId);
     if (display != null) {
       return display.getDisplayInfoLocked();
     }
     return null;
   }
 }
  @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("  mHeadless=" + mHeadless);
      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);

      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);
      }
    }
  }
 private void setDisplayInfoOverrideFromWindowManagerInternal(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);
       }
     }
   }
 }
 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
   synchronized (mSyncRoot) {
     LogicalDisplay display = mLogicalDisplays.get(displayId);
     if (display != null) {
       DisplayInfo info = display.getDisplayInfoLocked();
       if (info.hasAccess(callingUid)) {
         return info;
       }
     }
     return null;
   }
 }
 /**
  * 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.
  *
  * @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) {
       mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
       display.setDisplayInfoOverrideFromWindowManagerLocked(info);
       if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
         scheduleTraversalLocked(false);
       }
     }
   }
 }
 private int[] getDisplayIdsInternal(int callingUid) {
   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;
   }
 }
  // 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 int createVirtualDisplayInternal(
      IBinder appToken,
      int callingUid,
      String packageName,
      String name,
      int width,
      int height,
      int densityDpi,
      Surface surface,
      int flags) {
    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);
    }
    return -1;
  }
  // 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 void setDisplayHasContentInternal(
      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 configureDisplayInTransactionLocked(DisplayDevice device) {
    final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;

    // Find the logical display that the display device is showing.
    // Certain displays only ever show their own content.
    LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
    if (!ownContent) {
      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;
    }
    display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);

    // 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);
 }