Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 1 | /* |
Heemin Seog | 9b078d3 | 2020-04-21 15:07:32 -0700 | [diff] [blame] | 2 | * Copyright (C) 2020 The Android Open Source Project |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 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 | |
Heemin Seog | 9b078d3 | 2020-04-21 15:07:32 -0700 | [diff] [blame] | 17 | package com.android.systemui.car.navigationbar; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 18 | |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 19 | import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 20 | import static android.view.InsetsState.ITYPE_STATUS_BAR; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 21 | import static android.view.InsetsState.containsType; |
| 22 | |
| 23 | import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; |
| 24 | import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; |
| 25 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 26 | import android.content.Context; |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 27 | import android.content.res.Resources; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 28 | import android.graphics.PixelFormat; |
| 29 | import android.inputmethodservice.InputMethodService; |
| 30 | import android.os.Handler; |
| 31 | import android.os.IBinder; |
| 32 | import android.os.RemoteException; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 33 | import android.view.Display; |
| 34 | import android.view.Gravity; |
Heemin Seog | 8d6ec6a7 | 2019-10-25 14:34:11 -0700 | [diff] [blame] | 35 | import android.view.View; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 36 | import android.view.ViewGroup; |
| 37 | import android.view.WindowManager; |
| 38 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 39 | import androidx.annotation.VisibleForTesting; |
| 40 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 41 | import com.android.internal.statusbar.IStatusBarService; |
| 42 | import com.android.internal.statusbar.RegisterStatusBarResult; |
| 43 | import com.android.systemui.R; |
| 44 | import com.android.systemui.SystemUI; |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 45 | import com.android.systemui.car.CarDeviceProvisionedController; |
| 46 | import com.android.systemui.car.CarDeviceProvisionedListener; |
Dave Mankoff | 00e8a2f | 2019-12-18 16:59:49 -0500 | [diff] [blame] | 47 | import com.android.systemui.dagger.qualifiers.Main; |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 48 | import com.android.systemui.dagger.qualifiers.UiBackground; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 49 | import com.android.systemui.shared.system.ActivityManagerWrapper; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 50 | import com.android.systemui.statusbar.AutoHideUiElement; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 51 | import com.android.systemui.statusbar.CommandQueue; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 52 | import com.android.systemui.statusbar.phone.AutoHideController; |
| 53 | import com.android.systemui.statusbar.phone.BarTransitions; |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 54 | import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; |
| 55 | import com.android.systemui.statusbar.phone.StatusBarIconController; |
| 56 | import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 57 | import com.android.systemui.statusbar.policy.KeyguardStateController; |
| 58 | |
| 59 | import java.io.FileDescriptor; |
| 60 | import java.io.PrintWriter; |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 61 | import java.util.concurrent.Executor; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 62 | |
| 63 | import javax.inject.Inject; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 64 | |
| 65 | import dagger.Lazy; |
| 66 | |
| 67 | /** Navigation bars customized for the automotive use case. */ |
| 68 | public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks { |
| 69 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 70 | private final Resources mResources; |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 71 | private final CarNavigationBarController mCarNavigationBarController; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 72 | private final WindowManager mWindowManager; |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 73 | private final CarDeviceProvisionedController mCarDeviceProvisionedController; |
Heemin Seog | 4a68948 | 2019-11-04 10:37:43 -0800 | [diff] [blame] | 74 | private final CommandQueue mCommandQueue; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 75 | private final AutoHideController mAutoHideController; |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 76 | private final ButtonSelectionStateListener mButtonSelectionStateListener; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 77 | private final Handler mMainHandler; |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 78 | private final Executor mUiBgExecutor; |
Heemin Seog | 23f18d0 | 2020-04-24 17:53:22 -0700 | [diff] [blame] | 79 | private final IStatusBarService mBarService; |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 80 | private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy; |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 81 | private final ButtonSelectionStateController mButtonSelectionStateController; |
Heemin Seog | a3d358f | 2020-04-28 22:31:03 -0700 | [diff] [blame] | 82 | private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy; |
| 83 | private final Lazy<StatusBarIconController> mIconControllerLazy; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 84 | |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 85 | private final int mDisplayId; |
| 86 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 87 | private StatusBarSignalPolicy mSignalPolicy; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 88 | private ActivityManagerWrapper mActivityManagerWrapper; |
| 89 | |
| 90 | // If the nav bar should be hidden when the soft keyboard is visible. |
| 91 | private boolean mHideNavBarForKeyboard; |
| 92 | private boolean mBottomNavBarVisible; |
| 93 | |
| 94 | // Nav bar views. |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 95 | private ViewGroup mTopNavigationBarWindow; |
| 96 | private ViewGroup mBottomNavigationBarWindow; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 97 | private ViewGroup mLeftNavigationBarWindow; |
| 98 | private ViewGroup mRightNavigationBarWindow; |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 99 | private CarNavigationBarView mTopNavigationBarView; |
| 100 | private CarNavigationBarView mBottomNavigationBarView; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 101 | private CarNavigationBarView mLeftNavigationBarView; |
| 102 | private CarNavigationBarView mRightNavigationBarView; |
| 103 | |
| 104 | // To be attached to the navigation bars such that they can close the notification panel if |
| 105 | // it's open. |
| 106 | private boolean mDeviceIsSetUpForUser = true; |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 107 | private boolean mIsUserSetupInProgress = false; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 108 | |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 109 | @BarTransitions.TransitionMode |
| 110 | private int mStatusBarMode; |
| 111 | @BarTransitions.TransitionMode |
| 112 | private int mNavigationBarMode; |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 113 | private boolean mStatusBarTransientShown; |
| 114 | private boolean mNavBarTransientShown; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 115 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 116 | @Inject |
| 117 | public CarNavigationBar(Context context, |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 118 | @Main Resources resources, |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 119 | CarNavigationBarController carNavigationBarController, |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 120 | WindowManager windowManager, |
Eric Berglund | 89edc87 | 2020-01-21 15:28:35 -0800 | [diff] [blame] | 121 | CarDeviceProvisionedController deviceProvisionedController, |
Heemin Seog | 4a68948 | 2019-11-04 10:37:43 -0800 | [diff] [blame] | 122 | CommandQueue commandQueue, |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 123 | AutoHideController autoHideController, |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 124 | ButtonSelectionStateListener buttonSelectionStateListener, |
Dave Mankoff | 00e8a2f | 2019-12-18 16:59:49 -0500 | [diff] [blame] | 125 | @Main Handler mainHandler, |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 126 | @UiBackground Executor uiBgExecutor, |
Heemin Seog | 23f18d0 | 2020-04-24 17:53:22 -0700 | [diff] [blame] | 127 | IStatusBarService barService, |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 128 | Lazy<KeyguardStateController> keyguardStateControllerLazy, |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 129 | ButtonSelectionStateController buttonSelectionStateController, |
Heemin Seog | a3d358f | 2020-04-28 22:31:03 -0700 | [diff] [blame] | 130 | Lazy<PhoneStatusBarPolicy> iconPolicyLazy, |
| 131 | Lazy<StatusBarIconController> iconControllerLazy |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 132 | ) { |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 133 | super(context); |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 134 | mResources = resources; |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 135 | mCarNavigationBarController = carNavigationBarController; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 136 | mWindowManager = windowManager; |
Eric Berglund | 89edc87 | 2020-01-21 15:28:35 -0800 | [diff] [blame] | 137 | mCarDeviceProvisionedController = deviceProvisionedController; |
Heemin Seog | 4a68948 | 2019-11-04 10:37:43 -0800 | [diff] [blame] | 138 | mCommandQueue = commandQueue; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 139 | mAutoHideController = autoHideController; |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 140 | mButtonSelectionStateListener = buttonSelectionStateListener; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 141 | mMainHandler = mainHandler; |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 142 | mUiBgExecutor = uiBgExecutor; |
Heemin Seog | 23f18d0 | 2020-04-24 17:53:22 -0700 | [diff] [blame] | 143 | mBarService = barService; |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 144 | mKeyguardStateControllerLazy = keyguardStateControllerLazy; |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 145 | mButtonSelectionStateController = buttonSelectionStateController; |
Heemin Seog | a3d358f | 2020-04-28 22:31:03 -0700 | [diff] [blame] | 146 | mIconPolicyLazy = iconPolicyLazy; |
| 147 | mIconControllerLazy = iconControllerLazy; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 148 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 149 | mDisplayId = context.getDisplayId(); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 150 | } |
| 151 | |
| 152 | @Override |
| 153 | public void start() { |
| 154 | // Set initial state. |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 155 | mHideNavBarForKeyboard = mResources.getBoolean( |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 156 | com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard); |
| 157 | mBottomNavBarVisible = false; |
| 158 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 159 | // Connect into the status bar manager service |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 160 | mCommandQueue.addCallback(this); |
| 161 | |
| 162 | RegisterStatusBarResult result = null; |
| 163 | try { |
| 164 | result = mBarService.registerStatusBar(mCommandQueue); |
| 165 | } catch (RemoteException ex) { |
| 166 | ex.rethrowFromSystemServer(); |
| 167 | } |
| 168 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 169 | // StatusBarManagerService has a back up of IME token and it's restored here. |
| 170 | setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis, |
| 171 | result.mImeBackDisposition, result.mShowImeSwitcher); |
| 172 | |
| 173 | // Set up the initial icon state |
| 174 | int numIcons = result.mIcons.size(); |
| 175 | for (int i = 0; i < numIcons; i++) { |
| 176 | mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i)); |
| 177 | } |
| 178 | |
| 179 | mAutoHideController.setStatusBar(new AutoHideUiElement() { |
| 180 | @Override |
| 181 | public void synchronizeState() { |
| 182 | // No op. |
| 183 | } |
| 184 | |
| 185 | @Override |
| 186 | public boolean isVisible() { |
| 187 | return mStatusBarTransientShown; |
| 188 | } |
| 189 | |
| 190 | @Override |
| 191 | public void hide() { |
| 192 | clearTransient(); |
| 193 | } |
| 194 | }); |
| 195 | |
Heemin Seog | a8983af | 2020-03-31 13:16:48 -0700 | [diff] [blame] | 196 | mAutoHideController.setNavigationBar(new AutoHideUiElement() { |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 197 | @Override |
| 198 | public void synchronizeState() { |
| 199 | // No op. |
| 200 | } |
| 201 | |
| 202 | @Override |
| 203 | public boolean isVisible() { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 204 | return mNavBarTransientShown; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | @Override |
| 208 | public void hide() { |
| 209 | clearTransient(); |
| 210 | } |
| 211 | }); |
| 212 | |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 213 | mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup(); |
| 214 | mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress(); |
| 215 | mCarDeviceProvisionedController.addCallback( |
| 216 | new CarDeviceProvisionedListener() { |
| 217 | @Override |
| 218 | public void onUserSetupInProgressChanged() { |
| 219 | mMainHandler.post(() -> restartNavBarsIfNecessary()); |
| 220 | } |
| 221 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 222 | @Override |
| 223 | public void onUserSetupChanged() { |
| 224 | mMainHandler.post(() -> restartNavBarsIfNecessary()); |
| 225 | } |
| 226 | |
| 227 | @Override |
| 228 | public void onUserSwitched() { |
| 229 | mMainHandler.post(() -> restartNavBarsIfNecessary()); |
| 230 | } |
| 231 | }); |
| 232 | |
| 233 | createNavigationBar(result); |
| 234 | |
| 235 | mActivityManagerWrapper = ActivityManagerWrapper.getInstance(); |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 236 | mActivityManagerWrapper.registerTaskStackListener(mButtonSelectionStateListener); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 237 | |
Heemin Seog | 4860f80 | 2020-05-05 00:22:42 -0700 | [diff] [blame] | 238 | mUiBgExecutor.execute(mCarNavigationBarController::connectToHvac); |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 239 | |
| 240 | // Lastly, call to the icon policy to install/update all the icons. |
Heemin Seog | 23f18d0 | 2020-04-24 17:53:22 -0700 | [diff] [blame] | 241 | // Must be called on the main thread due to the use of observeForever() in |
| 242 | // mIconPolicy.init(). |
| 243 | mMainHandler.post(() -> { |
Heemin Seog | a3d358f | 2020-04-28 22:31:03 -0700 | [diff] [blame] | 244 | mIconPolicyLazy.get().init(); |
| 245 | mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconControllerLazy.get()); |
Heemin Seog | 23f18d0 | 2020-04-24 17:53:22 -0700 | [diff] [blame] | 246 | }); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 247 | } |
| 248 | |
| 249 | private void restartNavBarsIfNecessary() { |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 250 | boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup(); |
| 251 | boolean currentUserSetupInProgress = mCarDeviceProvisionedController |
| 252 | .isCurrentUserSetupInProgress(); |
| 253 | if (mIsUserSetupInProgress != currentUserSetupInProgress |
| 254 | || mDeviceIsSetUpForUser != currentUserSetup) { |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 255 | mDeviceIsSetUpForUser = currentUserSetup; |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 256 | mIsUserSetupInProgress = currentUserSetupInProgress; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 257 | restartNavBars(); |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * Remove all content from navbars and rebuild them. Used to allow for different nav bars |
| 263 | * before and after the device is provisioned. . Also for change of density and font size. |
| 264 | */ |
| 265 | private void restartNavBars() { |
| 266 | // remove and reattach all hvac components such that we don't keep a reference to unused |
| 267 | // ui elements |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 268 | mCarNavigationBarController.removeAllFromHvac(); |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 269 | mButtonSelectionStateController.removeAll(); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 270 | |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 271 | if (mTopNavigationBarWindow != null) { |
| 272 | mTopNavigationBarWindow.removeAllViews(); |
| 273 | mTopNavigationBarView = null; |
| 274 | } |
| 275 | |
| 276 | if (mBottomNavigationBarWindow != null) { |
| 277 | mBottomNavigationBarWindow.removeAllViews(); |
| 278 | mBottomNavigationBarView = null; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 279 | } |
| 280 | |
| 281 | if (mLeftNavigationBarWindow != null) { |
| 282 | mLeftNavigationBarWindow.removeAllViews(); |
| 283 | mLeftNavigationBarView = null; |
| 284 | } |
| 285 | |
| 286 | if (mRightNavigationBarWindow != null) { |
| 287 | mRightNavigationBarWindow.removeAllViews(); |
| 288 | mRightNavigationBarView = null; |
| 289 | } |
| 290 | |
| 291 | buildNavBarContent(); |
JianYang Liu | 4fbd981 | 2020-03-09 13:39:58 -0700 | [diff] [blame] | 292 | // If the UI was rebuilt (day/night change or user change) while the keyguard was up we need |
| 293 | // to correctly respect that state. |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 294 | if (mKeyguardStateControllerLazy.get().isShowing()) { |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 295 | mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser()); |
JianYang Liu | 4fbd981 | 2020-03-09 13:39:58 -0700 | [diff] [blame] | 296 | } else { |
| 297 | mCarNavigationBarController.hideAllKeyguardButtons(isDeviceSetupForUser()); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 298 | } |
kwaky | 371e621 | 2020-02-19 13:45:22 -0800 | [diff] [blame] | 299 | |
| 300 | // Upon restarting the Navigation Bar, CarFacetButtonController should immediately apply the |
| 301 | // selection state that reflects the current task stack. |
| 302 | mButtonSelectionStateListener.onTaskStackChanged(); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 303 | } |
| 304 | |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 305 | private boolean isDeviceSetupForUser() { |
| 306 | return mDeviceIsSetUpForUser && !mIsUserSetupInProgress; |
| 307 | } |
| 308 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 309 | private void createNavigationBar(RegisterStatusBarResult result) { |
| 310 | buildNavBarWindows(); |
| 311 | buildNavBarContent(); |
| 312 | attachNavBarWindows(); |
| 313 | |
| 314 | // Try setting up the initial state of the nav bar if applicable. |
| 315 | if (result != null) { |
| 316 | setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken, |
| 317 | result.mImeWindowVis, result.mImeBackDisposition, |
| 318 | result.mShowImeSwitcher); |
| 319 | } |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | private void buildNavBarWindows() { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 323 | mTopNavigationBarWindow = mCarNavigationBarController.getTopWindow(); |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 324 | mBottomNavigationBarWindow = mCarNavigationBarController.getBottomWindow(); |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 325 | mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow(); |
| 326 | mRightNavigationBarWindow = mCarNavigationBarController.getRightWindow(); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 327 | } |
| 328 | |
| 329 | private void buildNavBarContent() { |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 330 | mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser()); |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 331 | if (mTopNavigationBarView != null) { |
| 332 | mTopNavigationBarWindow.addView(mTopNavigationBarView); |
| 333 | } |
| 334 | |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 335 | mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser()); |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 336 | if (mBottomNavigationBarView != null) { |
| 337 | mBottomNavigationBarWindow.addView(mBottomNavigationBarView); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 338 | } |
| 339 | |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 340 | mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser()); |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 341 | if (mLeftNavigationBarView != null) { |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 342 | mLeftNavigationBarWindow.addView(mLeftNavigationBarView); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 343 | } |
| 344 | |
Abhijoy Saha | ee51369 | 2019-12-10 13:52:26 -0800 | [diff] [blame] | 345 | mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser()); |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 346 | if (mRightNavigationBarView != null) { |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 347 | mRightNavigationBarWindow.addView(mRightNavigationBarView); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 348 | } |
| 349 | } |
| 350 | |
| 351 | private void attachNavBarWindows() { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 352 | if (mTopNavigationBarWindow != null) { |
| 353 | int height = mResources.getDimensionPixelSize( |
| 354 | com.android.internal.R.dimen.status_bar_height); |
| 355 | WindowManager.LayoutParams lp = new WindowManager.LayoutParams( |
| 356 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 357 | height, |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 358 | WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL, |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 359 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 360 | | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
| 361 | | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
| 362 | | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 363 | PixelFormat.TRANSLUCENT); |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 364 | lp.setTitle("TopCarNavigationBar"); |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 365 | lp.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR}; |
| 366 | lp.setFitInsetsTypes(0); |
| 367 | lp.windowAnimations = 0; |
| 368 | lp.gravity = Gravity.TOP; |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 369 | mWindowManager.addView(mTopNavigationBarWindow, lp); |
| 370 | } |
| 371 | |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 372 | if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) { |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 373 | mBottomNavBarVisible = true; |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 374 | int height = mResources.getDimensionPixelSize( |
| 375 | com.android.internal.R.dimen.navigation_bar_height); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 376 | |
| 377 | WindowManager.LayoutParams lp = new WindowManager.LayoutParams( |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 378 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 379 | height, |
| 380 | WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 381 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
| 382 | | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
| 383 | | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
| 384 | | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, |
| 385 | PixelFormat.TRANSLUCENT); |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 386 | lp.setTitle("BottomCarNavigationBar"); |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 387 | lp.providesInsetsTypes = new int[]{ITYPE_NAVIGATION_BAR}; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 388 | lp.windowAnimations = 0; |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 389 | lp.gravity = Gravity.BOTTOM; |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 390 | mWindowManager.addView(mBottomNavigationBarWindow, lp); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 391 | } |
| 392 | |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 393 | if (mLeftNavigationBarWindow != null) { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 394 | int width = mResources.getDimensionPixelSize( |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 395 | R.dimen.car_left_navigation_bar_width); |
| 396 | WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams( |
| 397 | width, ViewGroup.LayoutParams.MATCH_PARENT, |
| 398 | WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, |
| 399 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
| 400 | | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
| 401 | | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
| 402 | | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, |
| 403 | PixelFormat.TRANSLUCENT); |
| 404 | leftlp.setTitle("LeftCarNavigationBar"); |
| 405 | leftlp.windowAnimations = 0; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 406 | leftlp.gravity = Gravity.LEFT; |
| 407 | mWindowManager.addView(mLeftNavigationBarWindow, leftlp); |
| 408 | } |
Heemin Seog | 991711a | 2020-04-24 00:38:39 -0700 | [diff] [blame] | 409 | |
Heemin Seog | fcccab7 | 2019-10-22 08:30:23 -0700 | [diff] [blame] | 410 | if (mRightNavigationBarWindow != null) { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 411 | int width = mResources.getDimensionPixelSize( |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 412 | R.dimen.car_right_navigation_bar_width); |
| 413 | WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams( |
| 414 | width, ViewGroup.LayoutParams.MATCH_PARENT, |
| 415 | WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, |
| 416 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
| 417 | | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
| 418 | | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
| 419 | | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, |
| 420 | PixelFormat.TRANSLUCENT); |
| 421 | rightlp.setTitle("RightCarNavigationBar"); |
| 422 | rightlp.windowAnimations = 0; |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 423 | rightlp.gravity = Gravity.RIGHT; |
| 424 | mWindowManager.addView(mRightNavigationBarWindow, rightlp); |
| 425 | } |
| 426 | } |
| 427 | |
| 428 | /** |
| 429 | * We register for soft keyboard visibility events such that we can hide the navigation bar |
| 430 | * giving more screen space to the IME. Note: this is optional and controlled by |
| 431 | * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}. |
| 432 | */ |
| 433 | @Override |
| 434 | public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, |
| 435 | boolean showImeSwitcher) { |
| 436 | if (!mHideNavBarForKeyboard) { |
| 437 | return; |
| 438 | } |
| 439 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 440 | if (mContext.getDisplayId() != displayId) { |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 441 | return; |
| 442 | } |
| 443 | |
| 444 | boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; |
Heemin Seog | 8d6ec6a7 | 2019-10-25 14:34:11 -0700 | [diff] [blame] | 445 | mCarNavigationBarController.setBottomWindowVisibility( |
| 446 | isKeyboardVisible ? View.GONE : View.VISIBLE); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 447 | } |
| 448 | |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 449 | @Override |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 450 | public void showTransient(int displayId, int[] types) { |
| 451 | if (displayId != mDisplayId) { |
| 452 | return; |
| 453 | } |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 454 | if (containsType(types, ITYPE_STATUS_BAR)) { |
| 455 | if (!mStatusBarTransientShown) { |
| 456 | mStatusBarTransientShown = true; |
| 457 | handleTransientChanged(); |
| 458 | } |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 459 | } |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 460 | if (containsType(types, ITYPE_NAVIGATION_BAR)) { |
| 461 | if (!mNavBarTransientShown) { |
| 462 | mNavBarTransientShown = true; |
| 463 | handleTransientChanged(); |
| 464 | } |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 465 | } |
| 466 | } |
| 467 | |
| 468 | @Override |
| 469 | public void abortTransient(int displayId, int[] types) { |
| 470 | if (displayId != mDisplayId) { |
| 471 | return; |
| 472 | } |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 473 | if (!containsType(types, ITYPE_STATUS_BAR) && !containsType(types, ITYPE_NAVIGATION_BAR)) { |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 474 | return; |
| 475 | } |
| 476 | clearTransient(); |
| 477 | } |
| 478 | |
| 479 | private void clearTransient() { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 480 | if (mStatusBarTransientShown) { |
| 481 | mStatusBarTransientShown = false; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 482 | handleTransientChanged(); |
| 483 | } |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 484 | if (mNavBarTransientShown) { |
| 485 | mNavBarTransientShown = false; |
| 486 | handleTransientChanged(); |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | @VisibleForTesting |
| 491 | boolean isStatusBarTransientShown() { |
| 492 | return mStatusBarTransientShown; |
| 493 | } |
| 494 | |
| 495 | @VisibleForTesting |
| 496 | boolean isNavBarTransientShown() { |
| 497 | return mNavBarTransientShown; |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 498 | } |
| 499 | |
| 500 | @Override |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 501 | public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| 502 | pw.print(" mTaskStackListener="); |
kwaky | 77d81dc | 2019-12-12 16:23:59 -0800 | [diff] [blame] | 503 | pw.println(mButtonSelectionStateListener); |
Heemin Seog | d59786b | 2019-11-08 09:20:26 -0800 | [diff] [blame] | 504 | pw.print(" mBottomNavigationBarView="); |
| 505 | pw.println(mBottomNavigationBarView); |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 506 | } |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 507 | |
| 508 | private void handleTransientChanged() { |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 509 | updateStatusBarMode(mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); |
| 510 | updateNavBarMode(mNavBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 511 | } |
| 512 | |
Heemin Seog | 29ecf61 | 2020-04-14 22:47:01 -0700 | [diff] [blame] | 513 | // Returns true if the status bar mode has changed. |
| 514 | private boolean updateStatusBarMode(int barMode) { |
| 515 | if (mStatusBarMode != barMode) { |
| 516 | mStatusBarMode = barMode; |
| 517 | mAutoHideController.touchAutoHide(); |
| 518 | return true; |
| 519 | } |
| 520 | return false; |
| 521 | } |
| 522 | |
| 523 | // Returns true if the nav bar mode has changed. |
| 524 | private boolean updateNavBarMode(int barMode) { |
Heemin Seog | e67cefea | 2020-01-28 12:02:50 -0800 | [diff] [blame] | 525 | if (mNavigationBarMode != barMode) { |
| 526 | mNavigationBarMode = barMode; |
| 527 | mAutoHideController.touchAutoHide(); |
| 528 | return true; |
| 529 | } |
| 530 | return false; |
| 531 | } |
Heemin Seog | 1a39dea | 2019-10-16 15:58:21 -0700 | [diff] [blame] | 532 | } |