/* * Copyright (C) 2018 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 android.car.cluster.sample; import android.annotation.Nullable; import android.content.Context; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.text.TextUtils; import android.util.Log; import android.view.Display; /** * This class provides a display for instrument cluster renderer. *

* By default it will try to provide physical secondary display if it is connected, if secondary * display is not connected during creation of this class then it will start networked virtual * display and listens for incoming connections. * * @see {@link NetworkedVirtualDisplay} */ public class ClusterDisplayProvider { private static final String TAG = ClusterDisplayProvider.class.getSimpleName(); private static final int NETWORKED_DISPLAY_WIDTH = 1280; private static final int NETWORKED_DISPLAY_HEIGHT = 720; private static final int NETWORKED_DISPLAY_DPI = 320; private final DisplayListener mListener; private final DisplayManager mDisplayManager; private NetworkedVirtualDisplay mNetworkedVirtualDisplay; private int mClusterDisplayId = -1; ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener) { mListener = clusterDisplayListener; mDisplayManager = context.getSystemService(DisplayManager.class); Display clusterDisplay = getInstrumentClusterDisplay(mDisplayManager); if (clusterDisplay != null) { mClusterDisplayId = clusterDisplay.getDisplayId(); clusterDisplayListener.onDisplayAdded(clusterDisplay.getDisplayId()); trackClusterDisplay(null /* no need to track display by name */); } else { Log.i(TAG, "No physical cluster display found, starting network display"); setupNetworkDisplay(context); } } private void setupNetworkDisplay(Context context) { mNetworkedVirtualDisplay = new NetworkedVirtualDisplay(context, NETWORKED_DISPLAY_WIDTH, NETWORKED_DISPLAY_HEIGHT, NETWORKED_DISPLAY_DPI); String displayName = mNetworkedVirtualDisplay.start(); trackClusterDisplay(displayName); } private void trackClusterDisplay(@Nullable String displayName) { mDisplayManager.registerDisplayListener(new DisplayListener() { @Override public void onDisplayAdded(int displayId) { boolean clusterDisplayAdded = false; if (displayName == null && mClusterDisplayId == -1) { mClusterDisplayId = displayId; clusterDisplayAdded = true; } else { Display display = mDisplayManager.getDisplay(displayId); if (display != null && TextUtils.equals(display.getName(), displayName)) { mClusterDisplayId = displayId; clusterDisplayAdded = true; } } if (clusterDisplayAdded) { mListener.onDisplayAdded(displayId); } } @Override public void onDisplayRemoved(int displayId) { if (displayId == mClusterDisplayId) { mClusterDisplayId = -1; mListener.onDisplayRemoved(displayId); } } @Override public void onDisplayChanged(int displayId) { if (displayId == mClusterDisplayId) { mListener.onDisplayChanged(displayId); } } }, null); } private static Display getInstrumentClusterDisplay(DisplayManager displayManager) { Display[] displays = displayManager.getDisplays(); Log.d(TAG, "There are currently " + displays.length + " displays connected."); if (displays.length > 1) { // TODO: assuming that secondary display is instrument cluster. Put this into settings? // We could use name and ownerPackageName to verify this is the right display. return displays[1]; } return null; } @Override public String toString() { return getClass().getSimpleName() + "{" + " clusterDisplayId = " + mClusterDisplayId + "}"; } }