From eeca9a9fd69060534acd0bc66d047c522b376384 Mon Sep 17 00:00:00 2001 From: Heemin Seog Date: Fri, 8 Nov 2019 16:16:49 -0800 Subject: [PATCH] Create a single car service to share in sysui Using this as an opportunity to daggerize related classes. Bug: 144189328 Test: manual, atest CarNavigationBarControllerTest Change-Id: I58d142bf20b50dca509d84fce6b6258e7d47e98e --- .../systemui/car/CarServiceProvider.java | 71 +++++++++++++++++++ .../systemui/statusbar/car/CarStatusBar.java | 46 +++++++----- .../statusbar/car/CarStatusBarModule.java | 9 +++ .../car/CarTrustAgentUnlockDialogHelper.java | 18 +++-- .../statusbar/car/DrivingStateHelper.java | 59 ++++++++------- .../statusbar/car/FullscreenUserSwitcher.java | 70 +++++++++++------- .../statusbar/car/PowerManagerHelper.java | 36 ++++++---- .../statusbar/car/hvac/HvacController.java | 44 +++++------- .../volume/CarVolumeDialogComponent.java | 12 +++- .../systemui/volume/CarVolumeDialogImpl.java | 60 +++++++--------- 10 files changed, 278 insertions(+), 147 deletions(-) create mode 100644 packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java new file mode 100644 index 0000000000000..f8bfeec6df2d2 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 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 com.android.systemui.car; + +import android.car.Car; +import android.content.Context; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** Provides a common connection to the car service that can be shared. */ +@Singleton +public class CarServiceProvider { + + private final Context mContext; + private final List mListeners = new ArrayList<>(); + private Car mCar; + + @Inject + public CarServiceProvider(Context context) { + mContext = context; + mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, + (car, ready) -> { + mCar = car; + + synchronized (mListeners) { + for (CarServiceOnConnectedListener listener : mListeners) { + if (ready) { + listener.onConnected(mCar); + } + } + } + }); + } + + /** + * Let's other components hook into the connection to the car service. If we're already + * connected to the car service, the callback is immediately triggered. + */ + public void addListener(CarServiceOnConnectedListener listener) { + if (mCar.isConnected()) { + listener.onConnected(mCar); + } + mListeners.add(listener); + } + + /** + * Listener which is triggered when Car Service is connected. + */ + public interface CarServiceOnConnectedListener { + /** This will be called when the car service has successfully been connected. */ + void onConnected(Car car); + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 78ac96020bae8..f8f36f692b253 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -66,6 +66,7 @@ import com.android.systemui.UiOffloadThread; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.car.CarServiceProvider; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.fragments.FragmentHostManager; @@ -164,6 +165,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt private float mBackgroundAlphaDiff; private float mInitialBackgroundAlpha; + private final Lazy mFullscreenUserSwitcherLazy; private FullscreenUserSwitcher mFullscreenUserSwitcher; private CarBatteryController mCarBatteryController; @@ -175,6 +177,9 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt private final Object mQueueLock = new Object(); private final CarNavigationBarController mCarNavigationBarController; + private final Lazy mDrivingStateHelperLazy; + private final Lazy mPowerManagerHelperLazy; + private final CarServiceProvider mCarServiceProvider; private CarFacetButtonController mCarFacetButtonController; private DeviceProvisionedController mDeviceProvisionedController; private boolean mDeviceIsSetUpForUser = true; @@ -311,6 +316,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt ViewMediatorCallback viewMediatorCallback, DismissCallbackRegistry dismissCallbackRegistry, /* Car Settings injected components. */ + CarServiceProvider carServiceProvider, + Lazy drivingStateHelperLazy, + Lazy powerManagerHelperLazy, + Lazy fullscreenUserSwitcherLazy, CarNavigationBarController carNavigationBarController) { super( context, @@ -384,6 +393,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt viewMediatorCallback, dismissCallbackRegistry); mScrimController = scrimController; + mCarServiceProvider = carServiceProvider; + mDrivingStateHelperLazy = drivingStateHelperLazy; + mPowerManagerHelperLazy = powerManagerHelperLazy; + mFullscreenUserSwitcherLazy = fullscreenUserSwitcherLazy; mCarNavigationBarController = carNavigationBarController; } @@ -449,10 +462,12 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt mSwitchToGuestTimer = new SwitchToGuestTimer(mContext); // Register a listener for driving state changes. - mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged); + mDrivingStateHelper = mDrivingStateHelperLazy.get(); + mDrivingStateHelper.setCarDrivingStateEventListener(this::onDrivingStateChanged); mDrivingStateHelper.connectToCarService(); - mPowerManagerHelper = new PowerManagerHelper(mContext, mCarPowerStateListener); + mPowerManagerHelper = mPowerManagerHelperLazy.get(); + mPowerManagerHelper.setCarPowerStateListener(mCarPowerStateListener); mPowerManagerHelper.connectToCarService(); } @@ -592,20 +607,13 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt }); CarNotificationListener carNotificationListener = new CarNotificationListener(); mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper(); - // This can take time if car service is not ready up to this time. - // TODO(b/142808072) Refactor CarUxRestrictionManagerWrapper to allow setting - // CarUxRestrictionsManager later and switch to Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT. - Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER, - (car, ready) -> { - if (!ready) { - return; - } - CarUxRestrictionsManager carUxRestrictionsManager = - (CarUxRestrictionsManager) - car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE); - mCarUxRestrictionManagerWrapper.setCarUxRestrictionsManager( - carUxRestrictionsManager); - }); + mCarServiceProvider.addListener(car -> { + CarUxRestrictionsManager carUxRestrictionsManager = + (CarUxRestrictionsManager) + car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE); + mCarUxRestrictionManagerWrapper.setCarUxRestrictionsManager( + carUxRestrictionsManager); + }); mNotificationDataManager = new NotificationDataManager(); mNotificationDataManager.setOnUnseenCountUpdateListener( @@ -974,8 +982,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt UserSwitcherController userSwitcherController = Dependency.get(UserSwitcherController.class); if (userSwitcherController.useFullscreenUserSwitcher()) { - mFullscreenUserSwitcher = new FullscreenUserSwitcher(this, - mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext); + mFullscreenUserSwitcher = mFullscreenUserSwitcherLazy.get(); + mFullscreenUserSwitcher.setStatusBar(this); + mFullscreenUserSwitcher.setContainer( + mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub)); } else { super.createUserSwitcher(); } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java index b9dacc0ded3e7..5418ebe5b8de8 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java @@ -29,6 +29,7 @@ import com.android.systemui.UiOffloadThread; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.car.CarServiceProvider; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -179,6 +180,10 @@ public class CarStatusBarModule { StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, DismissCallbackRegistry dismissCallbackRegistry, + CarServiceProvider carServiceProvider, + Lazy drivingStateHelperLazy, + Lazy powerManagerHelperLazy, + Lazy fullscreenUserSwitcherLazy, CarNavigationBarController carNavigationBarController) { return new CarStatusBar( context, @@ -250,6 +255,10 @@ public class CarStatusBarModule { statusBarKeyguardViewManager, viewMediatorCallback, dismissCallbackRegistry, + carServiceProvider, + drivingStateHelperLazy, + powerManagerHelperLazy, + fullscreenUserSwitcherLazy, carNavigationBarController); } } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java index ec72ee74f59af..ec4643302a052 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java @@ -22,6 +22,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.Handler; import android.os.UserHandle; @@ -36,15 +37,21 @@ import android.widget.TextView; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.MainResources; + +import javax.inject.Inject; +import javax.inject.Singleton; /** * A helper class displays an unlock dialog and receives broadcast about detecting trusted device * & unlocking state to show the appropriate message on the dialog. */ +@Singleton class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{ private static final String TAG = CarTrustAgentUnlockDialogHelper.class.getSimpleName(); private final Context mContext; + private final Resources mResources; private final WindowManager mWindowManager; private final UserManager mUserManager; private final WindowManager.LayoutParams mParams; @@ -60,10 +67,13 @@ class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{ private boolean mIsDialogShowing; private OnHideListener mOnHideListener; - CarTrustAgentUnlockDialogHelper(Context context) { + @Inject + CarTrustAgentUnlockDialogHelper(Context context, @MainResources Resources resources, + UserManager userManager, WindowManager windowManager) { mContext = context; - mUserManager = mContext.getSystemService(UserManager.class); - mWindowManager = mContext.getSystemService(WindowManager.class); + mResources = resources; + mUserManager = userManager; + mWindowManager = windowManager; mParams = createLayoutParams(); mFilter = getIntentFilter(); @@ -125,7 +135,7 @@ class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{ * @param listener listener that listens to dialog hide */ void showUnlockDialogAfterDelay(int uid, OnHideListener listener) { - long delayMillis = mContext.getResources().getInteger(R.integer.unlock_dialog_delay_ms); + long delayMillis = mResources.getInteger(R.integer.unlock_dialog_delay_ms); showUnlockDialogAfterDelay(uid, delayMillis, listener); } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java index cd87e78e4be9b..60934ab115321 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java @@ -17,31 +17,43 @@ package com.android.systemui.statusbar.car; import android.car.Car; -import android.car.Car.CarServiceLifecycleListener; import android.car.drivingstate.CarDrivingStateEvent; import android.car.drivingstate.CarDrivingStateManager; import android.car.drivingstate.CarDrivingStateManager.CarDrivingStateEventListener; -import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; +import com.android.systemui.car.CarServiceProvider; + +import javax.inject.Inject; +import javax.inject.Singleton; + /** * Helper class for connecting to the {@link CarDrivingStateManager} and listening for driving state * changes. */ +@Singleton public class DrivingStateHelper { public static final String TAG = "DrivingStateHelper"; - private final Context mContext; + private final CarServiceProvider mCarServiceProvider; + private CarDrivingStateManager mDrivingStateManager; - private Car mCar; private CarDrivingStateEventListener mDrivingStateHandler; - public DrivingStateHelper(Context context, - @NonNull CarDrivingStateEventListener drivingStateHandler) { - mContext = context; - mDrivingStateHandler = drivingStateHandler; + @Inject + public DrivingStateHelper(CarServiceProvider carServiceProvider) { + mCarServiceProvider = carServiceProvider; + } + + /** + * Sets the {@link CarDrivingStateEventListener}. Should be set before calling {@link + * #connectToCarService()}. + */ + public void setCarDrivingStateEventListener( + @NonNull CarDrivingStateEventListener carDrivingStateEventListener) { + mDrivingStateHandler = carDrivingStateEventListener; } /** @@ -64,25 +76,22 @@ public class DrivingStateHelper { * Establishes connection with the Car service. */ public void connectToCarService() { - mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, - mCarServiceLifecycleListener); + mCarServiceProvider.addListener(mCarServiceLifecycleListener); } - private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> { - if (!ready) { - return; - } - logD("Car Service connected"); - mDrivingStateManager = (CarDrivingStateManager) car.getCarManager( - Car.CAR_DRIVING_STATE_SERVICE); - if (mDrivingStateManager != null) { - mDrivingStateManager.registerListener(mDrivingStateHandler); - mDrivingStateHandler.onDrivingStateChanged( - mDrivingStateManager.getCurrentCarDrivingState()); - } else { - Log.e(TAG, "CarDrivingStateService service not available"); - } - }; + private final CarServiceProvider.CarServiceOnConnectedListener mCarServiceLifecycleListener = + car -> { + logD("Car Service connected"); + mDrivingStateManager = (CarDrivingStateManager) car.getCarManager( + Car.CAR_DRIVING_STATE_SERVICE); + if (mDrivingStateManager != null) { + mDrivingStateManager.registerListener(mDrivingStateHandler); + mDrivingStateHandler.onDrivingStateChanged( + mDrivingStateManager.getCurrentCarDrivingState()); + } else { + Log.e(TAG, "CarDrivingStateService service not available"); + } + }; private void logD(String message) { if (Log.isLoggable(TAG, Log.DEBUG)) { diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java index 31aced02b15e3..b188dc3949f2b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java @@ -26,6 +26,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.content.res.Resources; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; @@ -35,24 +36,34 @@ import android.view.ViewStub; import androidx.recyclerview.widget.GridLayoutManager; import com.android.systemui.R; +import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.dagger.qualifiers.MainResources; import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener; import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord; +import javax.inject.Inject; +import javax.inject.Singleton; + /** * Manages the fullscreen user switcher. */ +@Singleton public class FullscreenUserSwitcher { private static final String TAG = FullscreenUserSwitcher.class.getSimpleName(); // Because user 0 is headless, user count for single user is 2 private static final int NUMBER_OF_BACKGROUND_USERS = 1; - private final UserGridRecyclerView mUserGridView; - private final View mParent; - private final int mShortAnimDuration; - private final CarStatusBar mStatusBar; + private final Context mContext; + private final Resources mResources; private final UserManager mUserManager; + private final CarServiceProvider mCarServiceProvider; + private final CarTrustAgentUnlockDialogHelper mUnlockDialogHelper; + private final int mShortAnimDuration; + + private CarStatusBar mStatusBar; + private View mParent; + private UserGridRecyclerView mUserGridView; private CarTrustAgentEnrollmentManager mEnrollmentManager; - private CarTrustAgentUnlockDialogHelper mUnlockDialogHelper; private UserGridRecyclerView.UserRecord mSelectedUser; private CarUserManagerHelper mCarUserManagerHelper; private final BroadcastReceiver mUserUnlockReceiver = new BroadcastReceiver() { @@ -65,37 +76,46 @@ public class FullscreenUserSwitcher { mContext.unregisterReceiver(mUserUnlockReceiver); } }; - private final Car mCar; - public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) { - mStatusBar = statusBar; - mParent = containerStub.inflate(); + @Inject + public FullscreenUserSwitcher( + Context context, + @MainResources Resources resources, + UserManager userManager, + CarServiceProvider carServiceProvider, + CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper) { mContext = context; + mResources = resources; + mUserManager = userManager; + mCarServiceProvider = carServiceProvider; + mUnlockDialogHelper = carTrustAgentUnlockDialogHelper; + + mShortAnimDuration = mResources.getInteger(android.R.integer.config_shortAnimTime); + } + + /** Sets the status bar which controls the keyguard. */ + public void setStatusBar(CarStatusBar statusBar) { + mStatusBar = statusBar; + } + + /** Sets the {@link ViewStub} to show the user switcher. */ + public void setContainer(ViewStub containerStub) { + mParent = containerStub.inflate(); View container = mParent.findViewById(R.id.container); // Initialize user grid. mUserGridView = container.findViewById(R.id.user_grid); - GridLayoutManager layoutManager = new GridLayoutManager(context, - context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); + GridLayoutManager layoutManager = new GridLayoutManager(mContext, + mResources.getInteger(R.integer.user_fullscreen_switcher_num_col)); mUserGridView.setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserGridView.setUserSelectionListener(this::onUserSelected); - mCarUserManagerHelper = new CarUserManagerHelper(context); - mUnlockDialogHelper = new CarTrustAgentUnlockDialogHelper(mContext); - mUserManager = mContext.getSystemService(UserManager.class); + mCarUserManagerHelper = new CarUserManagerHelper(mContext); + mCarServiceProvider.addListener( + car -> mEnrollmentManager = (CarTrustAgentEnrollmentManager) car.getCarManager( + Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE)); - mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, - (car, ready) -> { - if (!ready) { - return; - } - mEnrollmentManager = (CarTrustAgentEnrollmentManager) car - .getCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE); - }); - - mShortAnimDuration = container.getResources() - .getInteger(android.R.integer.config_shortAnimTime); IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); if (mUserManager.isUserUnlocked(UserHandle.USER_SYSTEM)) { // User0 is unlocked, switched to the initial user diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java index a27dd341d4495..71847bbac9fd5 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java @@ -18,33 +18,33 @@ package com.android.systemui.statusbar.car; import android.annotation.NonNull; import android.car.Car; -import android.car.Car.CarServiceLifecycleListener; import android.car.hardware.power.CarPowerManager; import android.car.hardware.power.CarPowerManager.CarPowerStateListener; -import android.content.Context; import android.util.Log; +import com.android.systemui.car.CarServiceProvider; + +import javax.inject.Inject; +import javax.inject.Singleton; + /** * Helper class for connecting to the {@link CarPowerManager} and listening for power state changes. */ +@Singleton public class PowerManagerHelper { public static final String TAG = "PowerManagerHelper"; - private final Context mContext; - private final CarPowerStateListener mCarPowerStateListener; + private final CarServiceProvider mCarServiceProvider; - private Car mCar; private CarPowerManager mCarPowerManager; + private CarPowerStateListener mCarPowerStateListener; - private final CarServiceLifecycleListener mCarServiceLifecycleListener; + private final CarServiceProvider.CarServiceOnConnectedListener mCarServiceLifecycleListener; - PowerManagerHelper(Context context, @NonNull CarPowerStateListener listener) { - mContext = context; - mCarPowerStateListener = listener; - mCarServiceLifecycleListener = (car, ready) -> { - if (!ready) { - return; - } + @Inject + PowerManagerHelper(CarServiceProvider carServiceProvider) { + mCarServiceProvider = carServiceProvider; + mCarServiceLifecycleListener = car -> { Log.d(TAG, "Car Service connected"); mCarPowerManager = (CarPowerManager) car.getCarManager(Car.POWER_SERVICE); if (mCarPowerManager != null) { @@ -55,11 +55,17 @@ public class PowerManagerHelper { }; } + /** + * Sets a {@link CarPowerStateListener}. Should be set before {@link #connectToCarService()}. + */ + void setCarPowerStateListener(@NonNull CarPowerStateListener listener) { + mCarPowerStateListener = listener; + } + /** * Connect to Car service. */ void connectToCarService() { - mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, - mCarServiceLifecycleListener); + mCarServiceProvider.addListener(mCarServiceLifecycleListener); } } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java index 41914d212ee92..e12a95ea17bcd 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java @@ -20,15 +20,14 @@ import static android.car.VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS; import android.car.Car; -import android.car.Car.CarServiceLifecycleListener; import android.car.VehicleUnit; import android.car.hardware.CarPropertyValue; import android.car.hardware.hvac.CarHvacManager; import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback; -import android.content.Context; -import android.os.Handler; import android.util.Log; +import com.android.systemui.car.CarServiceProvider; + import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -37,19 +36,18 @@ import java.util.Map; import java.util.Objects; import javax.inject.Inject; +import javax.inject.Singleton; /** * Manages the connection to the Car service and delegates value changes to the registered * {@link TemperatureView}s */ +@Singleton public class HvacController { - public static final String TAG = "HvacController"; - public static final int BIND_TO_HVAC_RETRY_DELAY = 5000; - private Context mContext; - private Handler mHandler; - private Car mCar; + private final CarServiceProvider mCarServiceProvider; + private CarHvacManager mHvacManager; private HashMap> mTempComponents = new HashMap<>(); @@ -85,22 +83,20 @@ public class HvacController { } }; - private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> { - if (!ready) { - return; - } - try { - mHvacManager = (CarHvacManager) car.getCarManager(Car.HVAC_SERVICE); - mHvacManager.registerCallback(mHardwareCallback); - initComponents(); - } catch (Exception e) { - Log.e(TAG, "Failed to correctly connect to HVAC", e); - } - }; + private final CarServiceProvider.CarServiceOnConnectedListener mCarServiceLifecycleListener = + car -> { + try { + mHvacManager = (CarHvacManager) car.getCarManager(Car.HVAC_SERVICE); + mHvacManager.registerCallback(mHardwareCallback); + initComponents(); + } catch (Exception e) { + Log.e(TAG, "Failed to correctly connect to HVAC", e); + } + }; @Inject - public HvacController(Context context) { - mContext = context; + public HvacController(CarServiceProvider carServiceProvider) { + mCarServiceProvider = carServiceProvider; } /** @@ -108,9 +104,7 @@ public class HvacController { * ({@link CarHvacManager}) will happen on the same thread this method was called from. */ public void connectToCarService() { - mHandler = new Handler(); - mCar = Car.createCar(mContext, /* handler= */ mHandler, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, - mCarServiceLifecycleListener); + mCarServiceProvider.addListener(mCarServiceLifecycleListener); } /** diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java index 9d39684bf7966..5a3443674cf43 100644 --- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java @@ -18,6 +18,7 @@ package com.android.systemui.volume; import android.content.Context; +import com.android.systemui.car.CarServiceProvider; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.VolumeDialog; @@ -30,13 +31,20 @@ import javax.inject.Singleton; @Singleton public class CarVolumeDialogComponent extends VolumeDialogComponent { + private CarVolumeDialogImpl mCarVolumeDialog; + @Inject public CarVolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator, - VolumeDialogControllerImpl volumeDialogController) { + VolumeDialogControllerImpl volumeDialogController, + CarServiceProvider carServiceProvider) { super(context, keyguardViewMediator, volumeDialogController); + mCarVolumeDialog.setCarServiceProvider(carServiceProvider); } + /** This method is called while calling the super constructor. */ + @Override protected VolumeDialog createDefault() { - return new CarVolumeDialogImpl(mContext); + mCarVolumeDialog = new CarVolumeDialogImpl(mContext); + return mCarVolumeDialog; } } diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java index 09223e8ff4c3a..367959ec49724 100644 --- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java @@ -24,7 +24,6 @@ import android.annotation.Nullable; import android.app.Dialog; import android.app.KeyguardManager; import android.car.Car; -import android.car.Car.CarServiceLifecycleListener; import android.car.media.CarAudioManager; import android.content.Context; import android.content.DialogInterface; @@ -56,6 +55,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.systemui.R; +import com.android.systemui.car.CarServiceProvider; import com.android.systemui.plugins.VolumeDialog; import org.xmlpull.v1.XmlPullParserException; @@ -95,7 +95,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { private CustomDialog mDialog; private RecyclerView mListView; private CarVolumeItemAdapter mVolumeItemsAdapter; - private Car mCar; private CarAudioManager mCarAudioManager; private boolean mHovering; private int mCurrentlyDisplayingGroupId; @@ -147,30 +146,28 @@ public class CarVolumeDialogImpl implements VolumeDialog { } }; - private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> { - if (!ready) { - return; - } - mExpanded = false; - mCarAudioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE); - int volumeGroupCount = mCarAudioManager.getVolumeGroupCount(); - // Populates volume slider items from volume groups to UI. - for (int groupId = 0; groupId < volumeGroupCount; groupId++) { - VolumeItem volumeItem = getVolumeItemForUsages( - mCarAudioManager.getUsagesForVolumeGroupId(groupId)); - mAvailableVolumeItems.add(volumeItem); - // The first one is the default item. - if (groupId == 0) { - clearAllAndSetupDefaultCarVolumeLineItem(0); - } - } + private final CarServiceProvider.CarServiceOnConnectedListener mCarServiceOnConnectedListener = + car -> { + mExpanded = false; + mCarAudioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE); + int volumeGroupCount = mCarAudioManager.getVolumeGroupCount(); + // Populates volume slider items from volume groups to UI. + for (int groupId = 0; groupId < volumeGroupCount; groupId++) { + VolumeItem volumeItem = getVolumeItemForUsages( + mCarAudioManager.getUsagesForVolumeGroupId(groupId)); + mAvailableVolumeItems.add(volumeItem); + // The first one is the default item. + if (groupId == 0) { + clearAllAndSetupDefaultCarVolumeLineItem(0); + } + } - // If list is already initiated, update its content. - if (mVolumeItemsAdapter != null) { - mVolumeItemsAdapter.notifyDataSetChanged(); - } - mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback); - }; + // If list is already initiated, update its content. + if (mVolumeItemsAdapter != null) { + mVolumeItemsAdapter.notifyDataSetChanged(); + } + mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback); + }; public CarVolumeDialogImpl(Context context) { mContext = context; @@ -181,6 +178,11 @@ public class CarVolumeDialogImpl implements VolumeDialog { R.integer.car_volume_dialog_display_hovering_timeout); } + /** Sets a {@link CarServiceProvider} which connects to the audio service. */ + public void setCarServiceProvider(CarServiceProvider carServiceProvider) { + carServiceProvider.addListener(mCarServiceOnConnectedListener); + } + private static int getSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { return carAudioManager.getGroupVolume(volumeGroupId); } @@ -196,8 +198,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { @Override public void init(int windowType, Callback callback) { initDialog(); - mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, - mCarServiceLifecycleListener); } @Override @@ -205,12 +205,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { mHandler.removeCallbacksAndMessages(/* token= */ null); cleanupAudioManager(); - // unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup - // audio manager beforehand. - if (mCar != null) { - mCar.disconnect(); - mCar = null; - } } private void initDialog() {