1 /* 2 * Copyright (C) 2020 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.userswitcher; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorListenerAdapter; 21 import android.car.Car; 22 import android.car.user.CarUserManager; 23 import android.content.Context; 24 import android.content.pm.ActivityInfo; 25 import android.content.res.Configuration; 26 import android.content.res.Resources; 27 import android.view.KeyEvent; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.ViewGroup; 31 32 import androidx.recyclerview.widget.GridLayoutManager; 33 34 import com.android.settingslib.applications.InterestingConfigChanges; 35 import com.android.systemui.R; 36 import com.android.systemui.car.CarServiceProvider; 37 import com.android.systemui.car.window.OverlayViewController; 38 import com.android.systemui.car.window.OverlayViewGlobalStateController; 39 import com.android.systemui.dagger.SysUISingleton; 40 import com.android.systemui.dagger.qualifiers.Main; 41 import com.android.systemui.settings.UserTracker; 42 import com.android.systemui.statusbar.policy.ConfigurationController; 43 44 import javax.inject.Inject; 45 46 /** 47 * Controller for {@link R.layout#car_fullscreen_user_switcher}. 48 */ 49 @SysUISingleton 50 public class FullScreenUserSwitcherViewController extends OverlayViewController 51 implements ConfigurationController.ConfigurationListener { 52 private final Context mContext; 53 private final UserTracker mUserTracker; 54 private final Resources mResources; 55 private final CarServiceProvider mCarServiceProvider; 56 private final int mShortAnimationDuration; 57 private CarUserManager mCarUserManager; 58 private UserGridRecyclerView mUserGridView; 59 private UserGridRecyclerView.UserSelectionListener mUserSelectionListener; 60 private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges( 61 ActivityInfo.CONFIG_UI_MODE); 62 63 64 @Inject FullScreenUserSwitcherViewController( Context context, UserTracker userTracker, @Main Resources resources, ConfigurationController configurationController, CarServiceProvider carServiceProvider, OverlayViewGlobalStateController overlayViewGlobalStateController)65 public FullScreenUserSwitcherViewController( 66 Context context, 67 UserTracker userTracker, 68 @Main Resources resources, 69 ConfigurationController configurationController, 70 CarServiceProvider carServiceProvider, 71 OverlayViewGlobalStateController overlayViewGlobalStateController) { 72 super(R.id.fullscreen_user_switcher_stub, overlayViewGlobalStateController); 73 mContext = context; 74 mUserTracker = userTracker; 75 mResources = resources; 76 mCarServiceProvider = carServiceProvider; 77 mCarServiceProvider.addListener(car -> { 78 mCarUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE); 79 registerCarUserManagerIfPossible(); 80 }); 81 mShortAnimationDuration = mResources.getInteger(android.R.integer.config_shortAnimTime); 82 mConfigChanges.applyNewConfig(mContext.getResources()); 83 configurationController.addCallback(this); 84 } 85 86 @Override onFinishInflate()87 protected void onFinishInflate() { 88 initializeViews(); 89 } 90 91 @Override onConfigChanged(Configuration configuration)92 public void onConfigChanged(Configuration configuration) { 93 if (mConfigChanges.applyNewConfig(mContext.getResources())) { 94 // prerequisites 95 if (getLayout() == null) return; 96 UserSwitcherContainer container = getLayout().findViewById( 97 R.id.user_switcher_container); 98 if (container == null) return; 99 ViewGroup viewGroupParent = (ViewGroup) container.getParent(); 100 101 // store index 102 int viewIndex = viewGroupParent.indexOfChild(container); 103 104 // reinflate 105 viewGroupParent.removeView(container); 106 UserSwitcherContainer newContainer = (UserSwitcherContainer) LayoutInflater.from( 107 mContext).inflate(R.layout.car_fullscreen_user_switcher, 108 viewGroupParent, /* attachToRoot= */ false); 109 viewGroupParent.addView(newContainer, viewIndex); 110 initializeViews(); 111 } 112 } 113 114 @Override getFocusAreaViewId()115 protected int getFocusAreaViewId() { 116 return R.id.user_switcher_focus_area; 117 } 118 119 @Override shouldFocusWindow()120 protected boolean shouldFocusWindow() { 121 return true; 122 } 123 124 @Override showInternal()125 protected void showInternal() { 126 getLayout().setVisibility(View.VISIBLE); 127 } 128 129 @Override hideInternal()130 protected void hideInternal() { 131 // Switching is about to happen, since it takes time, fade out the switcher gradually. 132 fadeOut(); 133 } 134 initializeViews()135 private void initializeViews() { 136 // Intercept back button. 137 UserSwitcherContainer container = getLayout().findViewById(R.id.user_switcher_container); 138 container.setKeyEventHandler(event -> { 139 if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) { 140 return false; 141 } 142 143 if (event.getAction() == KeyEvent.ACTION_UP && getLayout().isVisibleToUser()) { 144 stop(); 145 } 146 return true; 147 }); 148 149 mUserGridView = getLayout().findViewById(R.id.user_grid); 150 GridLayoutManager layoutManager = new GridLayoutManager(mContext, 151 mResources.getInteger(R.integer.user_fullscreen_switcher_num_col)); 152 mUserGridView.setLayoutManager(layoutManager); 153 mUserGridView.setUserTracker(mUserTracker); 154 mUserGridView.buildAdapter(); 155 mUserGridView.setUserSelectionListener(mUserSelectionListener); 156 registerCarUserManagerIfPossible(); 157 } 158 fadeOut()159 private void fadeOut() { 160 mUserGridView.animate() 161 .alpha(0.0f) 162 .setDuration(mShortAnimationDuration) 163 .setListener(new AnimatorListenerAdapter() { 164 @Override 165 public void onAnimationEnd(Animator animation) { 166 getLayout().setVisibility(View.GONE); 167 mUserGridView.setAlpha(1.0f); 168 } 169 }); 170 171 } 172 173 /** 174 * Set {@link UserGridRecyclerView.UserSelectionListener}. 175 */ setUserGridSelectionListener( UserGridRecyclerView.UserSelectionListener userGridSelectionListener)176 void setUserGridSelectionListener( 177 UserGridRecyclerView.UserSelectionListener userGridSelectionListener) { 178 mUserSelectionListener = userGridSelectionListener; 179 } 180 registerCarUserManagerIfPossible()181 private void registerCarUserManagerIfPossible() { 182 if (mUserGridView != null && mCarUserManager != null) { 183 mUserGridView.setCarUserManager(mCarUserManager); 184 } 185 } 186 } 187