/* * 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 android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.display.IDisplayManager; import android.os.Binder; import android.os.SystemProperties; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; /** * Manages the properties, media routing and power state of attached displays. *

* The display manager service does not own or directly control the displays. * Instead, other components in the system register their display adapters with the * display manager service which acts as a central controller. *

*/ public final class DisplayManagerService extends IDisplayManager.Stub { private static final String TAG = "DisplayManagerService"; private static final String SYSTEM_HEADLESS = "ro.config.headless"; private final Object mLock = new Object(); private final Context mContext; private final boolean mHeadless; private final ArrayList mDisplayAdapters = new ArrayList(); private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo(); public DisplayManagerService(Context context) { mContext = context; mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); registerDefaultDisplayAdapter(); } private void registerDefaultDisplayAdapter() { if (mHeadless) { registerDisplayAdapter(new HeadlessDisplayAdapter(mContext)); } else { registerDisplayAdapter(new SurfaceFlingerDisplayAdapter(mContext)); } } // FIXME: this isn't the right API for the long term public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) { // hardcoded assuming 720p touch screen plugged into HDMI and USB // need to redesign this info.width = 1280; info.height = 720; } /** * Returns true if the device is headless. * * @return True if the device is headless. */ public boolean isHeadless() { return mHeadless; } /** * Save away new DisplayInfo data. * @param displayId The local DisplayInfo to store the new data in. * @param info The new data to be stored. */ public void setDisplayInfo(int displayId, DisplayInfo info) { synchronized (mLock) { if (displayId != Display.DEFAULT_DISPLAY) { throw new UnsupportedOperationException(); } mDefaultDisplayInfo.copyFrom(info); } } /** * Return requested DisplayInfo. * @param displayId The data to retrieve. * @param outInfo The structure to receive the data. */ @Override // Binder call public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) { synchronized (mLock) { if (displayId != Display.DEFAULT_DISPLAY) { return false; } outInfo.copyFrom(mDefaultDisplayInfo); return true; } } private void registerDisplayAdapter(DisplayAdapter adapter) { mDisplayAdapters.add(adapter); adapter.register(new DisplayAdapter.Listener() { @Override public void onDisplayDeviceAdded(DisplayDevice device) { DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); device.getInfo(deviceInfo); copyDisplayInfoFromDeviceInfo(mDefaultDisplayInfo, deviceInfo); } @Override public void onDisplayDeviceRemoved(DisplayDevice device) { } }); } private void copyDisplayInfoFromDeviceInfo( DisplayInfo displayInfo, DisplayDeviceInfo deviceInfo) { // Bootstrap the logical display using the physical display. displayInfo.appWidth = deviceInfo.width; displayInfo.appHeight = deviceInfo.height; displayInfo.logicalWidth = deviceInfo.width; displayInfo.logicalHeight = deviceInfo.height; displayInfo.rotation = Surface.ROTATION_0; displayInfo.refreshRate = deviceInfo.refreshRate; displayInfo.logicalDensityDpi = deviceInfo.densityDpi; displayInfo.physicalXDpi = deviceInfo.xDpi; displayInfo.physicalYDpi = deviceInfo.yDpi; displayInfo.smallestNominalAppWidth = deviceInfo.width; displayInfo.smallestNominalAppHeight = deviceInfo.height; displayInfo.largestNominalAppWidth = deviceInfo.width; displayInfo.largestNominalAppHeight = deviceInfo.height; } @Override // Binder call public void dump(FileDescriptor fd, 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)\n"); pw.println("Headless: " + mHeadless); synchronized (mLock) { for (DisplayAdapter adapter : mDisplayAdapters) { pw.println("Adapter: " + adapter.getName()); } pw.println("Default display: " + mDefaultDisplayInfo); } } }