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