1 /* 2 * Copyright (C) 2018 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 17 package android.car.cluster.sample; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.hardware.display.DisplayManager; 22 import android.hardware.display.DisplayManager.DisplayListener; 23 import android.text.TextUtils; 24 import android.util.Log; 25 import android.view.Display; 26 27 /** 28 * This class provides a display for instrument cluster renderer. 29 * <p> 30 * By default it will try to provide physical secondary display if it is connected, if secondary 31 * display is not connected during creation of this class then it will start networked virtual 32 * display and listens for incoming connections. 33 * 34 * @see {@link NetworkedVirtualDisplay} 35 */ 36 public class ClusterDisplayProvider { 37 private static final String TAG = ClusterDisplayProvider.class.getSimpleName(); 38 39 private static final int NETWORKED_DISPLAY_WIDTH = 1280; 40 private static final int NETWORKED_DISPLAY_HEIGHT = 720; 41 private static final int NETWORKED_DISPLAY_DPI = 320; 42 43 private final DisplayListener mListener; 44 private final DisplayManager mDisplayManager; 45 46 private NetworkedVirtualDisplay mNetworkedVirtualDisplay; 47 private int mClusterDisplayId = -1; 48 ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener)49 ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener) { 50 mListener = clusterDisplayListener; 51 mDisplayManager = context.getSystemService(DisplayManager.class); 52 53 Display clusterDisplay = getInstrumentClusterDisplay(mDisplayManager); 54 if (clusterDisplay != null) { 55 mClusterDisplayId = clusterDisplay.getDisplayId(); 56 clusterDisplayListener.onDisplayAdded(clusterDisplay.getDisplayId()); 57 trackClusterDisplay(null /* no need to track display by name */); 58 } else { 59 Log.i(TAG, "No physical cluster display found, starting network display"); 60 setupNetworkDisplay(context); 61 } 62 } 63 setupNetworkDisplay(Context context)64 private void setupNetworkDisplay(Context context) { 65 mNetworkedVirtualDisplay = new NetworkedVirtualDisplay(context, 66 NETWORKED_DISPLAY_WIDTH, NETWORKED_DISPLAY_HEIGHT, NETWORKED_DISPLAY_DPI); 67 String displayName = mNetworkedVirtualDisplay.start(); 68 trackClusterDisplay(displayName); 69 } 70 trackClusterDisplay(@ullable String displayName)71 private void trackClusterDisplay(@Nullable String displayName) { 72 mDisplayManager.registerDisplayListener(new DisplayListener() { 73 @Override 74 public void onDisplayAdded(int displayId) { 75 boolean clusterDisplayAdded = false; 76 77 if (displayName == null && mClusterDisplayId == -1) { 78 mClusterDisplayId = displayId; 79 clusterDisplayAdded = true; 80 } else { 81 Display display = mDisplayManager.getDisplay(displayId); 82 if (display != null && TextUtils.equals(display.getName(), displayName)) { 83 mClusterDisplayId = displayId; 84 clusterDisplayAdded = true; 85 } 86 } 87 88 if (clusterDisplayAdded) { 89 mListener.onDisplayAdded(displayId); 90 } 91 } 92 93 @Override 94 public void onDisplayRemoved(int displayId) { 95 if (displayId == mClusterDisplayId) { 96 mClusterDisplayId = -1; 97 mListener.onDisplayRemoved(displayId); 98 } 99 } 100 101 @Override 102 public void onDisplayChanged(int displayId) { 103 if (displayId == mClusterDisplayId) { 104 mListener.onDisplayChanged(displayId); 105 } 106 } 107 108 }, null); 109 } 110 getInstrumentClusterDisplay(DisplayManager displayManager)111 private static Display getInstrumentClusterDisplay(DisplayManager displayManager) { 112 Display[] displays = displayManager.getDisplays(); 113 Log.d(TAG, "There are currently " + displays.length + " displays connected."); 114 115 if (displays.length > 1) { 116 // TODO: assuming that secondary display is instrument cluster. Put this into settings? 117 // We could use name and ownerPackageName to verify this is the right display. 118 return displays[1]; 119 } 120 return null; 121 } 122 123 @Override toString()124 public String toString() { 125 return getClass().getSimpleName() + "{" 126 + " clusterDisplayId = " + mClusterDisplayId 127 + "}"; 128 } 129 } 130