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; 18 19 import android.car.Car; 20 import android.car.CarOccupantZoneManager; 21 import android.car.CarOccupantZoneManager.OccupantZoneInfo; 22 import android.content.Context; 23 import android.hardware.display.DisplayManager.DisplayListener; 24 import android.util.Log; 25 import android.view.Display; 26 27 import com.android.internal.util.Preconditions; 28 29 import java.util.List; 30 31 /** 32 * This class provides a display for instrument cluster renderer. 33 * <p> 34 * By default it will try to provide physical secondary display if it is connected, if secondary 35 * display is not connected during creation of this class then it will wait for the display will 36 * be added. 37 */ 38 public class ClusterDisplayProvider { 39 private static final String TAG = "Cluster.DisplayProvider"; 40 private static final boolean DEBUG = false; 41 42 private final DisplayListener mListener; 43 private final Car mCar; 44 private CarOccupantZoneManager mOccupantZoneManager; 45 46 private int mClusterDisplayId = Display.INVALID_DISPLAY; 47 ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener)48 ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener) { 49 mListener = clusterDisplayListener; 50 mCar = Car.createCar(context, null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER, 51 (car, ready) -> { 52 if (!ready) return; 53 initClusterDisplayProvider(context, (CarOccupantZoneManager) car.getCarManager( 54 Car.CAR_OCCUPANT_ZONE_SERVICE)); 55 }); 56 } 57 release()58 void release() { 59 if (mCar != null && mCar.isConnected()) { 60 mCar.disconnect(); 61 } 62 } 63 initClusterDisplayProvider( Context context, CarOccupantZoneManager occupantZoneManager)64 private void initClusterDisplayProvider( 65 Context context, CarOccupantZoneManager occupantZoneManager) { 66 Preconditions.checkArgument( 67 occupantZoneManager != null,"Can't get CarOccupantZoneManager"); 68 mOccupantZoneManager = occupantZoneManager; 69 checkClusterDisplayAdded(); 70 mOccupantZoneManager.registerOccupantZoneConfigChangeListener( 71 new ClusterDisplayChangeListener()); 72 } 73 checkClusterDisplayAdded()74 private void checkClusterDisplayAdded() { 75 Display clusterDisplay = getClusterDisplay(); 76 if (clusterDisplay != null) { 77 Log.i(TAG, String.format("Found display: %s (id: %d, owner: %s)", 78 clusterDisplay.getName(), clusterDisplay.getDisplayId(), 79 clusterDisplay.getOwnerPackageName())); 80 mClusterDisplayId = clusterDisplay.getDisplayId(); 81 mListener.onDisplayAdded(clusterDisplay.getDisplayId()); 82 } 83 } 84 getClusterDisplay()85 private Display getClusterDisplay() { 86 List<OccupantZoneInfo> zones = mOccupantZoneManager.getAllOccupantZones(); 87 int zones_size = zones.size(); 88 for (int i = 0; i < zones_size; ++i) { 89 OccupantZoneInfo zone = zones.get(i); 90 // Assumes that a Car has only one driver. 91 if (zone.occupantType == CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER) { 92 return mOccupantZoneManager.getDisplayForOccupant( 93 zone, CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER); 94 } 95 } 96 Log.e(TAG, "Can't find the OccupantZoneInfo for driver"); 97 return null; 98 } 99 100 private final class ClusterDisplayChangeListener implements 101 CarOccupantZoneManager.OccupantZoneConfigChangeListener { 102 @Override onOccupantZoneConfigChanged(int changeFlags)103 public void onOccupantZoneConfigChanged(int changeFlags) { 104 if (DEBUG) Log.d(TAG, "onOccupantZoneConfigChanged changeFlags=" + changeFlags); 105 if ((changeFlags & CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_DISPLAY) == 0) { 106 return; 107 } 108 if (mClusterDisplayId == Display.INVALID_DISPLAY) { 109 checkClusterDisplayAdded(); 110 } else { 111 Display clusterDisplay = getClusterDisplay(); 112 if (clusterDisplay == null) { 113 mListener.onDisplayRemoved(mClusterDisplayId); 114 mClusterDisplayId = Display.INVALID_DISPLAY; 115 } 116 } 117 } 118 } 119 120 @Override toString()121 public String toString() { 122 return getClass().getSimpleName() + "{" 123 + " clusterDisplayId = " + mClusterDisplayId 124 + "}"; 125 } 126 }