DisplayManagerService.java revision 848c2dc93b6795e171f3dd6f64ea0be65e2762ca
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.display;
18
19import android.Manifest;
20import android.content.Context;
21import android.content.pm.PackageManager;
22import android.hardware.display.IDisplayManager;
23import android.os.Binder;
24import android.os.SystemProperties;
25import android.view.Display;
26import android.view.DisplayInfo;
27import android.view.Surface;
28
29import java.io.FileDescriptor;
30import java.io.PrintWriter;
31import java.util.ArrayList;
32
33/**
34 * Manages the properties, media routing and power state of attached displays.
35 * <p>
36 * The display manager service does not own or directly control the displays.
37 * Instead, other components in the system register their display adapters with the
38 * display manager service which acts as a central controller.
39 * </p>
40 */
41public final class DisplayManagerService extends IDisplayManager.Stub {
42    private static final String TAG = "DisplayManagerService";
43
44    private static final String SYSTEM_HEADLESS = "ro.config.headless";
45
46    private final Object mLock = new Object();
47
48    private final Context mContext;
49    private final boolean mHeadless;
50
51    private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
52    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
53
54    public DisplayManagerService(Context context) {
55        mContext = context;
56        mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
57
58        registerDefaultDisplayAdapter();
59    }
60
61    private void registerDefaultDisplayAdapter() {
62        if (mHeadless) {
63            registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
64        } else {
65            registerDisplayAdapter(new SurfaceFlingerDisplayAdapter(mContext));
66        }
67    }
68
69    // FIXME: this isn't the right API for the long term
70    public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
71        // hardcoded assuming 720p touch screen plugged into HDMI and USB
72        // need to redesign this
73        info.width = 1280;
74        info.height = 720;
75    }
76
77    /**
78     * Returns true if the device is headless.
79     *
80     * @return True if the device is headless.
81     */
82    public boolean isHeadless() {
83        return mHeadless;
84    }
85
86    /**
87     * Save away new DisplayInfo data.
88     * @param displayId The local DisplayInfo to store the new data in.
89     * @param info The new data to be stored.
90     */
91    public void setDisplayInfo(int displayId, DisplayInfo info) {
92        synchronized (mLock) {
93            if (displayId != Display.DEFAULT_DISPLAY) {
94                throw new UnsupportedOperationException();
95            }
96            mDefaultDisplayInfo.copyFrom(info);
97        }
98    }
99
100    /**
101     * Return requested DisplayInfo.
102     * @param displayId The data to retrieve.
103     * @param outInfo The structure to receive the data.
104     */
105    @Override // Binder call
106    public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) {
107        synchronized (mLock) {
108            if (displayId != Display.DEFAULT_DISPLAY) {
109                return false;
110            }
111            outInfo.copyFrom(mDefaultDisplayInfo);
112            return true;
113        }
114    }
115
116    private void registerDisplayAdapter(DisplayAdapter adapter) {
117        mDisplayAdapters.add(adapter);
118        adapter.register(new DisplayAdapter.Listener() {
119            @Override
120            public void onDisplayDeviceAdded(DisplayDevice device) {
121                DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
122                device.getInfo(deviceInfo);
123                copyDisplayInfoFromDeviceInfo(mDefaultDisplayInfo, deviceInfo);
124            }
125
126            @Override
127            public void onDisplayDeviceRemoved(DisplayDevice device) {
128            }
129        });
130    }
131
132    private void copyDisplayInfoFromDeviceInfo(
133            DisplayInfo displayInfo, DisplayDeviceInfo deviceInfo) {
134        // Bootstrap the logical display using the physical display.
135        displayInfo.appWidth = deviceInfo.width;
136        displayInfo.appHeight = deviceInfo.height;
137        displayInfo.logicalWidth = deviceInfo.width;
138        displayInfo.logicalHeight = deviceInfo.height;
139        displayInfo.rotation = Surface.ROTATION_0;
140        displayInfo.refreshRate = deviceInfo.refreshRate;
141        displayInfo.logicalDensityDpi = deviceInfo.densityDpi;
142        displayInfo.physicalXDpi = deviceInfo.xDpi;
143        displayInfo.physicalYDpi = deviceInfo.yDpi;
144        displayInfo.smallestNominalAppWidth = deviceInfo.width;
145        displayInfo.smallestNominalAppHeight = deviceInfo.height;
146        displayInfo.largestNominalAppWidth = deviceInfo.width;
147        displayInfo.largestNominalAppHeight = deviceInfo.height;
148    }
149
150    @Override // Binder call
151    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
152        if (mContext == null
153                || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
154                        != PackageManager.PERMISSION_GRANTED) {
155            pw.println("Permission Denial: can't dump DisplayManager from from pid="
156                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
157            return;
158        }
159
160        pw.println("DISPLAY MANAGER (dumpsys display)\n");
161
162        pw.println("Headless: " + mHeadless);
163
164        synchronized (mLock) {
165            for (DisplayAdapter adapter : mDisplayAdapters) {
166                pw.println("Adapter: " + adapter.getName());
167            }
168
169            pw.println("Default display: " + mDefaultDisplayInfo);
170        }
171    }
172}
173