summaryrefslogtreecommitdiff
path: root/DirectRenderingCluster/src/android/car/cluster/ClusterDisplayProvider.java
blob: 40500994840c9d13bc6049aaf309b8d7fc7a82d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * 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;

import android.car.Car;
import android.car.CarOccupantZoneManager;
import android.car.CarOccupantZoneManager.OccupantZoneInfo;
import android.content.Context;
import android.hardware.display.DisplayManager.DisplayListener;
import android.util.Log;
import android.view.Display;

import com.android.internal.util.Preconditions;

import java.util.List;

/**
 * This class provides a display for instrument cluster renderer.
 * <p>
 * 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 wait for the display will
 * be added.
 */
public class ClusterDisplayProvider {
    private static final String TAG = "Cluster.DisplayProvider";
    private static final boolean DEBUG = false;

    private final DisplayListener mListener;
    private final Car mCar;
    private CarOccupantZoneManager mOccupantZoneManager;

    private int mClusterDisplayId = Display.INVALID_DISPLAY;

    ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener) {
        mListener = clusterDisplayListener;
        mCar = Car.createCar(context, null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER,
                (car, ready) -> {
                    if (!ready) return;
                    initClusterDisplayProvider(context, (CarOccupantZoneManager) car.getCarManager(
                            Car.CAR_OCCUPANT_ZONE_SERVICE));
                });
    }

    void release() {
        if (mCar != null && mCar.isConnected()) {
            mCar.disconnect();
        }
    }

    private void initClusterDisplayProvider(
            Context context, CarOccupantZoneManager occupantZoneManager) {
        Preconditions.checkArgument(
                occupantZoneManager != null,"Can't get CarOccupantZoneManager");
        mOccupantZoneManager = occupantZoneManager;
        checkClusterDisplayAdded();
        mOccupantZoneManager.registerOccupantZoneConfigChangeListener(
                new ClusterDisplayChangeListener());
    }

    private void checkClusterDisplayAdded() {
        Display clusterDisplay = getClusterDisplay();
        if (clusterDisplay != null) {
            Log.i(TAG, String.format("Found display: %s (id: %d, owner: %s)",
                    clusterDisplay.getName(), clusterDisplay.getDisplayId(),
                    clusterDisplay.getOwnerPackageName()));
            mClusterDisplayId = clusterDisplay.getDisplayId();
            mListener.onDisplayAdded(clusterDisplay.getDisplayId());
        }
    }

    private Display getClusterDisplay() {
        List<OccupantZoneInfo> zones = mOccupantZoneManager.getAllOccupantZones();
        int zones_size = zones.size();
        for (int i = 0; i < zones_size; ++i) {
            OccupantZoneInfo zone = zones.get(i);
            // Assumes that a Car has only one driver.
            if (zone.occupantType == CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER) {
                return mOccupantZoneManager.getDisplayForOccupant(
                        zone, CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER);
            }
        }
        Log.e(TAG, "Can't find the OccupantZoneInfo for driver");
        return null;
    }

    private final class ClusterDisplayChangeListener implements
            CarOccupantZoneManager.OccupantZoneConfigChangeListener {
        @Override
        public void onOccupantZoneConfigChanged(int changeFlags) {
            if (DEBUG) Log.d(TAG, "onOccupantZoneConfigChanged changeFlags=" + changeFlags);
            if ((changeFlags & CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_DISPLAY) == 0) {
                return;
            }
            if (mClusterDisplayId == Display.INVALID_DISPLAY) {
                checkClusterDisplayAdded();
            } else {
                Display clusterDisplay = getClusterDisplay();
                if (clusterDisplay == null) {
                    mListener.onDisplayRemoved(mClusterDisplayId);
                    mClusterDisplayId = Display.INVALID_DISPLAY;
                }
            }
        }
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "{"
                + " clusterDisplayId = " + mClusterDisplayId
                + "}";
    }
}