1 /* 2 * Copyright (C) 2024 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.systembar; 18 19 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING; 20 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED; 21 22 import android.car.Car; 23 import android.car.user.CarUserManager; 24 import android.content.Context; 25 import android.os.Build; 26 import android.os.UserManager; 27 import android.util.Log; 28 29 import androidx.annotation.NonNull; 30 31 import com.android.car.docklib.DockViewController; 32 import com.android.car.docklib.data.DockProtoDataController; 33 import com.android.car.docklib.view.DockView; 34 import com.android.car.dockutil.Flags; 35 import com.android.systemui.R; 36 import com.android.systemui.car.CarServiceProvider; 37 import com.android.systemui.car.systembar.element.CarSystemBarElementController; 38 import com.android.systemui.car.systembar.element.CarSystemBarElementStateController; 39 import com.android.systemui.car.systembar.element.CarSystemBarElementStatusBarDisableController; 40 import com.android.systemui.car.systembar.element.layout.CarSystemBarFrameLayout; 41 import com.android.systemui.settings.UserFileManager; 42 import com.android.systemui.settings.UserTracker; 43 44 import dagger.assisted.Assisted; 45 import dagger.assisted.AssistedFactory; 46 import dagger.assisted.AssistedInject; 47 48 import java.io.File; 49 50 /** Wrapper controller class for instantiating {@link DockViewController} inside CarSystemUI */ 51 public class DockViewControllerWrapper extends 52 CarSystemBarElementController<CarSystemBarFrameLayout> { 53 private static final boolean DEBUG = Build.IS_ENG || Build.IS_USERDEBUG; 54 55 private static final String TAG = DockViewControllerWrapper.class.getSimpleName(); 56 57 private final Context mContext; 58 private final UserManager mUserManager; 59 private final UserTracker mUserTracker; 60 private final UserFileManager mUserFileManager; 61 private final CarServiceProvider mCarServiceProvider; 62 63 private DockViewController mDockViewController; 64 private CarUserManager mCarUserManager; 65 private int mActiveUnlockedUserId = -1; 66 67 private final CarUserManager.UserLifecycleListener mUserLifecycleListener = 68 new CarUserManager.UserLifecycleListener() { 69 @Override 70 public void onEvent(@NonNull CarUserManager.UserLifecycleEvent event) { 71 if (event.getUserHandle().isSystem()) { 72 return; 73 } 74 75 switch (event.getEventType()) { 76 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKED -> { 77 if (event.getUserId() == mUserTracker.getUserId()) { 78 mActiveUnlockedUserId = event.getUserId(); 79 setupDock(); 80 } 81 } 82 case USER_LIFECYCLE_EVENT_TYPE_SWITCHING -> { 83 if (event.getPreviousUserId() == mActiveUnlockedUserId) { 84 destroyDock(); 85 } 86 } 87 } 88 } 89 }; 90 91 private final CarServiceProvider.CarServiceOnConnectedListener mCarOnConnectedListener = 92 new CarServiceProvider.CarServiceOnConnectedListener() { 93 @Override 94 public void onConnected(Car car) { 95 mCarUserManager = car.getCarManager(CarUserManager.class); 96 if (mCarUserManager != null) { 97 mCarUserManager.addListener(mContext.getMainExecutor(), 98 mUserLifecycleListener); 99 } 100 } 101 }; 102 103 @AssistedInject DockViewControllerWrapper(@ssisted CarSystemBarFrameLayout view, CarSystemBarElementStatusBarDisableController disableController, CarSystemBarElementStateController stateController, Context context, UserTracker userTracker, UserFileManager userFileManager, CarServiceProvider carServiceProvider)104 DockViewControllerWrapper(@Assisted CarSystemBarFrameLayout view, 105 CarSystemBarElementStatusBarDisableController disableController, 106 CarSystemBarElementStateController stateController, Context context, 107 UserTracker userTracker, UserFileManager userFileManager, 108 CarServiceProvider carServiceProvider) { 109 super(view, disableController, stateController); 110 mContext = context; 111 mUserManager = context.getSystemService(UserManager.class); 112 mUserTracker = userTracker; 113 mUserFileManager = userFileManager; 114 mCarServiceProvider = carServiceProvider; 115 } 116 117 @AssistedFactory 118 public interface Factory extends 119 CarSystemBarElementController.Factory<CarSystemBarFrameLayout, 120 DockViewControllerWrapper> { 121 } 122 123 @Override onViewAttached()124 protected void onViewAttached() { 125 super.onViewAttached(); 126 setupDock(); 127 mCarServiceProvider.addListener(mCarOnConnectedListener); 128 } 129 130 @Override onViewDetached()131 protected void onViewDetached() { 132 super.onViewDetached(); 133 mCarServiceProvider.removeListener(mCarOnConnectedListener); 134 if (mCarUserManager != null) { 135 mCarUserManager.removeListener(mUserLifecycleListener); 136 mCarUserManager = null; 137 } 138 destroyDock(); 139 } 140 createDockViewController(DockView dockView, Context userContext, File dataFile)141 protected DockViewController createDockViewController(DockView dockView, Context userContext, 142 File dataFile) { 143 return new DockViewController(dockView, userContext, dataFile); 144 } 145 setupDock()146 private void setupDock() { 147 if (!Flags.dockFeature()) { 148 return; 149 } 150 if (mDockViewController != null) { 151 if (DEBUG) { 152 Log.d(TAG, "Dock already initialized"); 153 } 154 return; 155 } 156 DockView dockView = mView.findViewById(R.id.dock); 157 if (dockView == null) { 158 if (DEBUG) { 159 Log.d(TAG, "Dock cannot be initialised: Cannot find dock view"); 160 } 161 return; 162 } 163 if (!mUserManager.isUserUnlocked(mUserTracker.getUserId())) { 164 if (DEBUG) { 165 Log.d(TAG, "Dock cannot be initialised: User not unlocked"); 166 } 167 return; 168 } 169 mDockViewController = createDockViewController( 170 dockView, 171 mUserTracker.getUserContext(), 172 mUserFileManager.getFile( 173 DockProtoDataController.FILE_NAME, 174 mUserTracker.getUserId() 175 ) 176 ); 177 } 178 destroyDock()179 private void destroyDock() { 180 if (mDockViewController != null) { 181 mDockViewController.destroy(); 182 mDockViewController = null; 183 } 184 } 185 } 186