• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 com.android.systemui.car.userpicker;
18 
19 import static android.car.CarOccupantZoneManager.DISPLAY_TYPE_MAIN;
20 import static android.car.CarOccupantZoneManager.INVALID_USER_ID;
21 import static android.car.CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER;
22 import static android.car.CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER;
23 import static android.car.CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER;
24 import static android.car.CarOccupantZoneManager.USER_ASSIGNMENT_RESULT_FAIL_DRIVER_ZONE;
25 import static android.car.VehicleAreaSeat.SEAT_ROW_1_CENTER;
26 import static android.car.VehicleAreaSeat.SEAT_ROW_1_LEFT;
27 import static android.car.VehicleAreaSeat.SEAT_ROW_1_RIGHT;
28 import static android.car.VehicleAreaSeat.SEAT_ROW_2_CENTER;
29 import static android.car.VehicleAreaSeat.SEAT_ROW_2_LEFT;
30 import static android.car.VehicleAreaSeat.SEAT_ROW_2_RIGHT;
31 import static android.car.VehicleAreaSeat.SEAT_ROW_3_CENTER;
32 import static android.car.VehicleAreaSeat.SEAT_ROW_3_LEFT;
33 import static android.car.VehicleAreaSeat.SEAT_ROW_3_RIGHT;
34 import static android.view.Display.INVALID_DISPLAY;
35 
36 import android.annotation.Nullable;
37 import android.annotation.UserIdInt;
38 import android.car.Car;
39 import android.car.CarOccupantZoneManager;
40 import android.car.CarOccupantZoneManager.OccupantZoneInfo;
41 import android.car.hardware.power.CarPowerManager;
42 import android.car.user.CarUserManager;
43 import android.car.user.CarUserManager.UserLifecycleListener;
44 import android.car.user.UserLifecycleEventFilter;
45 import android.content.Context;
46 import android.util.Pair;
47 import android.util.Slog;
48 import android.view.Display;
49 
50 import androidx.annotation.VisibleForTesting;
51 
52 import com.android.systemui.R;
53 import com.android.systemui.car.CarServiceProvider;
54 
55 import java.util.HashMap;
56 import java.util.List;
57 import java.util.Map;
58 import java.util.concurrent.Executor;
59 
60 import javax.inject.Inject;
61 
62 @UserPickerScope
63 final class CarServiceMediator {
64     private static final String TAG = CarServiceMediator.class.getSimpleName();
65 
66     // These are needed when getting the string of the seat for users.
67     private String mSeatDriver;
68     private String mSeatFront;
69     private String mSeatRear;
70     private String mSeatLeftSide;
71     private String mSeatCenterSide;
72     private String mSeatRightSide;
73 
74     private CarOccupantZoneManager mCarOccupantZoneManager;
75     private CarUserManager mCarUserManager;
76     private CarPowerManager mCarPowerManager;
77 
78     private final Context mContext;
79     private final CarServiceProvider mCarServiceProvider;
80     private final Map<UserLifecycleListener, Pair<Executor, UserLifecycleEventFilter>>
81             mUserLifecycleListeners = new HashMap<>();
82 
83     private final CarServiceProvider.CarServiceOnConnectedListener mServiceOnConnectedListener =
84             new CarServiceProvider.CarServiceOnConnectedListener() {
85                 @Override
86                 public void onConnected(Car car) {
87                     onConnect(car);
88                 }
89             };
90 
91     @Inject
CarServiceMediator(Context context, CarServiceProvider carServiceProvider)92     CarServiceMediator(Context context, CarServiceProvider carServiceProvider) {
93         mContext = context.getApplicationContext();
94         mCarServiceProvider = carServiceProvider;
95         mCarServiceProvider.addListener(mServiceOnConnectedListener);
96 
97         updateTexts();
98     }
99 
100     @VisibleForTesting
onConnect(Car car)101     void onConnect(Car car) {
102         mCarOccupantZoneManager = car.getCarManager(CarOccupantZoneManager.class);
103         mCarUserManager = car.getCarManager(CarUserManager.class);
104         mCarPowerManager = car.getCarManager(CarPowerManager.class);
105         //re-register listeners in case of CarService crash and recreation
106         if (mCarUserManager != null) {
107             for (UserLifecycleListener listener : mUserLifecycleListeners.keySet()) {
108                 mCarUserManager.addListener(mUserLifecycleListeners.get(listener).first,
109                         mUserLifecycleListeners.get(listener).second, listener);
110             }
111         }
112     }
113 
updateTexts()114     void updateTexts() {
115         mSeatDriver = mContext.getString(R.string.seat_driver);
116         mSeatFront = mContext.getString(R.string.seat_front);
117         mSeatRear = mContext.getString(R.string.seat_rear);
118         mSeatLeftSide = mContext.getString(R.string.seat_left_side);
119         mSeatCenterSide = mContext.getString(R.string.seat_center_side);
120         mSeatRightSide = mContext.getString(R.string.seat_right_side);
121     }
122 
registerUserChangeEventsListener(Executor receiver, UserLifecycleEventFilter filter, UserLifecycleListener listener)123     void registerUserChangeEventsListener(Executor receiver, UserLifecycleEventFilter filter,
124             UserLifecycleListener listener) {
125         mUserLifecycleListeners.put(listener, new Pair<>(receiver, filter));
126         if (mCarUserManager != null) {
127             mCarUserManager.addListener(receiver, filter, listener);
128         }
129     }
130 
onDestroy()131     void onDestroy() {
132         for (UserLifecycleListener listener : mUserLifecycleListeners.keySet()) {
133             mCarUserManager.removeListener(listener);
134         }
135         mUserLifecycleListeners.clear();
136         mCarServiceProvider.removeListener(mServiceOnConnectedListener);
137     }
138 
139     @Nullable
getCarUserManager()140     CarUserManager getCarUserManager() {
141         return mCarUserManager;
142     }
143 
144     @Nullable
getOccupantZoneForDisplayId(int displayId)145     OccupantZoneInfo getOccupantZoneForDisplayId(int displayId) {
146         if (mCarOccupantZoneManager == null || displayId == INVALID_DISPLAY) {
147             Slog.w(TAG, "Cannot get occupant zone manager or has been requested for invalid"
148                     + " display.");
149             return null;
150         }
151 
152         List<OccupantZoneInfo> occupantZoneInfos = mCarOccupantZoneManager.getAllOccupantZones();
153         for (int index = 0; index < occupantZoneInfos.size(); index++) {
154             CarOccupantZoneManager.OccupantZoneInfo occupantZoneInfo = occupantZoneInfos.get(index);
155             List<Display> displays = mCarOccupantZoneManager.getAllDisplaysForOccupant(
156                     occupantZoneInfo);
157             for (int displayIndex = 0; displayIndex < displays.size(); displayIndex++) {
158                 if (displays.get(displayIndex).getDisplayId() == displayId) {
159                     return occupantZoneInfo;
160                 }
161             }
162         }
163         return null;
164     }
165 
getDisplayIdForUser(@serIdInt int userId)166     int getDisplayIdForUser(@UserIdInt int userId) {
167         if (mCarOccupantZoneManager == null) {
168             Slog.w(TAG, "Cannot get occupant zone manager.");
169             return INVALID_DISPLAY;
170         }
171 
172         List<OccupantZoneInfo> occupantZoneInfos = mCarOccupantZoneManager.getAllOccupantZones();
173         for (int i = 0; i < occupantZoneInfos.size(); i++) {
174             OccupantZoneInfo zoneInfo = occupantZoneInfos.get(i);
175             int zoneUserId = mCarOccupantZoneManager.getUserForOccupant(zoneInfo);
176             if (zoneUserId == userId) {
177                 Display d = mCarOccupantZoneManager.getDisplayForOccupant(zoneInfo,
178                         DISPLAY_TYPE_MAIN);
179                 return d != null ? d.getDisplayId() : INVALID_DISPLAY;
180             }
181         }
182         return INVALID_DISPLAY;
183     }
184 
getUserForDisplay(int displayId)185     int getUserForDisplay(int displayId) {
186         if (mCarOccupantZoneManager == null) {
187             Slog.w(TAG, "Cannot get occupant zone manager.");
188             return INVALID_USER_ID;
189         }
190 
191         return mCarOccupantZoneManager.getUserForDisplayId(displayId);
192     }
193 
unassignOccupantZoneForDisplay(int displayId)194     int unassignOccupantZoneForDisplay(int displayId) {
195         OccupantZoneInfo zoneInfo = getOccupantZoneForDisplayId(displayId);
196         if (zoneInfo == null) {
197             // Return any error code for this situation.
198             Slog.w(TAG, "Cannot find occupant zone info associated with display " + displayId);
199             return USER_ASSIGNMENT_RESULT_FAIL_DRIVER_ZONE;
200         }
201         return mCarOccupantZoneManager.unassignOccupantZone(zoneInfo);
202     }
203 
getSeatString(int displayId)204     String getSeatString(int displayId) {
205         String seatString = "";
206         OccupantZoneInfo zoneInfo = getOccupantZoneForDisplayId(displayId);
207         if (zoneInfo == null) {
208             Slog.w(TAG, "Cannot find occupant zone info associated with display " + displayId);
209             return seatString;
210         }
211 
212         switch (zoneInfo.occupantType) {
213             case OCCUPANT_TYPE_FRONT_PASSENGER:
214                 return mSeatFront + " " + getSeatSideString(zoneInfo.seat);
215             case OCCUPANT_TYPE_REAR_PASSENGER:
216                 return mSeatRear + " " + getSeatSideString(zoneInfo.seat);
217             case OCCUPANT_TYPE_DRIVER:
218                 return mSeatDriver;
219         }
220         return seatString;
221     }
222 
getSeatSideString(int seat)223     private String getSeatSideString(int seat) {
224         switch (seat) {
225             case SEAT_ROW_1_LEFT:
226             case SEAT_ROW_2_LEFT:
227             case SEAT_ROW_3_LEFT:
228                 return mSeatLeftSide;
229             case SEAT_ROW_1_CENTER:
230             case SEAT_ROW_2_CENTER:
231             case SEAT_ROW_3_CENTER:
232                 return mSeatCenterSide;
233             case SEAT_ROW_1_RIGHT:
234             case SEAT_ROW_2_RIGHT:
235             case SEAT_ROW_3_RIGHT:
236                 return mSeatRightSide;
237             default:
238                 return "";
239         }
240     }
241 
screenOffDisplay(int displayId)242     void screenOffDisplay(int displayId) {
243         if (mCarPowerManager == null) {
244             Slog.e(TAG, "Cannot get power manager.");
245             return;
246         }
247         mCarPowerManager.setDisplayPowerState(displayId, /* enable= */ false);
248     }
249 }
250