LocalDisplayAdapter.java revision 9e316a1a2a8d734315bbd56a85308f9657a92913
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.content.Context; 20import android.os.Handler; 21import android.os.IBinder; 22import android.os.Looper; 23import android.util.SparseArray; 24import android.view.DisplayEventReceiver; 25import android.view.Surface; 26import android.view.Surface.PhysicalDisplayInfo; 27 28import java.io.PrintWriter; 29 30/** 31 * A display adapter for the local displays managed by Surface Flinger. 32 * <p> 33 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 34 * </p> 35 */ 36final class LocalDisplayAdapter extends DisplayAdapter { 37 private static final String TAG = "LocalDisplayAdapter"; 38 39 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] { 40 Surface.BUILT_IN_DISPLAY_ID_MAIN, 41 Surface.BUILT_IN_DISPLAY_ID_HDMI, 42 }; 43 44 private final SparseArray<LocalDisplayDevice> mDevices = 45 new SparseArray<LocalDisplayDevice>(); 46 private final HotplugDisplayEventReceiver mHotplugReceiver; 47 48 private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo(); 49 50 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 51 Context context, Handler handler, Listener listener) { 52 super(syncRoot, context, handler, listener, TAG); 53 mHotplugReceiver = new HotplugDisplayEventReceiver(handler.getLooper()); 54 } 55 56 @Override 57 public void registerLocked() { 58 // TODO: listen for notifications from Surface Flinger about 59 // built-in displays being added or removed and rescan as needed. 60 super.registerLocked(); 61 scanDisplaysLocked(); 62 } 63 64 private void scanDisplaysLocked() { 65 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) { 66 IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId); 67 if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) { 68 LocalDisplayDevice device = mDevices.get(builtInDisplayId); 69 if (device == null) { 70 // Display was added. 71 device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys); 72 mDevices.put(builtInDisplayId, device); 73 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED); 74 } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) { 75 // Display properties changed. 76 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED); 77 } 78 } else { 79 LocalDisplayDevice device = mDevices.get(builtInDisplayId); 80 if (device != null) { 81 // Display was removed. 82 mDevices.remove(builtInDisplayId); 83 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); 84 } 85 } 86 } 87 } 88 89 private final class LocalDisplayDevice extends DisplayDevice { 90 private final int mBuiltInDisplayId; 91 private final PhysicalDisplayInfo mPhys; 92 93 private DisplayDeviceInfo mInfo; 94 private boolean mHavePendingChanges; 95 private boolean mBlanked; 96 97 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId, 98 PhysicalDisplayInfo phys) { 99 super(LocalDisplayAdapter.this, displayToken); 100 mBuiltInDisplayId = builtInDisplayId; 101 mPhys = new PhysicalDisplayInfo(phys); 102 } 103 104 public boolean updatePhysicalDisplayInfoLocked(PhysicalDisplayInfo phys) { 105 if (!mPhys.equals(phys)) { 106 mPhys.copyFrom(phys); 107 mHavePendingChanges = true; 108 return true; 109 } 110 return false; 111 } 112 113 @Override 114 public void applyPendingDisplayDeviceInfoChangesLocked() { 115 if (mHavePendingChanges) { 116 mInfo = null; 117 mHavePendingChanges = false; 118 } 119 } 120 121 @Override 122 public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 123 if (mInfo == null) { 124 mInfo = new DisplayDeviceInfo(); 125 mInfo.width = mPhys.width; 126 mInfo.height = mPhys.height; 127 mInfo.refreshRate = mPhys.refreshRate; 128 129 // Assume that all built-in displays have secure output (eg. HDCP) and 130 // support compositing from gralloc protected buffers. 131 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE 132 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 133 134 if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) { 135 mInfo.name = getContext().getResources().getString( 136 com.android.internal.R.string.display_manager_built_in_display_name); 137 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY 138 | DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION; 139 mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f); 140 mInfo.xDpi = mPhys.xDpi; 141 mInfo.yDpi = mPhys.yDpi; 142 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; 143 } else { 144 mInfo.name = getContext().getResources().getString( 145 com.android.internal.R.string.display_manager_hdmi_display_name); 146 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 147 mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height); 148 } 149 } 150 return mInfo; 151 } 152 153 @Override 154 public void blankLocked() { 155 mBlanked = true; 156 Surface.blankDisplay(getDisplayTokenLocked()); 157 } 158 159 @Override 160 public void unblankLocked() { 161 mBlanked = false; 162 Surface.unblankDisplay(getDisplayTokenLocked()); 163 } 164 165 @Override 166 public void dumpLocked(PrintWriter pw) { 167 super.dumpLocked(pw); 168 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId); 169 pw.println("mPhys=" + mPhys); 170 pw.println("mBlanked=" + mBlanked); 171 } 172 } 173 174 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver { 175 public HotplugDisplayEventReceiver(Looper looper) { 176 super(looper); 177 } 178 179 @Override 180 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) { 181 synchronized (getSyncRoot()) { 182 scanDisplaysLocked(); 183 } 184 } 185 } 186}