diff options
Diffstat (limited to 'packages/CarSystemUI/src')
25 files changed, 1794 insertions, 895 deletions
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java index 34afb132805c..b3102e248ab2 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java @@ -21,8 +21,8 @@ import com.android.systemui.bubbles.dagger.BubbleModule; import com.android.systemui.car.navigationbar.CarNavigationBar; import com.android.systemui.car.notification.CarNotificationModule; import com.android.systemui.car.sideloaded.SideLoadedAppController; -import com.android.systemui.car.statusbar.CarStatusBar; -import com.android.systemui.car.statusbar.CarStatusBarModule; +import com.android.systemui.car.statusbar.UnusedStatusBar; +import com.android.systemui.car.statusbar.UnusedStatusBarModule; import com.android.systemui.car.voicerecognition.ConnectedDeviceVoiceRecognitionNotifier; import com.android.systemui.car.volume.VolumeUI; import com.android.systemui.car.window.OverlayWindowModule; @@ -39,7 +39,6 @@ import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.notification.InstantAppNotifier; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.statusbar.tv.TvStatusBar; import com.android.systemui.theme.ThemeOverlayController; import com.android.systemui.toast.ToastUI; import com.android.systemui.util.leak.GarbageMonitor; @@ -50,9 +49,9 @@ import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; /** Binder for car specific {@link SystemUI} modules. */ -@Module(includes = {RecentsModule.class, CarStatusBarModule.class, NotificationsModule.class, +@Module(includes = {RecentsModule.class, NotificationsModule.class, BubbleModule.class, KeyguardModule.class, OverlayWindowModule.class, - CarNotificationModule.class}) + CarNotificationModule.class, UnusedStatusBarModule.class}) public abstract class CarSystemUIBinder { /** Inject into AuthController. */ @Binds @@ -155,19 +154,7 @@ public abstract class CarSystemUIBinder { @Binds @IntoMap @ClassKey(StatusBar.class) - public abstract SystemUI bindsStatusBar(CarStatusBar sysui); - - /** Inject into TvStatusBar. */ - @Binds - @IntoMap - @ClassKey(TvStatusBar.class) - public abstract SystemUI bindsTvStatusBar(TvStatusBar sysui); - - /** Inject into StatusBarGoogle. */ - @Binds - @IntoMap - @ClassKey(CarStatusBar.class) - public abstract SystemUI bindsCarStatusBar(CarStatusBar sysui); + public abstract SystemUI bindsStatusBar(UnusedStatusBar sysui); /** Inject into VolumeUI. */ @Binds diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java index 59d6ed67b552..0e3c7f31886b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java @@ -28,10 +28,9 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarDeviceProvisionedControllerImpl; import com.android.systemui.car.keyguard.CarKeyguardViewController; -import com.android.systemui.car.statusbar.CarStatusBar; -import com.android.systemui.car.statusbar.CarStatusBarKeyguardViewManager; import com.android.systemui.car.statusbar.DozeServiceHost; import com.android.systemui.car.statusbar.DummyNotificationShadeWindowController; +import com.android.systemui.car.statusbar.UnusedStatusBar; import com.android.systemui.car.volume.CarVolumeDialogComponent; import com.android.systemui.dagger.SystemUIRootComponent; import com.android.systemui.dagger.qualifiers.Background; @@ -60,13 +59,14 @@ import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryControllerImpl; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.volume.VolumeDialogComponent; +import com.android.systemui.wm.DisplayImeController; +import com.android.systemui.wm.DisplaySystemBarsController; import javax.inject.Named; import javax.inject.Singleton; @@ -97,6 +97,10 @@ public abstract class CarSystemUIModule { groupManager, configurationController); } + @Binds + abstract DisplayImeController bindDisplayImeController( + DisplaySystemBarsController displaySystemBarsController); + @Singleton @Provides @Named(LEAK_REPORT_EMAIL_NAME) @@ -135,7 +139,7 @@ public abstract class CarSystemUIModule { @Binds @Singleton - public abstract QSFactory provideQSFactory(QSFactoryImpl qsFactoryImpl); + public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); @Binds abstract DockManager bindDockManager(DockManagerImpl dockManager); @@ -152,17 +156,10 @@ public abstract class CarSystemUIModule { CarSystemUIRootComponent systemUIRootComponent); @Binds - public abstract StatusBar bindStatusBar(CarStatusBar statusBar); - - @Binds abstract VolumeDialogComponent bindVolumeDialogComponent( CarVolumeDialogComponent carVolumeDialogComponent); @Binds - abstract StatusBarKeyguardViewManager bindStatusBarKeyguardViewManager( - CarStatusBarKeyguardViewManager keyguardViewManager); - - @Binds abstract KeyguardViewController bindKeyguardViewController( CarKeyguardViewController carKeyguardViewController); @@ -180,4 +177,7 @@ public abstract class CarSystemUIModule { @Binds abstract DozeHost bindDozeHost(DozeServiceHost dozeServiceHost); + + @Binds + abstract StatusBar bindStatusBar(UnusedStatusBar statusBar); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarSystemUiTest.java b/packages/CarSystemUI/src/com/android/systemui/car/CarSystemUiTest.java new file mode 100644 index 000000000000..5f593b06c511 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/CarSystemUiTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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 java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates that a test class should be run as part of CarSystemUI presubmit + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +public @interface CarSystemUiTest { +} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java index 69766cc6c0d0..ec018f9bb62e 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java @@ -21,10 +21,13 @@ import android.car.user.CarUserManager; import android.content.Context; import android.os.Bundle; import android.os.Handler; +import android.os.UserHandle; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; import androidx.annotation.VisibleForTesting; @@ -61,7 +64,7 @@ import dagger.Lazy; public class CarKeyguardViewController extends OverlayViewController implements KeyguardViewController { private static final String TAG = "CarKeyguardViewController"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private final Context mContext; private final Handler mHandler; @@ -75,9 +78,10 @@ public class CarKeyguardViewController extends OverlayViewController implements private final DismissCallbackRegistry mDismissCallbackRegistry; private final ViewMediatorCallback mViewMediatorCallback; private final CarNavigationBarController mCarNavigationBarController; + private final InputMethodManager mInputMethodManager; // Needed to instantiate mBouncer. - private final KeyguardBouncer.BouncerExpansionCallback - mExpansionCallback = new KeyguardBouncer.BouncerExpansionCallback() { + private final KeyguardBouncer.BouncerExpansionCallback mExpansionCallback = + new KeyguardBouncer.BouncerExpansionCallback() { @Override public void onFullyShown() { } @@ -96,7 +100,8 @@ public class CarKeyguardViewController extends OverlayViewController implements }; private final CarUserManager.UserLifecycleListener mUserLifecycleListener = (e) -> { if (e.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) { - revealKeyguardIfBouncerPrepared(); + UserHandle currentUser = e.getUserHandle(); + revealKeyguardIfBouncerPrepared(currentUser); } }; @@ -136,11 +141,18 @@ public class CarKeyguardViewController extends OverlayViewController implements mDismissCallbackRegistry = dismissCallbackRegistry; mViewMediatorCallback = viewMediatorCallback; mCarNavigationBarController = carNavigationBarController; + // TODO(b/169280588): Inject InputMethodManager instead. + mInputMethodManager = mContext.getSystemService(InputMethodManager.class); registerUserSwitchedListener(); } @Override + protected boolean shouldShowNavigationBarInsets() { + return true; + } + + @Override public void onFinishInflate() { mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils, @@ -172,7 +184,6 @@ public class CarKeyguardViewController extends OverlayViewController implements mKeyguardStateController.notifyKeyguardState(mShowing, /* occluded= */ false); mCarNavigationBarController.showAllKeyguardButtons(/* isSetUp= */ true); start(); - getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ true); reset(/* hideBouncerWhenShowing= */ false); notifyKeyguardUpdateMonitor(); } @@ -187,7 +198,6 @@ public class CarKeyguardViewController extends OverlayViewController implements mBouncer.hide(/* destroyView= */ true); mCarNavigationBarController.hideAllKeyguardButtons(/* isSetUp= */ true); stop(); - getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ false); mKeyguardStateController.notifyKeyguardDoneFading(); mHandler.post(mViewMediatorCallback::keyguardGone); notifyKeyguardUpdateMonitor(); @@ -232,7 +242,6 @@ public class CarKeyguardViewController extends OverlayViewController implements public void onCancelClicked() { if (mBouncer == null) return; - getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ false); getOverlayViewGlobalStateController().setWindowNeedsInput(/* needsInput= */ false); mBouncer.hide(/* destroyView= */ true); @@ -361,9 +370,9 @@ public class CarKeyguardViewController extends OverlayViewController implements } /** - * Hides Keyguard so that the transitioning Bouncer can be hidden until it is prepared. To be - * called by {@link com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator} - * when a new user is selected. + * Hides Keyguard so that the transitioning Bouncer can be hidden until it is prepared. To be + * called by {@link com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator} + * when a new user is selected. */ public void hideKeyguardToPrepareBouncer() { getLayout().setVisibility(View.INVISIBLE); @@ -374,29 +383,41 @@ public class CarKeyguardViewController extends OverlayViewController implements mBouncer = keyguardBouncer; } - private void revealKeyguardIfBouncerPrepared() { + private void revealKeyguardIfBouncerPrepared(UserHandle currentUser) { int reattemptDelayMillis = 50; Runnable revealKeyguard = () -> { if (mBouncer == null) { if (DEBUG) { Log.d(TAG, "revealKeyguardIfBouncerPrepared: revealKeyguard request is ignored " - + "since the Bouncer has not been initialized yet."); + + "since the Bouncer has not been initialized yet."); } return; } if (!mBouncer.inTransit() || !mBouncer.isSecure()) { getLayout().setVisibility(View.VISIBLE); + updateCurrentUserForPasswordEntry(currentUser); } else { if (DEBUG) { Log.d(TAG, "revealKeyguardIfBouncerPrepared: Bouncer is not prepared " + "yet so reattempting after " + reattemptDelayMillis + "ms."); } - mHandler.postDelayed(this::revealKeyguardIfBouncerPrepared, reattemptDelayMillis); + mHandler.postDelayed(() -> revealKeyguardIfBouncerPrepared(currentUser), + reattemptDelayMillis); } }; mHandler.post(revealKeyguard); } + private void updateCurrentUserForPasswordEntry(UserHandle currentUser) { + EditText passwordEntry = getLayout().findViewById(R.id.passwordEntry); + if (passwordEntry != null) { + mHandler.post(() -> { + mInputMethodManager.restartInput(passwordEntry); + passwordEntry.setTextOperationUser(currentUser); + }); + } + } + private void notifyKeyguardUpdateMonitor() { mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(mShowing); if (mBouncer != null) { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java index 37dfce4e16ce..b6d251fbfe16 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java @@ -16,8 +16,6 @@ package com.android.systemui.car.navigationbar; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.containsType; @@ -28,13 +26,11 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE import android.content.Context; import android.content.res.Resources; -import android.graphics.PixelFormat; import android.inputmethodservice.InputMethodService; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.view.Display; -import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsetsController; @@ -45,7 +41,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.RegisterStatusBarResult; import com.android.internal.view.AppearanceRegion; -import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarDeviceProvisionedListener; @@ -74,7 +69,6 @@ import dagger.Lazy; /** Navigation bars customized for the automotive use case. */ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks { - private final Resources mResources; private final CarNavigationBarController mCarNavigationBarController; private final SysuiDarkIconDispatcher mStatusBarIconController; @@ -91,12 +85,17 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks private final Lazy<StatusBarIconController> mIconControllerLazy; private final int mDisplayId; + private final SystemBarConfigs mSystemBarConfigs; private StatusBarSignalPolicy mSignalPolicy; private ActivityManagerWrapper mActivityManagerWrapper; // If the nav bar should be hidden when the soft keyboard is visible. - private boolean mHideNavBarForKeyboard; + private boolean mHideTopBarForKeyboard; + private boolean mHideLeftBarForKeyboard; + private boolean mHideRightBarForKeyboard; + private boolean mHideBottomBarForKeyboard; + private boolean mBottomNavBarVisible; // Nav bar views. @@ -139,7 +138,8 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks IStatusBarService barService, Lazy<KeyguardStateController> keyguardStateControllerLazy, Lazy<PhoneStatusBarPolicy> iconPolicyLazy, - Lazy<StatusBarIconController> iconControllerLazy + Lazy<StatusBarIconController> iconControllerLazy, + SystemBarConfigs systemBarConfigs ) { super(context); mResources = resources; @@ -156,6 +156,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks mKeyguardStateControllerLazy = keyguardStateControllerLazy; mIconPolicyLazy = iconPolicyLazy; mIconControllerLazy = iconControllerLazy; + mSystemBarConfigs = systemBarConfigs; mDisplayId = context.getDisplayId(); } @@ -163,8 +164,13 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks @Override public void start() { // Set initial state. - mHideNavBarForKeyboard = mResources.getBoolean( - com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard); + mHideTopBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP); + mHideBottomBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide( + SystemBarConfigs.BOTTOM); + mHideLeftBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.LEFT); + mHideRightBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide( + SystemBarConfigs.RIGHT); + mBottomNavBarVisible = false; // Connect into the status bar manager service @@ -342,100 +348,63 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks private void buildNavBarContent() { mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser()); if (mTopNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.TOP, mTopNavigationBarView); mTopNavigationBarWindow.addView(mTopNavigationBarView); } mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser()); if (mBottomNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.BOTTOM, mBottomNavigationBarView); mBottomNavigationBarWindow.addView(mBottomNavigationBarView); } mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser()); if (mLeftNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.LEFT, mLeftNavigationBarView); mLeftNavigationBarWindow.addView(mLeftNavigationBarView); } mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser()); if (mRightNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.RIGHT, mRightNavigationBarView); mRightNavigationBarWindow.addView(mRightNavigationBarView); } } private void attachNavBarWindows() { - if (mTopNavigationBarWindow != null) { - int height = mResources.getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_height); - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - height, - WindowManager.LayoutParams.TYPE_STATUS_BAR, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - lp.setTitle("TopCarNavigationBar"); - lp.windowAnimations = 0; - lp.gravity = Gravity.TOP; - mWindowManager.addView(mTopNavigationBarWindow, lp); - } - - if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) { - mBottomNavBarVisible = true; - int height = mResources.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height); - - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - height, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - lp.setTitle("BottomCarNavigationBar"); - lp.windowAnimations = 0; - lp.gravity = Gravity.BOTTOM; - mWindowManager.addView(mBottomNavigationBarWindow, lp); - } - - if (mLeftNavigationBarWindow != null) { - int width = mResources.getDimensionPixelSize( - R.dimen.car_left_navigation_bar_width); - WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams( - width, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - leftlp.setTitle("LeftCarNavigationBar"); - leftlp.providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR}; - leftlp.setFitInsetsTypes(0); - leftlp.windowAnimations = 0; - leftlp.gravity = Gravity.LEFT; - mWindowManager.addView(mLeftNavigationBarWindow, leftlp); - } + mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide); + } - if (mRightNavigationBarWindow != null) { - int width = mResources.getDimensionPixelSize( - R.dimen.car_right_navigation_bar_width); - WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams( - width, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - rightlp.setTitle("RightCarNavigationBar"); - rightlp.providesInsetsTypes = new int[]{ITYPE_EXTRA_NAVIGATION_BAR}; - rightlp.setFitInsetsTypes(0); - rightlp.windowAnimations = 0; - rightlp.gravity = Gravity.RIGHT; - mWindowManager.addView(mRightNavigationBarWindow, rightlp); + private void attachNavBarBySide(int side) { + switch(side) { + case SystemBarConfigs.TOP: + if (mTopNavigationBarWindow != null) { + mWindowManager.addView(mTopNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP)); + } + break; + case SystemBarConfigs.BOTTOM: + if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) { + mBottomNavBarVisible = true; + + mWindowManager.addView(mBottomNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM)); + } + break; + case SystemBarConfigs.LEFT: + if (mLeftNavigationBarWindow != null) { + mWindowManager.addView(mLeftNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT)); + } + break; + case SystemBarConfigs.RIGHT: + if (mRightNavigationBarWindow != null) { + mWindowManager.addView(mRightNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT)); + } + break; + default: + return; } } @@ -447,17 +416,30 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { - if (!mHideNavBarForKeyboard) { - return; - } - if (mContext.getDisplayId() != displayId) { return; } boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; - mCarNavigationBarController.setBottomWindowVisibility( - isKeyboardVisible ? View.GONE : View.VISIBLE); + + if (mHideTopBarForKeyboard) { + mCarNavigationBarController.setTopWindowVisibility( + isKeyboardVisible ? View.GONE : View.VISIBLE); + } + + if (mHideBottomBarForKeyboard) { + mCarNavigationBarController.setBottomWindowVisibility( + isKeyboardVisible ? View.GONE : View.VISIBLE); + } + + if (mHideLeftBarForKeyboard) { + mCarNavigationBarController.setLeftWindowVisibility( + isKeyboardVisible ? View.GONE : View.VISIBLE); + } + if (mHideRightBarForKeyboard) { + mCarNavigationBarController.setRightWindowVisibility( + isKeyboardVisible ? View.GONE : View.VISIBLE); + } } @Override diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java index ca780ae645c9..e522d19249e3 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java @@ -22,7 +22,6 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; -import com.android.systemui.R; import com.android.systemui.car.hvac.HvacController; import javax.inject.Inject; @@ -61,7 +60,8 @@ public class CarNavigationBarController { NavigationBarViewFactory navigationBarViewFactory, ButtonSelectionStateController buttonSelectionStateController, Lazy<HvacController> hvacControllerLazy, - ButtonRoleHolderController buttonRoleHolderController) { + ButtonRoleHolderController buttonRoleHolderController, + SystemBarConfigs systemBarConfigs) { mContext = context; mNavigationBarViewFactory = navigationBarViewFactory; mButtonSelectionStateController = buttonSelectionStateController; @@ -69,19 +69,17 @@ public class CarNavigationBarController { mButtonRoleHolderController = buttonRoleHolderController; // Read configuration. - mShowTop = mContext.getResources().getBoolean(R.bool.config_enableTopNavigationBar); - mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar); - mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar); - mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar); + mShowTop = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.TOP); + mShowBottom = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.BOTTOM); + mShowLeft = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.LEFT); + mShowRight = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.RIGHT); } /** * Hides all system bars. */ public void hideBars() { - if (mTopView != null) { - mTopView.setVisibility(View.GONE); - } + setTopWindowVisibility(View.GONE); setBottomWindowVisibility(View.GONE); setLeftWindowVisibility(View.GONE); setRightWindowVisibility(View.GONE); @@ -91,9 +89,7 @@ public class CarNavigationBarController { * Shows all system bars. */ public void showBars() { - if (mTopView != null) { - mTopView.setVisibility(View.VISIBLE); - } + setTopWindowVisibility(View.VISIBLE); setBottomWindowVisibility(View.VISIBLE); setLeftWindowVisibility(View.VISIBLE); setRightWindowVisibility(View.VISIBLE); @@ -135,6 +131,11 @@ public class CarNavigationBarController { return mShowRight ? mNavigationBarViewFactory.getRightWindow() : null; } + /** Toggles the top nav bar visibility. */ + public boolean setTopWindowVisibility(@View.Visibility int visibility) { + return setWindowVisibility(getTopWindow(), visibility); + } + /** Toggles the bottom nav bar visibility. */ public boolean setBottomWindowVisibility(@View.Visibility int visibility) { return setWindowVisibility(getBottomWindow(), visibility); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java index 029d4c7fa2fb..ab401bbf06bb 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; -import android.view.WindowInsets; import android.widget.LinearLayout; import com.android.systemui.Dependency; @@ -77,11 +76,6 @@ public class CarNavigationBarView extends LinearLayout { setFocusable(false); } - @Override - public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) { - return windowInsets; - } - // Used to forward touch events even if the touch was initiated from a child component @Override public boolean onInterceptTouchEvent(MotionEvent ev) { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java index d60bc418ece2..adf8d4d5acf8 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java @@ -148,10 +148,9 @@ public class NavigationBarViewFactory { CarNavigationBarView view = (CarNavigationBarView) View.inflate(mContext, barLayout, /* root= */ null); - // Include a FocusParkingView at the end. The rotary controller "parks" the focus here when - // the user navigates to another window. This is also used to prevent wrap-around which is - // why it must be first or last in Tab order. - view.addView(new FocusParkingView(mContext)); + // Include a FocusParkingView at the beginning. The rotary controller "parks" the focus here + // when the user navigates to another window. This is also used to prevent wrap-around. + view.addView(new FocusParkingView(mContext), 0); mCachedViewMap.put(type, view); return mCachedViewMap.get(type); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java new file mode 100644 index 000000000000..2efa2b3d4870 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2020 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.navigationbar; + +import android.annotation.IntDef; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.Log; +import android.view.Gravity; +import android.view.InsetsState; +import android.view.ViewGroup; +import android.view.WindowManager; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.R; +import com.android.systemui.car.notification.BottomNotificationPanelViewMediator; +import com.android.systemui.car.notification.TopNotificationPanelViewMediator; +import com.android.systemui.dagger.qualifiers.Main; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Reads configs for system bars for each side (TOP, BOTTOM, LEFT, and RIGHT) and returns the + * corresponding {@link android.view.WindowManager.LayoutParams} per the configuration. + */ +@Singleton +public class SystemBarConfigs { + + private static final String TAG = SystemBarConfigs.class.getSimpleName(); + // The z-order from which system bars will start to appear on top of HUN's. + private static final int HUN_ZORDER = 10; + + @IntDef(value = {TOP, BOTTOM, LEFT, RIGHT}) + @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) + private @interface SystemBarSide { + } + + public static final int TOP = 0; + public static final int BOTTOM = 1; + public static final int LEFT = 2; + public static final int RIGHT = 3; + + /* + NOTE: The elements' order in the map below must be preserved as-is since the correct + corresponding values are obtained by the index. + */ + private static final int[] BAR_TYPE_MAP = { + InsetsState.ITYPE_STATUS_BAR, + InsetsState.ITYPE_NAVIGATION_BAR, + InsetsState.ITYPE_CLIMATE_BAR, + InsetsState.ITYPE_EXTRA_NAVIGATION_BAR + }; + + private static final Map<@SystemBarSide Integer, Integer> BAR_GRAVITY_MAP = new ArrayMap<>(); + private static final Map<@SystemBarSide Integer, String> BAR_TITLE_MAP = new ArrayMap<>(); + private static final Map<@SystemBarSide Integer, Integer> BAR_GESTURE_MAP = new ArrayMap<>(); + + private final Resources mResources; + private final Map<@SystemBarSide Integer, SystemBarConfig> mSystemBarConfigMap = + new ArrayMap<>(); + private final List<@SystemBarSide Integer> mSystemBarSidesByZOrder = new ArrayList<>(); + + private boolean mTopNavBarEnabled; + private boolean mBottomNavBarEnabled; + private boolean mLeftNavBarEnabled; + private boolean mRightNavBarEnabled; + + @Inject + public SystemBarConfigs(@Main Resources resources) { + mResources = resources; + + populateMaps(); + readConfigs(); + + checkEnabledBarsHaveUniqueBarTypes(); + checkSystemBarEnabledForNotificationPanel(); + checkHideBottomBarForKeyboardConfigSync(); + + setInsetPaddingsForOverlappingCorners(); + sortSystemBarSidesByZOrder(); + } + + protected WindowManager.LayoutParams getLayoutParamsBySide(@SystemBarSide int side) { + return mSystemBarConfigMap.get(side) != null + ? mSystemBarConfigMap.get(side).getLayoutParams() : null; + } + + protected boolean getEnabledStatusBySide(@SystemBarSide int side) { + switch (side) { + case TOP: + return mTopNavBarEnabled; + case BOTTOM: + return mBottomNavBarEnabled; + case LEFT: + return mLeftNavBarEnabled; + case RIGHT: + return mRightNavBarEnabled; + default: + return false; + } + } + + protected boolean getHideForKeyboardBySide(@SystemBarSide int side) { + return mSystemBarConfigMap.get(side) != null + && mSystemBarConfigMap.get(side).getHideForKeyboard(); + } + + protected void insetSystemBar(@SystemBarSide int side, CarNavigationBarView view) { + int[] paddings = mSystemBarConfigMap.get(side).getPaddings(); + view.setPadding(paddings[2], paddings[0], paddings[3], paddings[1]); + } + + protected List<Integer> getSystemBarSidesByZOrder() { + return mSystemBarSidesByZOrder; + } + + @VisibleForTesting + protected static int getHunZOrder() { + return HUN_ZORDER; + } + + private static void populateMaps() { + BAR_GRAVITY_MAP.put(TOP, Gravity.TOP); + BAR_GRAVITY_MAP.put(BOTTOM, Gravity.BOTTOM); + BAR_GRAVITY_MAP.put(LEFT, Gravity.LEFT); + BAR_GRAVITY_MAP.put(RIGHT, Gravity.RIGHT); + + BAR_TITLE_MAP.put(TOP, "TopCarSystemBar"); + BAR_TITLE_MAP.put(BOTTOM, "BottomCarSystemBar"); + BAR_TITLE_MAP.put(LEFT, "LeftCarSystemBar"); + BAR_TITLE_MAP.put(RIGHT, "RightCarSystemBar"); + + BAR_GESTURE_MAP.put(TOP, InsetsState.ITYPE_TOP_MANDATORY_GESTURES); + BAR_GESTURE_MAP.put(BOTTOM, InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES); + BAR_GESTURE_MAP.put(LEFT, InsetsState.ITYPE_LEFT_MANDATORY_GESTURES); + BAR_GESTURE_MAP.put(RIGHT, InsetsState.ITYPE_RIGHT_MANDATORY_GESTURES); + } + + private void readConfigs() { + mTopNavBarEnabled = mResources.getBoolean(R.bool.config_enableTopNavigationBar); + mBottomNavBarEnabled = mResources.getBoolean(R.bool.config_enableBottomNavigationBar); + mLeftNavBarEnabled = mResources.getBoolean(R.bool.config_enableLeftNavigationBar); + mRightNavBarEnabled = mResources.getBoolean(R.bool.config_enableRightNavigationBar); + + if (mTopNavBarEnabled) { + SystemBarConfig topBarConfig = + new SystemBarConfigBuilder() + .setSide(TOP) + .setGirth(mResources.getDimensionPixelSize( + R.dimen.car_top_navigation_bar_height)) + .setBarType(mResources.getInteger(R.integer.config_topSystemBarType)) + .setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder)) + .setHideForKeyboard(mResources.getBoolean( + R.bool.config_hideTopSystemBarForKeyboard)) + .build(); + mSystemBarConfigMap.put(TOP, topBarConfig); + } + + if (mBottomNavBarEnabled) { + SystemBarConfig bottomBarConfig = + new SystemBarConfigBuilder() + .setSide(BOTTOM) + .setGirth(mResources.getDimensionPixelSize( + R.dimen.car_bottom_navigation_bar_height)) + .setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType)) + .setZOrder( + mResources.getInteger(R.integer.config_bottomSystemBarZOrder)) + .setHideForKeyboard(mResources.getBoolean( + R.bool.config_hideBottomSystemBarForKeyboard)) + .build(); + mSystemBarConfigMap.put(BOTTOM, bottomBarConfig); + } + + if (mLeftNavBarEnabled) { + SystemBarConfig leftBarConfig = + new SystemBarConfigBuilder() + .setSide(LEFT) + .setGirth(mResources.getDimensionPixelSize( + R.dimen.car_left_navigation_bar_width)) + .setBarType(mResources.getInteger(R.integer.config_leftSystemBarType)) + .setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder)) + .setHideForKeyboard(mResources.getBoolean( + R.bool.config_hideLeftSystemBarForKeyboard)) + .build(); + mSystemBarConfigMap.put(LEFT, leftBarConfig); + } + + if (mRightNavBarEnabled) { + SystemBarConfig rightBarConfig = + new SystemBarConfigBuilder() + .setSide(RIGHT) + .setGirth(mResources.getDimensionPixelSize( + R.dimen.car_right_navigation_bar_width)) + .setBarType(mResources.getInteger(R.integer.config_rightSystemBarType)) + .setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder)) + .setHideForKeyboard(mResources.getBoolean( + R.bool.config_hideRightSystemBarForKeyboard)) + .build(); + mSystemBarConfigMap.put(RIGHT, rightBarConfig); + } + } + + private void checkEnabledBarsHaveUniqueBarTypes() throws RuntimeException { + Set<Integer> barTypesUsed = new ArraySet<>(); + int enabledNavBarCount = mSystemBarConfigMap.size(); + + for (SystemBarConfig systemBarConfig : mSystemBarConfigMap.values()) { + barTypesUsed.add(systemBarConfig.getBarType()); + } + + // The number of bar types used cannot be fewer than that of enabled system bars. + if (barTypesUsed.size() < enabledNavBarCount) { + throw new RuntimeException("Each enabled system bar must have a unique bar type. Check " + + "the configuration in config.xml"); + } + } + + private void checkSystemBarEnabledForNotificationPanel() throws RuntimeException { + + String notificationPanelMediatorName = + mResources.getString(R.string.config_notificationPanelViewMediator); + if (notificationPanelMediatorName == null) { + return; + } + + Class<?> notificationPanelMediatorUsed = null; + try { + notificationPanelMediatorUsed = Class.forName(notificationPanelMediatorName); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + if (!mTopNavBarEnabled && TopNotificationPanelViewMediator.class.isAssignableFrom( + notificationPanelMediatorUsed)) { + throw new RuntimeException( + "Top System Bar must be enabled to use " + notificationPanelMediatorName); + } + + if (!mBottomNavBarEnabled && BottomNotificationPanelViewMediator.class.isAssignableFrom( + notificationPanelMediatorUsed)) { + throw new RuntimeException("Bottom System Bar must be enabled to use " + + notificationPanelMediatorName); + } + } + + private void checkHideBottomBarForKeyboardConfigSync() throws RuntimeException { + if (mBottomNavBarEnabled) { + boolean actual = mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard); + boolean expected = mResources.getBoolean( + com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard); + + if (actual != expected) { + throw new RuntimeException("config_hideBottomSystemBarForKeyboard must not be " + + "overlaid directly and should always refer to" + + "config_automotiveHideNavBarForKeyboard. However, their values " + + "currently do not sync. Set config_hideBottomSystemBarForKeyguard to " + + "@*android:bool/config_automotiveHideNavBarForKeyboard. To change its " + + "value, overlay config_automotiveHideNavBarForKeyboard in " + + "framework/base/core/res/res."); + } + } + } + + private void setInsetPaddingsForOverlappingCorners() { + setInsetPaddingForOverlappingCorner(TOP, LEFT); + setInsetPaddingForOverlappingCorner(TOP, RIGHT); + setInsetPaddingForOverlappingCorner(BOTTOM, LEFT); + setInsetPaddingForOverlappingCorner(BOTTOM, RIGHT); + } + + private void setInsetPaddingForOverlappingCorner(@SystemBarSide int horizontalSide, + @SystemBarSide int verticalSide) { + + if (isVerticalBar(horizontalSide) || isHorizontalBar(verticalSide)) { + Log.w(TAG, "configureBarPaddings: Returning immediately since the horizontal and " + + "vertical sides were not provided correctly."); + return; + } + + SystemBarConfig horizontalBarConfig = mSystemBarConfigMap.get(horizontalSide); + SystemBarConfig verticalBarConfig = mSystemBarConfigMap.get(verticalSide); + + if (verticalBarConfig != null && horizontalBarConfig != null) { + int horizontalBarZOrder = horizontalBarConfig.getZOrder(); + int horizontalBarGirth = horizontalBarConfig.getGirth(); + int verticalBarZOrder = verticalBarConfig.getZOrder(); + int verticalBarGirth = verticalBarConfig.getGirth(); + + if (horizontalBarZOrder > verticalBarZOrder) { + verticalBarConfig.setPaddingBySide(horizontalSide, horizontalBarGirth); + } else if (horizontalBarZOrder < verticalBarZOrder) { + horizontalBarConfig.setPaddingBySide(verticalSide, verticalBarGirth); + } else { + throw new RuntimeException( + BAR_TITLE_MAP.get(horizontalSide) + " " + BAR_TITLE_MAP.get(verticalSide) + + " have the same Z-Order, and so their placing order cannot be " + + "determined. Determine which bar should be placed on top of the " + + "other bar and change the Z-order in config.xml accordingly." + ); + } + } + } + + private void sortSystemBarSidesByZOrder() { + List<SystemBarConfig> systemBarsByZOrder = new ArrayList<>(mSystemBarConfigMap.values()); + + systemBarsByZOrder.sort(new Comparator<SystemBarConfig>() { + @Override + public int compare(SystemBarConfig o1, SystemBarConfig o2) { + return o1.getZOrder() - o2.getZOrder(); + } + }); + + systemBarsByZOrder.forEach(systemBarConfig -> { + mSystemBarSidesByZOrder.add(systemBarConfig.getSide()); + }); + } + + private static boolean isHorizontalBar(@SystemBarSide int side) { + return side == TOP || side == BOTTOM; + } + + private static boolean isVerticalBar(@SystemBarSide int side) { + return side == LEFT || side == RIGHT; + } + + private static final class SystemBarConfig { + private final int mSide; + private final int mBarType; + private final int mGirth; + private final int mZOrder; + private final boolean mHideForKeyboard; + + private int[] mPaddings = new int[]{0, 0, 0, 0}; + + private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder, + boolean hideForKeyboard) { + mSide = side; + mBarType = barType; + mGirth = girth; + mZOrder = zOrder; + mHideForKeyboard = hideForKeyboard; + } + + private int getSide() { + return mSide; + } + + private int getBarType() { + return mBarType; + } + + private int getGirth() { + return mGirth; + } + + private int getZOrder() { + return mZOrder; + } + + private boolean getHideForKeyboard() { + return mHideForKeyboard; + } + + private int[] getPaddings() { + return mPaddings; + } + + private WindowManager.LayoutParams getLayoutParams() { + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + isHorizontalBar(mSide) ? ViewGroup.LayoutParams.MATCH_PARENT : mGirth, + isHorizontalBar(mSide) ? mGirth : ViewGroup.LayoutParams.MATCH_PARENT, + mapZOrderToBarType(mZOrder), + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, + PixelFormat.TRANSLUCENT); + lp.setTitle(BAR_TITLE_MAP.get(mSide)); + lp.providesInsetsTypes = new int[]{BAR_TYPE_MAP[mBarType], BAR_GESTURE_MAP.get(mSide)}; + lp.setFitInsetsTypes(0); + lp.windowAnimations = 0; + lp.gravity = BAR_GRAVITY_MAP.get(mSide); + return lp; + } + + private int mapZOrderToBarType(int zOrder) { + return zOrder >= HUN_ZORDER ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL + : WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; + } + + private void setPaddingBySide(@SystemBarSide int side, int padding) { + mPaddings[side] = padding; + } + } + + private static final class SystemBarConfigBuilder { + private int mSide; + private int mBarType; + private int mGirth; + private int mZOrder; + private boolean mHideForKeyboard; + + private SystemBarConfigBuilder setSide(@SystemBarSide int side) { + mSide = side; + return this; + } + + private SystemBarConfigBuilder setBarType(int type) { + mBarType = type; + return this; + } + + private SystemBarConfigBuilder setGirth(int girth) { + mGirth = girth; + return this; + } + + private SystemBarConfigBuilder setZOrder(int zOrder) { + mZOrder = zOrder; + return this; + } + + private SystemBarConfigBuilder setHideForKeyboard(boolean hide) { + mHideForKeyboard = hide; + return this; + } + + private SystemBarConfig build() { + return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder, mHideForKeyboard); + } + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java index 1eead62c042a..fd804c71c9d0 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java @@ -23,6 +23,8 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.inputmethodservice.InputMethodService; +import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.GestureDetector; @@ -80,6 +82,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController private final StatusBarStateController mStatusBarStateController; private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen; private final NotificationVisibilityLogger mNotificationVisibilityLogger; + private final int mNavBarHeight; private float mInitialBackgroundAlpha; private float mBackgroundAlphaDiff; @@ -89,7 +92,6 @@ public class NotificationPanelViewController extends OverlayPanelViewController private RecyclerView mNotificationList; private NotificationViewController mNotificationViewController; - private boolean mIsTracking; private boolean mNotificationListAtEnd; private float mFirstTouchDownOnGlassPane; private boolean mNotificationListAtEndAtTimeOfTouch; @@ -137,7 +139,10 @@ public class NotificationPanelViewController extends OverlayPanelViewController mStatusBarStateController = statusBarStateController; mNotificationVisibilityLogger = notificationVisibilityLogger; + mNavBarHeight = mResources.getDimensionPixelSize(R.dimen.car_bottom_navigation_bar_height); + mCommandQueue.addCallback(this); + // Notification background setup. mInitialBackgroundAlpha = (float) mResources.getInteger( R.integer.config_initialNotificationBackgroundAlpha) / 100; @@ -178,6 +183,27 @@ public class NotificationPanelViewController extends OverlayPanelViewController } } + @Override + public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, + boolean showImeSwitcher) { + if (mContext.getDisplayId() != displayId) { + return; + } + boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; + int bottomMargin = isKeyboardVisible ? 0 : mNavBarHeight; + ViewGroup container = (ViewGroup) getLayout(); + if (container == null) { + // Notification panel hasn't been inflated before. We shouldn't try to update the layout + // params. + return; + } + + ViewGroup.MarginLayoutParams params = + (ViewGroup.MarginLayoutParams) container.getLayoutParams(); + params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, bottomMargin); + container.setLayoutParams(params); + } + // OverlayViewController @Override @@ -192,11 +218,21 @@ public class NotificationPanelViewController extends OverlayPanelViewController } @Override - protected boolean shouldShowNavigationBar() { + protected boolean shouldShowNavigationBarInsets() { + return true; + } + + @Override + protected boolean shouldShowStatusBarInsets() { return true; } @Override + protected int getInsetTypesToFit() { + return 0; + } + + @Override protected boolean shouldShowHUN() { return mEnableHeadsUpNotificationWhenNotificationShadeOpen; } @@ -287,14 +323,14 @@ public class NotificationPanelViewController extends OverlayPanelViewController // The glass pane is used to view touch events before passed to the notification list. // This allows us to initialize gesture listeners and detect when to close the notifications glassPane.setOnTouchListener((v, event) -> { - if (event.getActionMasked() == MotionEvent.ACTION_UP) { + if (isClosingAction(event)) { mNotificationListAtEndAtTimeOfTouch = false; } - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (isOpeningAction(event)) { mFirstTouchDownOnGlassPane = event.getRawX(); mNotificationListAtEndAtTimeOfTouch = mNotificationListAtEnd; // Reset the tracker when there is a touch down on the glass pane. - mIsTracking = false; + setIsTracking(false); // Pass the down event to gesture detector so that it knows where the touch event // started. closeGestureDetector.onTouchEvent(event); @@ -329,22 +365,21 @@ public class NotificationPanelViewController extends OverlayPanelViewController // If the card is swiping we should not allow the notification shade to close. // Hence setting mNotificationListAtEndAtTimeOfTouch to false will stop that - // for us. We are also checking for mIsTracking because while swiping the + // for us. We are also checking for isTracking() because while swiping the // notification shade to close if the user goes a bit horizontal while swiping // upwards then also this should close. - if (mIsNotificationCardSwiping && !mIsTracking) { + if (mIsNotificationCardSwiping && !isTracking()) { mNotificationListAtEndAtTimeOfTouch = false; } boolean handled = closeGestureDetector.onTouchEvent(event); - boolean isTracking = mIsTracking; + boolean isTracking = isTracking(); Rect rect = getLayout().getClipBounds(); float clippedHeight = 0; if (rect != null) { clippedHeight = rect.bottom; } - if (!handled && event.getActionMasked() == MotionEvent.ACTION_UP - && mIsSwipingVerticallyToClose) { + if (!handled && isClosingAction(event) && mIsSwipingVerticallyToClose) { if (getSettleClosePercentage() < getPercentageFromEndingEdge() && isTracking) { animatePanel(DEFAULT_FLING_VELOCITY, false); } else if (clippedHeight != getLayout().getHeight() && isTracking) { @@ -357,7 +392,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController // Updating the mNotificationListAtEndAtTimeOfTouch state has to be done after // the event has been passed to the closeGestureDetector above, such that the // closeGestureDetector sees the up event before the state has changed. - if (event.getActionMasked() == MotionEvent.ACTION_UP) { + if (isClosingAction(event)) { mNotificationListAtEndAtTimeOfTouch = false; } return handled || isTracking; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java deleted file mode 100644 index d692487d410e..000000000000 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (C) 2020 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.statusbar; - -import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; - -import android.annotation.Nullable; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.PowerManager; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.View; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.statusbar.RegisterStatusBarResult; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.BatteryMeterView; -import com.android.systemui.Dependency; -import com.android.systemui.InitController; -import com.android.systemui.Prefs; -import com.android.systemui.R; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.bubbles.BubbleController; -import com.android.systemui.car.CarDeviceProvisionedController; -import com.android.systemui.car.CarDeviceProvisionedListener; -import com.android.systemui.car.bluetooth.CarBatteryController; -import com.android.systemui.car.navigationbar.CarNavigationBarController; -import com.android.systemui.classifier.FalsingLog; -import com.android.systemui.colorextraction.SysuiColorExtractor; -import com.android.systemui.dagger.qualifiers.UiBackground; -import com.android.systemui.fragments.FragmentHostManager; -import com.android.systemui.keyguard.DismissCallbackRegistry; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.ScreenLifecycle; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.plugins.DarkIconDispatcher; -import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.PluginDependencyProvider; -import com.android.systemui.plugins.qs.QS; -import com.android.systemui.recents.Recents; -import com.android.systemui.recents.ScreenPinningRequest; -import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.stackdivider.Divider; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.KeyguardIndicationController; -import com.android.systemui.statusbar.NavigationBarController; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.NotificationRemoteInputManager; -import com.android.systemui.statusbar.NotificationShadeDepthController; -import com.android.systemui.statusbar.NotificationViewHierarchyManager; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.SuperStatusBarViewFactory; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.VibratorHelper; -import com.android.systemui.statusbar.notification.DynamicPrivacyController; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.init.NotificationsController; -import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; -import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; -import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor; -import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.NotificationGutsManager; -import com.android.systemui.statusbar.phone.AutoHideController; -import com.android.systemui.statusbar.phone.BiometricUnlockController; -import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; -import com.android.systemui.statusbar.phone.DozeParameters; -import com.android.systemui.statusbar.phone.DozeScrimController; -import com.android.systemui.statusbar.phone.DozeServiceHost; -import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; -import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.KeyguardDismissUtil; -import com.android.systemui.statusbar.phone.LightBarController; -import com.android.systemui.statusbar.phone.LightsOutNotifController; -import com.android.systemui.statusbar.phone.LockscreenLockIconController; -import com.android.systemui.statusbar.phone.LockscreenWallpaper; -import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; -import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; -import com.android.systemui.statusbar.phone.ScrimController; -import com.android.systemui.statusbar.phone.ShadeController; -import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.statusbar.phone.StatusBarIconController; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; -import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; -import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.ExtensionController; -import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; -import com.android.systemui.statusbar.policy.UserInfoControllerImpl; -import com.android.systemui.statusbar.policy.UserSwitcherController; -import com.android.systemui.volume.VolumeComponent; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.Executor; - -import javax.inject.Named; -import javax.inject.Provider; - -import dagger.Lazy; - -/** - * A status bar tailored for the automotive use case. - */ -public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler { - private static final String TAG = "CarStatusBar"; - - private final UserSwitcherController mUserSwitcherController; - private final ScrimController mScrimController; - - private CarBatteryController mCarBatteryController; - private BatteryMeterView mBatteryMeterView; - private Drawable mNotificationPanelBackground; - - private final Object mQueueLock = new Object(); - private final CarNavigationBarController mCarNavigationBarController; - private final CarDeviceProvisionedController mCarDeviceProvisionedController; - private final ScreenLifecycle mScreenLifecycle; - - private boolean mDeviceIsSetUpForUser = true; - private boolean mIsUserSetupInProgress = false; - - public CarStatusBar( - Context context, - NotificationsController notificationsController, - LightBarController lightBarController, - AutoHideController autoHideController, - KeyguardUpdateMonitor keyguardUpdateMonitor, - StatusBarIconController statusBarIconController, - PulseExpansionHandler pulseExpansionHandler, - NotificationWakeUpCoordinator notificationWakeUpCoordinator, - KeyguardBypassController keyguardBypassController, - KeyguardStateController keyguardStateController, - HeadsUpManagerPhone headsUpManagerPhone, - DynamicPrivacyController dynamicPrivacyController, - BypassHeadsUpNotifier bypassHeadsUpNotifier, - FalsingManager falsingManager, - BroadcastDispatcher broadcastDispatcher, - RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, - NotificationGutsManager notificationGutsManager, - NotificationLogger notificationLogger, - NotificationInterruptStateProvider notificationInterruptStateProvider, - NotificationViewHierarchyManager notificationViewHierarchyManager, - KeyguardViewMediator keyguardViewMediator, - DisplayMetrics displayMetrics, - MetricsLogger metricsLogger, - @UiBackground Executor uiBgExecutor, - NotificationMediaManager notificationMediaManager, - NotificationLockscreenUserManager lockScreenUserManager, - NotificationRemoteInputManager remoteInputManager, - UserSwitcherController userSwitcherController, - NetworkController networkController, - BatteryController batteryController, - SysuiColorExtractor colorExtractor, - ScreenLifecycle screenLifecycle, - WakefulnessLifecycle wakefulnessLifecycle, - SysuiStatusBarStateController statusBarStateController, - VibratorHelper vibratorHelper, - BubbleController bubbleController, - NotificationGroupManager groupManager, - VisualStabilityManager visualStabilityManager, - CarDeviceProvisionedController carDeviceProvisionedController, - NavigationBarController navigationBarController, - Lazy<AssistManager> assistManagerLazy, - ConfigurationController configurationController, - NotificationShadeWindowController notificationShadeWindowController, - LockscreenLockIconController lockscreenLockIconController, - DozeParameters dozeParameters, - ScrimController scrimController, - Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, - Lazy<BiometricUnlockController> biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - ScreenPinningRequest screenPinningRequest, - DozeScrimController dozeScrimController, - VolumeComponent volumeComponent, - CommandQueue commandQueue, - Optional<Recents> recents, - Provider<StatusBarComponent.Builder> statusBarComponentBuilder, - PluginManager pluginManager, - Optional<Divider> dividerOptional, - SuperStatusBarViewFactory superStatusBarViewFactory, - LightsOutNotifController lightsOutNotifController, - StatusBarNotificationActivityStarter.Builder - statusBarNotificationActivityStarterBuilder, - ShadeController shadeController, - StatusBarKeyguardViewManager statusBarKeyguardViewManager, - ViewMediatorCallback viewMediatorCallback, - InitController initController, - DarkIconDispatcher darkIconDispatcher, - @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, - PluginDependencyProvider pluginDependencyProvider, - KeyguardDismissUtil keyguardDismissUtil, - ExtensionController extensionController, - UserInfoControllerImpl userInfoControllerImpl, - PhoneStatusBarPolicy phoneStatusBarPolicy, - KeyguardIndicationController keyguardIndicationController, - DismissCallbackRegistry dismissCallbackRegistry, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, - Lazy<NotificationShadeDepthController> depthControllerLazy, - /* Car Settings injected components. */ - CarNavigationBarController carNavigationBarController) { - super( - context, - notificationsController, - lightBarController, - autoHideController, - keyguardUpdateMonitor, - statusBarIconController, - pulseExpansionHandler, - notificationWakeUpCoordinator, - keyguardBypassController, - keyguardStateController, - headsUpManagerPhone, - dynamicPrivacyController, - bypassHeadsUpNotifier, - falsingManager, - broadcastDispatcher, - remoteInputQuickSettingsDisabler, - notificationGutsManager, - notificationLogger, - notificationInterruptStateProvider, - notificationViewHierarchyManager, - keyguardViewMediator, - displayMetrics, - metricsLogger, - uiBgExecutor, - notificationMediaManager, - lockScreenUserManager, - remoteInputManager, - userSwitcherController, - networkController, - batteryController, - colorExtractor, - screenLifecycle, - wakefulnessLifecycle, - statusBarStateController, - vibratorHelper, - bubbleController, - groupManager, - visualStabilityManager, - carDeviceProvisionedController, - navigationBarController, - assistManagerLazy, - configurationController, - notificationShadeWindowController, - lockscreenLockIconController, - dozeParameters, - scrimController, - null /* keyguardLiftController */, - lockscreenWallpaperLazy, - biometricUnlockControllerLazy, - dozeServiceHost, - powerManager, - screenPinningRequest, - dozeScrimController, - volumeComponent, - commandQueue, - recents, - statusBarComponentBuilder, - pluginManager, - dividerOptional, - lightsOutNotifController, - statusBarNotificationActivityStarterBuilder, - shadeController, - superStatusBarViewFactory, - statusBarKeyguardViewManager, - viewMediatorCallback, - initController, - darkIconDispatcher, - timeTickHandler, - pluginDependencyProvider, - keyguardDismissUtil, - extensionController, - userInfoControllerImpl, - phoneStatusBarPolicy, - keyguardIndicationController, - dismissCallbackRegistry, - depthControllerLazy, - statusBarTouchableRegionManager); - mUserSwitcherController = userSwitcherController; - mScrimController = scrimController; - mCarDeviceProvisionedController = carDeviceProvisionedController; - mCarNavigationBarController = carNavigationBarController; - mScreenLifecycle = screenLifecycle; - } - - @Override - public void start() { - mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup(); - mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress(); - - super.start(); - - createBatteryController(); - mCarBatteryController.startListening(); - - mCarDeviceProvisionedController.addCallback( - new CarDeviceProvisionedListener() { - @Override - public void onUserSetupInProgressChanged() { - mDeviceIsSetUpForUser = mCarDeviceProvisionedController - .isCurrentUserSetup(); - mIsUserSetupInProgress = mCarDeviceProvisionedController - .isCurrentUserSetupInProgress(); - } - - @Override - public void onUserSetupChanged() { - mDeviceIsSetUpForUser = mCarDeviceProvisionedController - .isCurrentUserSetup(); - mIsUserSetupInProgress = mCarDeviceProvisionedController - .isCurrentUserSetupInProgress(); - } - - @Override - public void onUserSwitched() { - mDeviceIsSetUpForUser = mCarDeviceProvisionedController - .isCurrentUserSetup(); - mIsUserSetupInProgress = mCarDeviceProvisionedController - .isCurrentUserSetupInProgress(); - } - }); - - mNotificationInterruptStateProvider.addSuppressor(new NotificationInterruptSuppressor() { - @Override - public String getName() { - return TAG; - } - - @Override - public boolean suppressInterruptions(NotificationEntry entry) { - // Because space is usually constrained in the auto use-case, there should not be a - // pinned notification when the shade has been expanded. - // Ensure this by not allowing any interruptions (ie: pinning any notifications) if - // the shade is already opened. - return !getPresenter().isPresenterFullyCollapsed(); - } - }); - } - - @Override - public boolean hideKeyguard() { - boolean result = super.hideKeyguard(); - mCarNavigationBarController.hideAllKeyguardButtons(isDeviceSetupForUser()); - return result; - } - - @Override - public void showKeyguard() { - super.showKeyguard(); - mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser()); - } - - private boolean isDeviceSetupForUser() { - return mDeviceIsSetUpForUser && !mIsUserSetupInProgress; - } - - @Override - protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) { - super.makeStatusBarView(result); - - mNotificationPanelBackground = getDefaultWallpaper(); - mScrimController.setScrimBehindDrawable(mNotificationPanelBackground); - - FragmentHostManager manager = FragmentHostManager.get(mPhoneStatusBarWindow); - manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { - mBatteryMeterView = fragment.getView().findViewById(R.id.battery); - - // By default, the BatteryMeterView should not be visible. It will be toggled - // when a device has connected by bluetooth. - mBatteryMeterView.setVisibility(View.GONE); - }); - } - - @Override - public void animateExpandNotificationsPanel() { - // No op. - } - - @Override - protected QS createDefaultQSFragment() { - return null; - } - - private BatteryController createBatteryController() { - mCarBatteryController = new CarBatteryController(mContext); - mCarBatteryController.addBatteryViewHandler(this); - return mCarBatteryController; - } - - @Override - protected void createNavigationBar(@Nullable RegisterStatusBarResult result) { - // No op. - } - - @Override - public void notifyBiometricAuthModeChanged() { - // No op. - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - //When executing dump() function simultaneously, we need to serialize them - //to get mStackScroller's position correctly. - synchronized (mQueueLock) { - pw.println(" mStackScroller: " + viewInfo(mStackScroller)); - pw.println(" mStackScroller: " + viewInfo(mStackScroller) - + " scroll " + mStackScroller.getScrollX() - + "," + mStackScroller.getScrollY()); - } - pw.print(" mCarBatteryController="); - pw.println(mCarBatteryController); - pw.print(" mBatteryMeterView="); - pw.println(mBatteryMeterView); - - if (Dependency.get(KeyguardUpdateMonitor.class) != null) { - Dependency.get(KeyguardUpdateMonitor.class).dump(fd, pw, args); - } - - FalsingLog.dump(pw); - - pw.println("SharedPreferences:"); - for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) { - pw.print(" "); - pw.print(entry.getKey()); - pw.print("="); - pw.println(entry.getValue()); - } - } - - @Override - public void showBatteryView() { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView); - } - - if (mBatteryMeterView != null) { - mBatteryMeterView.setVisibility(View.VISIBLE); - } - } - - @Override - public void hideBatteryView() { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView); - } - - if (mBatteryMeterView != null) { - mBatteryMeterView.setVisibility(View.GONE); - } - } - - @Override - protected void createUserSwitcher() { - if (!mUserSwitcherController.useFullscreenUserSwitcher()) { - super.createUserSwitcher(); - } - } - - /** - * Dismisses the keyguard and shows bouncer if authentication is necessary. - */ - public void dismissKeyguard() { - // Don't dismiss keyguard when the screen is off. - if (mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF) { - return; - } - executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */, - true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */); - } - - /** - * Ensures that relevant child views are appropriately recreated when the device's density - * changes. - */ - @Override - public void onDensityOrFontScaleChanged() { - super.onDensityOrFontScaleChanged(); - // Need to update the background on density changed in case the change was due to night - // mode. - mNotificationPanelBackground = getDefaultWallpaper(); - mScrimController.setScrimBehindDrawable(mNotificationPanelBackground); - } - - /** - * Returns the {@link Drawable} that represents the wallpaper that the user has currently set. - */ - private Drawable getDefaultWallpaper() { - return mContext.getDrawable(com.android.internal.R.drawable.default_wallpaper); - } -} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarKeyguardViewManager.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarKeyguardViewManager.java deleted file mode 100644 index 96a998a500e1..000000000000 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarKeyguardViewManager.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2020 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.statusbar; - -import android.content.Context; -import android.view.View; - -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.R; -import com.android.systemui.car.navigationbar.CarNavigationBarController; -import com.android.systemui.dock.DockManager; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.phone.NavigationModeController; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.KeyguardStateController; - -import java.util.HashSet; -import java.util.Set; - -import javax.inject.Inject; -import javax.inject.Singleton; - -/** Car implementation of the {@link StatusBarKeyguardViewManager}. */ -@Singleton -public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager { - - protected boolean mShouldHideNavBar; - private final CarNavigationBarController mCarNavigationBarController; - private Set<OnKeyguardCancelClickedListener> mKeygaurdCancelClickedListenerSet; - - @Inject - public CarStatusBarKeyguardViewManager(Context context, - ViewMediatorCallback callback, - LockPatternUtils lockPatternUtils, - SysuiStatusBarStateController sysuiStatusBarStateController, - ConfigurationController configurationController, - KeyguardUpdateMonitor keyguardUpdateMonitor, - NavigationModeController navigationModeController, - DockManager dockManager, - NotificationShadeWindowController notificationShadeWindowController, - KeyguardStateController keyguardStateController, - NotificationMediaManager notificationMediaManager, - CarNavigationBarController carNavigationBarController) { - super(context, callback, lockPatternUtils, sysuiStatusBarStateController, - configurationController, keyguardUpdateMonitor, navigationModeController, - dockManager, notificationShadeWindowController, keyguardStateController, - notificationMediaManager); - mShouldHideNavBar = context.getResources() - .getBoolean(R.bool.config_hideNavWhenKeyguardBouncerShown); - mCarNavigationBarController = carNavigationBarController; - mKeygaurdCancelClickedListenerSet = new HashSet<>(); - } - - @Override - protected void updateNavigationBarVisibility(boolean navBarVisible) { - if (!mShouldHideNavBar) { - return; - } - int visibility = navBarVisible ? View.VISIBLE : View.GONE; - mCarNavigationBarController.setBottomWindowVisibility(visibility); - mCarNavigationBarController.setLeftWindowVisibility(visibility); - mCarNavigationBarController.setRightWindowVisibility(visibility); - } - - /** - * Car is a multi-user system. There's a cancel button on the bouncer that allows the user to - * go back to the user switcher and select another user. Different user may have different - * security mode which requires bouncer container to be resized. For this reason, the bouncer - * view is destroyed on cancel. - */ - @Override - protected boolean shouldDestroyViewOnReset() { - return true; - } - - /** - * Called when cancel button in bouncer is pressed. - */ - @Override - public void onCancelClicked() { - mKeygaurdCancelClickedListenerSet.forEach(OnKeyguardCancelClickedListener::onCancelClicked); - } - - /** - * Do nothing on this change. - * The base class hides the keyguard which for automotive we want to avoid b/c this would happen - * on a configuration change due to day/night (headlight state). - */ - @Override - public void onDensityOrFontScaleChanged() { } - - /** - * Add listener for keyguard cancel clicked. - */ - public void addOnKeyguardCancelClickedListener( - OnKeyguardCancelClickedListener keyguardCancelClickedListener) { - mKeygaurdCancelClickedListenerSet.add(keyguardCancelClickedListener); - } - - /** - * Remove listener for keyguard cancel clicked. - */ - public void removeOnKeyguardCancelClickedListener( - OnKeyguardCancelClickedListener keyguardCancelClickedListener) { - mKeygaurdCancelClickedListenerSet.remove(keyguardCancelClickedListener); - } - - - /** - * Defines a callback for keyguard cancel button clicked listeners. - */ - public interface OnKeyguardCancelClickedListener { - /** - * Called when keyguard cancel button is clicked. - */ - void onCancelClicked(); - } -} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java new file mode 100644 index 000000000000..48334bd6e5c7 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2020 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.statusbar; + +import android.content.Context; +import android.os.Handler; +import android.os.PowerManager; +import android.util.DisplayMetrics; + +import com.android.internal.logging.MetricsLogger; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.InitController; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.keyguard.DismissCallbackRegistry; +import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.DarkIconDispatcher; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.PluginDependencyProvider; +import com.android.systemui.recents.Recents; +import com.android.systemui.recents.ScreenPinningRequest; +import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.stackdivider.Divider; +import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.KeyguardIndicationController; +import com.android.systemui.statusbar.NavigationBarController; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationViewHierarchyManager; +import com.android.systemui.statusbar.PulseExpansionHandler; +import com.android.systemui.statusbar.SuperStatusBarViewFactory; +import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.VibratorHelper; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.init.NotificationsController; +import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; +import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; +import com.android.systemui.statusbar.notification.logging.NotificationLogger; +import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.phone.AutoHideController; +import com.android.systemui.statusbar.phone.BiometricUnlockController; +import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.DozeScrimController; +import com.android.systemui.statusbar.phone.DozeServiceHost; +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; +import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.KeyguardDismissUtil; +import com.android.systemui.statusbar.phone.KeyguardLiftController; +import com.android.systemui.statusbar.phone.LightBarController; +import com.android.systemui.statusbar.phone.LightsOutNotifController; +import com.android.systemui.statusbar.phone.LockscreenLockIconController; +import com.android.systemui.statusbar.phone.LockscreenWallpaper; +import com.android.systemui.statusbar.phone.NavigationBarView; +import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; +import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.phone.ShadeController; +import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; +import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; +import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.ExtensionController; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; +import com.android.systemui.statusbar.policy.UserInfoControllerImpl; +import com.android.systemui.statusbar.policy.UserSwitcherController; +import com.android.systemui.volume.VolumeComponent; + +import java.util.Optional; +import java.util.concurrent.Executor; + +import javax.inject.Provider; + +import dagger.Lazy; + +/** Unused variant of {@link StatusBar} specifically used in the automotive context. */ +public class UnusedStatusBar extends StatusBar { + + public UnusedStatusBar(Context context, + NotificationsController notificationsController, + LightBarController lightBarController, + AutoHideController autoHideController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + StatusBarIconController statusBarIconController, + PulseExpansionHandler pulseExpansionHandler, + NotificationWakeUpCoordinator notificationWakeUpCoordinator, + KeyguardBypassController keyguardBypassController, + KeyguardStateController keyguardStateController, + HeadsUpManagerPhone headsUpManagerPhone, + DynamicPrivacyController dynamicPrivacyController, + BypassHeadsUpNotifier bypassHeadsUpNotifier, + FalsingManager falsingManager, + BroadcastDispatcher broadcastDispatcher, + RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, + NotificationGutsManager notificationGutsManager, + NotificationLogger notificationLogger, + NotificationInterruptStateProvider notificationInterruptStateProvider, + NotificationViewHierarchyManager notificationViewHierarchyManager, + KeyguardViewMediator keyguardViewMediator, + DisplayMetrics displayMetrics, + MetricsLogger metricsLogger, + Executor uiBgExecutor, + NotificationMediaManager notificationMediaManager, + NotificationLockscreenUserManager lockScreenUserManager, + NotificationRemoteInputManager remoteInputManager, + UserSwitcherController userSwitcherController, + NetworkController networkController, + BatteryController batteryController, + SysuiColorExtractor colorExtractor, + ScreenLifecycle screenLifecycle, + WakefulnessLifecycle wakefulnessLifecycle, + SysuiStatusBarStateController statusBarStateController, + VibratorHelper vibratorHelper, + BubbleController bubbleController, + NotificationGroupManager groupManager, + VisualStabilityManager visualStabilityManager, + DeviceProvisionedController deviceProvisionedController, + NavigationBarController navigationBarController, + Lazy<AssistManager> assistManagerLazy, + ConfigurationController configurationController, + NotificationShadeWindowController notificationShadeWindowController, + LockscreenLockIconController lockscreenLockIconController, + DozeParameters dozeParameters, + ScrimController scrimController, + KeyguardLiftController keyguardLiftController, + Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, + Lazy<BiometricUnlockController> biometricUnlockControllerLazy, + DozeServiceHost dozeServiceHost, + PowerManager powerManager, + ScreenPinningRequest screenPinningRequest, + DozeScrimController dozeScrimController, + VolumeComponent volumeComponent, + CommandQueue commandQueue, + Optional<Recents> recentsOptional, + Provider<StatusBarComponent.Builder> statusBarComponentBuilder, + PluginManager pluginManager, + Optional<Divider> dividerOptional, + LightsOutNotifController lightsOutNotifController, + StatusBarNotificationActivityStarter.Builder statusBarNotifActivityStarterBuilder, + ShadeController shadeController, + SuperStatusBarViewFactory superStatusBarViewFactory, + StatusBarKeyguardViewManager statusBarKeyguardViewManager, + ViewMediatorCallback viewMediatorCallback, + InitController initController, + DarkIconDispatcher darkIconDispatcher, + Handler timeTickHandler, + PluginDependencyProvider pluginDependencyProvider, + KeyguardDismissUtil keyguardDismissUtil, + ExtensionController extensionController, + UserInfoControllerImpl userInfoControllerImpl, + PhoneStatusBarPolicy phoneStatusBarPolicy, + KeyguardIndicationController keyguardIndicationController, + DismissCallbackRegistry dismissCallbackRegistry, + Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy, + StatusBarTouchableRegionManager statusBarTouchableRegionManager) { + super(context, notificationsController, lightBarController, autoHideController, + keyguardUpdateMonitor, statusBarIconController, pulseExpansionHandler, + notificationWakeUpCoordinator, keyguardBypassController, keyguardStateController, + headsUpManagerPhone, dynamicPrivacyController, bypassHeadsUpNotifier, + falsingManager, + broadcastDispatcher, remoteInputQuickSettingsDisabler, notificationGutsManager, + notificationLogger, notificationInterruptStateProvider, + notificationViewHierarchyManager, keyguardViewMediator, displayMetrics, + metricsLogger, + uiBgExecutor, notificationMediaManager, lockScreenUserManager, remoteInputManager, + userSwitcherController, networkController, batteryController, colorExtractor, + screenLifecycle, wakefulnessLifecycle, statusBarStateController, vibratorHelper, + bubbleController, groupManager, visualStabilityManager, deviceProvisionedController, + navigationBarController, assistManagerLazy, configurationController, + notificationShadeWindowController, lockscreenLockIconController, dozeParameters, + scrimController, keyguardLiftController, lockscreenWallpaperLazy, + biometricUnlockControllerLazy, dozeServiceHost, powerManager, screenPinningRequest, + dozeScrimController, volumeComponent, commandQueue, recentsOptional, + statusBarComponentBuilder, pluginManager, dividerOptional, lightsOutNotifController, + statusBarNotifActivityStarterBuilder, shadeController, superStatusBarViewFactory, + statusBarKeyguardViewManager, viewMediatorCallback, initController, + darkIconDispatcher, + timeTickHandler, pluginDependencyProvider, keyguardDismissUtil, extensionController, + userInfoControllerImpl, phoneStatusBarPolicy, keyguardIndicationController, + dismissCallbackRegistry, notificationShadeDepthControllerLazy, + statusBarTouchableRegionManager); + } + + @Override + public void notifyBiometricAuthModeChanged() { + // No-op for Automotive devices. + } + + @Override + public NavigationBarView getNavigationBarView() { + // Return null for Automotive devices. + return null; + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBarModule.java index dc2eb04c2990..2c86e4db3b82 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBarModule.java @@ -23,6 +23,8 @@ import android.os.Handler; import android.os.PowerManager; import android.util.DisplayMetrics; +import androidx.annotation.Nullable; + import com.android.internal.logging.MetricsLogger; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; @@ -30,8 +32,6 @@ import com.android.systemui.InitController; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; -import com.android.systemui.car.CarDeviceProvisionedController; -import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.keyguard.DismissCallbackRegistry; @@ -75,6 +75,7 @@ import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; +import com.android.systemui.statusbar.phone.KeyguardLiftController; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LightsOutNotifController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; @@ -92,6 +93,7 @@ import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneDependenciesModule; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.NetworkController; @@ -112,17 +114,17 @@ import dagger.Module; import dagger.Provides; /** - * Dagger Module providing {@link CarStatusBar}. + * Dagger Module providing {@link UnusedStatusBar}. */ @Module(includes = {StatusBarDependenciesModule.class, StatusBarPhoneDependenciesModule.class, NotificationRowModule.class}) -public class CarStatusBarModule { +public interface UnusedStatusBarModule { /** * Provides our instance of StatusBar which is considered optional. */ @Provides @Singleton - static CarStatusBar provideStatusBar( + static UnusedStatusBar provideStatusBar( Context context, NotificationsController notificationsController, LightBarController lightBarController, @@ -141,7 +143,7 @@ public class CarStatusBarModule { RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, NotificationGutsManager notificationGutsManager, NotificationLogger notificationLogger, - NotificationInterruptStateProvider notificationInterruptionStateProvider, + NotificationInterruptStateProvider notificationInterruptStateProvider, NotificationViewHierarchyManager notificationViewHierarchyManager, KeyguardViewMediator keyguardViewMediator, DisplayMetrics displayMetrics, @@ -161,7 +163,7 @@ public class CarStatusBarModule { BubbleController bubbleController, NotificationGroupManager groupManager, VisualStabilityManager visualStabilityManager, - CarDeviceProvisionedController carDeviceProvisionedController, + DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, @@ -169,6 +171,7 @@ public class CarStatusBarModule { LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, + @Nullable KeyguardLiftController keyguardLiftController, Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, Lazy<BiometricUnlockController> biometricUnlockControllerLazy, DozeServiceHost dozeServiceHost, @@ -181,11 +184,11 @@ public class CarStatusBarModule { Provider<StatusBarComponent.Builder> statusBarComponentBuilder, PluginManager pluginManager, Optional<Divider> dividerOptional, - SuperStatusBarViewFactory superStatusBarViewFactory, LightsOutNotifController lightsOutNotifController, StatusBarNotificationActivityStarter.Builder statusBarNotificationActivityStarterBuilder, ShadeController shadeController, + SuperStatusBarViewFactory superStatusBarViewFactory, StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, InitController initController, @@ -197,11 +200,10 @@ public class CarStatusBarModule { UserInfoControllerImpl userInfoControllerImpl, PhoneStatusBarPolicy phoneStatusBarPolicy, KeyguardIndicationController keyguardIndicationController, + Lazy<NotificationShadeDepthController> notificationShadeDepthController, DismissCallbackRegistry dismissCallbackRegistry, - StatusBarTouchableRegionManager statusBarTouchableRegionManager, - Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy, - CarNavigationBarController carNavigationBarController) { - return new CarStatusBar( + StatusBarTouchableRegionManager statusBarTouchableRegionManager) { + return new UnusedStatusBar( context, notificationsController, lightBarController, @@ -220,7 +222,7 @@ public class CarStatusBarModule { remoteInputQuickSettingsDisabler, notificationGutsManager, notificationLogger, - notificationInterruptionStateProvider, + notificationInterruptStateProvider, notificationViewHierarchyManager, keyguardViewMediator, displayMetrics, @@ -240,7 +242,7 @@ public class CarStatusBarModule { bubbleController, groupManager, visualStabilityManager, - carDeviceProvisionedController, + deviceProvisionedController, navigationBarController, assistManagerLazy, configurationController, @@ -248,6 +250,7 @@ public class CarStatusBarModule { lockscreenLockIconController, dozeParameters, scrimController, + keyguardLiftController, lockscreenWallpaperLazy, biometricUnlockControllerLazy, dozeServiceHost, @@ -260,10 +263,10 @@ public class CarStatusBarModule { statusBarComponentBuilder, pluginManager, dividerOptional, - superStatusBarViewFactory, lightsOutNotifController, statusBarNotificationActivityStarterBuilder, shadeController, + superStatusBarViewFactory, statusBarKeyguardViewManager, viewMediatorCallback, initController, @@ -276,8 +279,7 @@ public class CarStatusBarModule { phoneStatusBarPolicy, keyguardIndicationController, dismissCallbackRegistry, - statusBarTouchableRegionManager, - notificationShadeDepthControllerLazy, - carNavigationBarController); + notificationShadeDepthController, + statusBarTouchableRegionManager); } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java index 10b2b973071a..aac4cfbf83c4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java @@ -18,6 +18,8 @@ package com.android.systemui.car.userswitcher; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.car.Car; +import android.car.user.CarUserManager; import android.content.Context; import android.content.res.Resources; import android.view.View; @@ -25,6 +27,7 @@ import android.view.View; import androidx.recyclerview.widget.GridLayoutManager; import com.android.systemui.R; +import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.window.OverlayViewController; import com.android.systemui.car.window.OverlayViewGlobalStateController; import com.android.systemui.dagger.qualifiers.Main; @@ -39,7 +42,9 @@ import javax.inject.Singleton; public class FullScreenUserSwitcherViewController extends OverlayViewController { private final Context mContext; private final Resources mResources; + private final CarServiceProvider mCarServiceProvider; private final int mShortAnimationDuration; + private CarUserManager mCarUserManager; private UserGridRecyclerView mUserGridView; private UserGridRecyclerView.UserSelectionListener mUserSelectionListener; @@ -47,10 +52,16 @@ public class FullScreenUserSwitcherViewController extends OverlayViewController public FullScreenUserSwitcherViewController( Context context, @Main Resources resources, + CarServiceProvider carServiceProvider, OverlayViewGlobalStateController overlayViewGlobalStateController) { super(R.id.fullscreen_user_switcher_stub, overlayViewGlobalStateController); mContext = context; mResources = resources; + mCarServiceProvider = carServiceProvider; + mCarServiceProvider.addListener(car -> { + mCarUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE); + registerCarUserManagerIfPossible(); + }); mShortAnimationDuration = mResources.getInteger(android.R.integer.config_shortAnimTime); } @@ -63,6 +74,12 @@ public class FullScreenUserSwitcherViewController extends OverlayViewController mUserGridView.setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserGridView.setUserSelectionListener(mUserSelectionListener); + registerCarUserManagerIfPossible(); + } + + @Override + protected boolean shouldFocusWindow() { + return false; } @Override @@ -91,18 +108,6 @@ public class FullScreenUserSwitcherViewController extends OverlayViewController } /** - * Invalidate underlying view. - */ - void invalidate() { - if (getLayout() == null) { - // layout hasn't been inflated. - return; - } - - getLayout().invalidate(); - } - - /** * Set {@link UserGridRecyclerView.UserSelectionListener}. */ void setUserGridSelectionListener( @@ -110,15 +115,9 @@ public class FullScreenUserSwitcherViewController extends OverlayViewController mUserSelectionListener = userGridSelectionListener; } - /** - * Returns {@code true} when layout is visible. - */ - boolean isVisible() { - if (getLayout() == null) { - // layout hasn't been inflated. - return false; + private void registerCarUserManagerIfPossible() { + if (mUserGridView != null && mCarUserManager != null) { + mUserGridView.setCarUserManager(mCarUserManager); } - - return getLayout().getVisibility() == View.VISIBLE; } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java index a526e6943004..a374df6fcaee 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java @@ -24,11 +24,15 @@ import static android.view.WindowInsets.Type.statusBars; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; -import android.car.userlib.CarUserManagerHelper; +import android.car.user.CarUserManager; +import android.car.user.UserCreationResult; +import android.car.user.UserSwitchResult; +import android.car.userlib.UserHelper; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -40,7 +44,9 @@ import android.graphics.Rect; import android.os.AsyncTask; import android.os.UserHandle; import android.os.UserManager; +import android.sysprop.CarProperties; import android.util.AttributeSet; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -54,6 +60,7 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.android.internal.infra.AndroidFuture; import com.android.internal.util.UserIcons; import com.android.systemui.R; @@ -61,6 +68,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -68,9 +76,12 @@ import java.util.stream.Collectors; * One of the uses of this is for the lock screen in auto. */ public class UserGridRecyclerView extends RecyclerView { + private static final String TAG = UserGridRecyclerView.class.getSimpleName(); + private static final int TIMEOUT_MS = CarProperties.user_hal_timeout().orElse(5_000) + 500; + private UserSelectionListener mUserSelectionListener; private UserAdapter mAdapter; - private CarUserManagerHelper mCarUserManagerHelper; + private CarUserManager mCarUserManager; private UserManager mUserManager; private Context mContext; private UserIconProvider mUserIconProvider; @@ -85,7 +96,6 @@ public class UserGridRecyclerView extends RecyclerView { public UserGridRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; - mCarUserManagerHelper = new CarUserManagerHelper(mContext); mUserManager = UserManager.get(mContext); mUserIconProvider = new UserIconProvider(); @@ -184,6 +194,11 @@ public class UserGridRecyclerView extends RecyclerView { mUserSelectionListener = userSelectionListener; } + /** Sets a {@link CarUserManager}. */ + public void setCarUserManager(CarUserManager carUserManager) { + mCarUserManager = carUserManager; + } + private void onUsersUpdate() { mAdapter.clearUsers(); mAdapter.updateUsers(createUserRecords(getUsersForUserGrid())); @@ -273,7 +288,9 @@ public class UserGridRecyclerView extends RecyclerView { notifyUserSelected(userRecord); UserInfo guest = createNewOrFindExistingGuest(mContext); if (guest != null) { - mCarUserManagerHelper.switchToUser(guest); + if (!switchUser(guest.id)) { + Log.e(TAG, "Failed to switch to guest user: " + guest.id); + } } break; case UserRecord.ADD_USER: @@ -289,7 +306,9 @@ public class UserGridRecyclerView extends RecyclerView { // If the user doesn't want to be a guest or add a user, switch to the user // selected notifyUserSelected(userRecord); - mCarUserManagerHelper.switchToUser(userRecord.mInfo); + if (!switchUser(userRecord.mInfo.id)) { + Log.e(TAG, "Failed to switch users: " + userRecord.mInfo.id); + } } }); @@ -430,8 +449,9 @@ public class UserGridRecyclerView extends RecyclerView { */ @Nullable public UserInfo createNewOrFindExistingGuest(Context context) { + AndroidFuture<UserCreationResult> future = mCarUserManager.createGuest(mGuestName); // CreateGuest will return null if a guest already exists. - UserInfo newGuest = mUserManager.createGuest(context, mGuestName); + UserInfo newGuest = getUserInfo(future); if (newGuest != null) { new UserIconProvider().assignDefaultIcon( mUserManager, context.getResources(), newGuest); @@ -444,7 +464,6 @@ public class UserGridRecyclerView extends RecyclerView { @Override public void onClick(DialogInterface dialog, int which) { if (which == BUTTON_POSITIVE) { - notifyUserSelected(mAddUserRecord); new AddNewUserTask().execute(mNewUserName); } else if (which == BUTTON_NEGATIVE) { // Enable the add button only if cancel @@ -462,11 +481,77 @@ public class UserGridRecyclerView extends RecyclerView { } } + @Nullable + private UserInfo getUserInfo(AndroidFuture<UserCreationResult> future) { + UserCreationResult userCreationResult; + try { + userCreationResult = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (Exception e) { + Log.w(TAG, "Could not create user.", e); + return null; + } + + if (userCreationResult == null) { + Log.w(TAG, "Timed out while creating user: " + TIMEOUT_MS + "ms"); + return null; + } + if (!userCreationResult.isSuccess() || userCreationResult.getUser() == null) { + Log.w(TAG, "Could not create user: " + userCreationResult); + return null; + } + + return userCreationResult.getUser(); + } + + private boolean switchUser(@UserIdInt int userId) { + AndroidFuture<UserSwitchResult> userSwitchResultFuture = + mCarUserManager.switchUser(userId); + UserSwitchResult userSwitchResult; + try { + userSwitchResult = userSwitchResultFuture.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (Exception e) { + Log.w(TAG, "Could not switch user.", e); + return false; + } + + if (userSwitchResult == null) { + Log.w(TAG, "Timed out while switching user: " + TIMEOUT_MS + "ms"); + return false; + } + if (!userSwitchResult.isSuccess()) { + Log.w(TAG, "Could not switch user: " + userSwitchResult); + return false; + } + + return true; + } + + // TODO(b/161539497): Replace AsyncTask with standard {@link java.util.concurrent} code. private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> { @Override protected UserInfo doInBackground(String... userNames) { - return mCarUserManagerHelper.createNewNonAdminUser(userNames[0]); + AndroidFuture<UserCreationResult> future = mCarUserManager.createUser(userNames[0], + /* flags= */ 0); + try { + UserInfo user = getUserInfo(future); + if (user != null) { + UserHelper.setDefaultNonAdminRestrictions(mContext, user, + /* enable= */ true); + UserHelper.assignDefaultIcon(mContext, user); + mAddUserRecord = new UserRecord(user, UserRecord.ADD_USER); + return user; + } else { + Log.e(TAG, "Failed to create user in the background"); + return user; + } + } catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + Log.e(TAG, "Error creating new user: ", e); + } + return null; } @Override @@ -476,7 +561,11 @@ public class UserGridRecyclerView extends RecyclerView { @Override protected void onPostExecute(UserInfo user) { if (user != null) { - mCarUserManagerHelper.switchToUser(user); + notifyUserSelected(mAddUserRecord); + mAddUserView.setEnabled(true); + if (!switchUser(user.id)) { + Log.e(TAG, "Failed to switch to new user: " + user.id); + } } if (mAddUserView != null) { mAddUserView.setEnabled(true); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java index 45f3d342fb6e..0d77c1341ffb 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java @@ -91,6 +91,11 @@ public class UserSwitchTransitionViewController extends OverlayViewController { R.integer.config_userSwitchTransitionViewShownTimeoutMs); } + @Override + protected int getInsetTypesToFit() { + return 0; + } + /** * Makes the user switch transition view appear and draws the content inside of it if a user * that is different from the previous user is provided and if the dialog is not already diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java index aea691443290..7db2823dc3b9 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java @@ -16,12 +16,12 @@ package com.android.systemui.car.userswitcher; -import android.app.ActivityManager; import android.car.Car; import android.car.user.CarUserManager; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.window.OverlayViewMediator; @@ -36,13 +36,16 @@ public class UserSwitchTransitionViewMediator implements OverlayViewMediator, private static final String TAG = "UserSwitchTransitionViewMediator"; private final CarServiceProvider mCarServiceProvider; + private final CarDeviceProvisionedController mCarDeviceProvisionedController; private final UserSwitchTransitionViewController mUserSwitchTransitionViewController; @Inject public UserSwitchTransitionViewMediator( CarServiceProvider carServiceProvider, + CarDeviceProvisionedController carDeviceProvisionedController, UserSwitchTransitionViewController userSwitchTransitionViewController) { mCarServiceProvider = carServiceProvider; + mCarDeviceProvisionedController = carDeviceProvisionedController; mUserSwitchTransitionViewController = userSwitchTransitionViewController; } @@ -74,7 +77,7 @@ public class UserSwitchTransitionViewMediator implements OverlayViewMediator, @VisibleForTesting void handleUserLifecycleEvent(CarUserManager.UserLifecycleEvent event) { if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING - && ActivityManager.getCurrentUser() == event.getUserId()) { + && mCarDeviceProvisionedController.getCurrentUser() == event.getUserId()) { mUserSwitchTransitionViewController.handleShow(event.getUserId()); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java index 45808a8a0b3e..3c9879c671a5 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java @@ -191,6 +191,38 @@ public abstract class OverlayPanelViewController extends OverlayViewController { } } + /** Checks if a {@link MotionEvent} is an action to open the panel. + * @param e {@link MotionEvent} to check. + * @return true only if opening action. + */ + protected boolean isOpeningAction(MotionEvent e) { + if (mAnimateDirection == POSITIVE_DIRECTION) { + return e.getActionMasked() == MotionEvent.ACTION_DOWN; + } + + if (mAnimateDirection == NEGATIVE_DIRECTION) { + return e.getActionMasked() == MotionEvent.ACTION_UP; + } + + return false; + } + + /** Checks if a {@link MotionEvent} is an action to close the panel. + * @param e {@link MotionEvent} to check. + * @return true only if closing action. + */ + protected boolean isClosingAction(MotionEvent e) { + if (mAnimateDirection == POSITIVE_DIRECTION) { + return e.getActionMasked() == MotionEvent.ACTION_UP; + } + + if (mAnimateDirection == NEGATIVE_DIRECTION) { + return e.getActionMasked() == MotionEvent.ACTION_DOWN; + } + + return false; + } + /* ***************************************************************************************** * * Panel Animation * ***************************************************************************************** */ @@ -206,7 +238,6 @@ public abstract class OverlayPanelViewController extends OverlayViewController { } onAnimateCollapsePanel(); - getOverlayViewGlobalStateController().setWindowFocusable(false); animatePanel(mClosingVelocity, /* isClosing= */ true); } @@ -243,8 +274,7 @@ public abstract class OverlayPanelViewController extends OverlayViewController { * Depending on certain conditions, determines whether to fully expand or collapse the panel. */ protected void maybeCompleteAnimation(MotionEvent event) { - if (event.getActionMasked() == MotionEvent.ACTION_UP - && isPanelVisible()) { + if (isClosingAction(event) && isPanelVisible()) { if (mSettleClosePercentage < mPercentageFromEndingEdge) { animatePanel(DEFAULT_FLING_VELOCITY, false); } else { @@ -266,14 +296,17 @@ public abstract class OverlayPanelViewController extends OverlayViewController { float from = getCurrentStartPosition(rect); if (from != to) { animate(from, to, velocity, isClosing); - return; } + + // If we swipe down the notification panel all the way to the bottom of the screen + // (i.e. from == to), then we have finished animating the panel. + return; } // We will only be here if the shade is being opened programmatically or via button when // height of the layout was not calculated. - ViewTreeObserver notificationTreeObserver = getLayout().getViewTreeObserver(); - notificationTreeObserver.addOnGlobalLayoutListener( + ViewTreeObserver panelTreeObserver = getLayout().getViewTreeObserver(); + panelTreeObserver.addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { @@ -381,7 +414,6 @@ public abstract class OverlayPanelViewController extends OverlayViewController { getOverlayViewGlobalStateController().hideView(/* panelViewController= */ this); } getLayout().setVisibility(visible ? View.VISIBLE : View.INVISIBLE); - getOverlayViewGlobalStateController().setWindowFocusable(visible); } /* ***************************************************************************************** * @@ -476,6 +508,11 @@ public abstract class OverlayPanelViewController extends OverlayViewController { return mIsTracking; } + /** Sets whether the panel is currently tracking or not. */ + protected final void setIsTracking(boolean isTracking) { + mIsTracking = isTracking; + } + /** Returns {@code true} if the panel is currently animating. */ protected final boolean isAnimating() { return mIsAnimating; @@ -514,7 +551,7 @@ public abstract class OverlayPanelViewController extends OverlayViewController { } setPanelVisible(true); - // clips the view for the notification shade when the user scrolls to open. + // clips the view for the panel when the user scrolls to open. setViewClipBounds((int) event2.getRawY()); // Initially the scroll starts with height being zero. This checks protects from divide @@ -569,11 +606,11 @@ public abstract class OverlayPanelViewController extends OverlayViewController { boolean isInClosingDirection = mAnimateDirection * distanceY > 0; // This check is to figure out if onScroll was called while swiping the card at - // bottom of the list. At that time we should not allow notification shade to + // bottom of the panel. At that time we should not allow panel to // close. We are also checking for the upwards swipe gesture here because it is - // possible if a user is closing the notification shade and while swiping starts + // possible if a user is closing the panel and while swiping starts // to open again but does not fling. At that time we should allow the - // notification shade to close fully or else it would stuck in between. + // panel to close fully or else it would stuck in between. if (Math.abs(getLayout().getHeight() - y) > SWIPE_DOWN_MIN_DISTANCE && isInClosingDirection) { setViewClipBounds((int) y); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java index 3969f92c690a..8adc1adcc41c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java @@ -16,9 +16,12 @@ package com.android.systemui.car.window; +import static android.view.WindowInsets.Type.statusBars; + import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; +import android.view.WindowInsets; /** * Owns a {@link View} that is present in SystemUIOverlayWindow. @@ -133,9 +136,18 @@ public class OverlayViewController { } /** - * Returns {@code true} if navigation bar should be displayed over this view. + * Returns {@code true} if navigation bar insets should be displayed over this view. Has no + * effect if {@link #shouldFocusWindow} returns {@code false}. + */ + protected boolean shouldShowNavigationBarInsets() { + return false; + } + + /** + * Returns {@code true} if status bar insets should be displayed over this view. Has no + * effect if {@link #shouldFocusWindow} returns {@code false}. */ - protected boolean shouldShowNavigationBar() { + protected boolean shouldShowStatusBarInsets() { return false; } @@ -145,4 +157,22 @@ public class OverlayViewController { protected boolean shouldShowWhenOccluded() { return false; } + + /** + * Returns {@code true} if the window should be focued when this view is visible. Note that + * returning {@code false} here means that {@link #shouldShowStatusBarInsets} and + * {@link #shouldShowNavigationBarInsets} will have no effect. + */ + protected boolean shouldFocusWindow() { + return true; + } + + /** + * Returns the insets types to fit to the sysui overlay window when this + * {@link OverlayViewController} is in the foreground. + */ + @WindowInsets.Type.InsetsType + protected int getInsetTypesToFit() { + return statusBars(); + } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java index 8e9410964313..55f0975aeccf 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java @@ -16,13 +16,16 @@ package com.android.systemui.car.window; +import static android.view.WindowInsets.Type.navigationBars; +import static android.view.WindowInsets.Type.statusBars; + import android.annotation.Nullable; import android.util.Log; +import android.view.WindowInsets.Type.InsetsType; +import android.view.WindowInsetsController; import androidx.annotation.VisibleForTesting; -import com.android.systemui.car.navigationbar.CarNavigationBarController; - import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -48,10 +51,7 @@ public class OverlayViewGlobalStateController { private static final String TAG = OverlayViewGlobalStateController.class.getSimpleName(); private static final int UNKNOWN_Z_ORDER = -1; private final SystemUIOverlayWindowController mSystemUIOverlayWindowController; - private final CarNavigationBarController mCarNavigationBarController; - - private boolean mIsOccluded; - + private final WindowInsetsController mWindowInsetsController; @VisibleForTesting Map<OverlayViewController, Integer> mZOrderMap; @VisibleForTesting @@ -60,14 +60,15 @@ public class OverlayViewGlobalStateController { Set<OverlayViewController> mViewsHiddenForOcclusion; @VisibleForTesting OverlayViewController mHighestZOrder; + private boolean mIsOccluded; @Inject public OverlayViewGlobalStateController( - CarNavigationBarController carNavigationBarController, SystemUIOverlayWindowController systemUIOverlayWindowController) { mSystemUIOverlayWindowController = systemUIOverlayWindowController; mSystemUIOverlayWindowController.attach(); - mCarNavigationBarController = carNavigationBarController; + mWindowInsetsController = + mSystemUIOverlayWindowController.getBaseLayout().getWindowInsetsController(); mZOrderMap = new HashMap<>(); mZOrderVisibleSortedMap = new TreeMap<>(); mViewsHiddenForOcclusion = new HashSet<>(); @@ -115,7 +116,10 @@ public class OverlayViewGlobalStateController { } updateInternalsWhenShowingView(viewController); + refreshInsetTypesToFit(); + refreshWindowFocus(); refreshNavigationBarVisibility(); + refreshStatusBarVisibility(); Log.d(TAG, "Content shown: " + viewController.getClass().getName()); debugLog(); @@ -185,7 +189,10 @@ public class OverlayViewGlobalStateController { mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController)); refreshHighestZOrderWhenHidingView(viewController); + refreshInsetTypesToFit(); + refreshWindowFocus(); refreshNavigationBarVisibility(); + refreshStatusBarVisibility(); if (mZOrderVisibleSortedMap.isEmpty()) { setWindowVisible(false); @@ -208,10 +215,42 @@ public class OverlayViewGlobalStateController { } private void refreshNavigationBarVisibility() { - if (mZOrderVisibleSortedMap.isEmpty() || mHighestZOrder.shouldShowNavigationBar()) { - mCarNavigationBarController.showBars(); + if (mZOrderVisibleSortedMap.isEmpty()) { + mWindowInsetsController.show(navigationBars()); + return; + } + + // Do not hide navigation bar insets if the window is not focusable. + if (mHighestZOrder.shouldFocusWindow() && !mHighestZOrder.shouldShowNavigationBarInsets()) { + mWindowInsetsController.hide(navigationBars()); } else { - mCarNavigationBarController.hideBars(); + mWindowInsetsController.show(navigationBars()); + } + } + + private void refreshStatusBarVisibility() { + if (mZOrderVisibleSortedMap.isEmpty()) { + mWindowInsetsController.show(statusBars()); + return; + } + + // Do not hide status bar insets if the window is not focusable. + if (mHighestZOrder.shouldFocusWindow() && !mHighestZOrder.shouldShowStatusBarInsets()) { + mWindowInsetsController.hide(statusBars()); + } else { + mWindowInsetsController.show(statusBars()); + } + } + + private void refreshWindowFocus() { + setWindowFocusable(mHighestZOrder == null ? false : mHighestZOrder.shouldFocusWindow()); + } + + private void refreshInsetTypesToFit() { + if (mZOrderVisibleSortedMap.isEmpty()) { + setFitInsetsTypes(statusBars()); + } else { + setFitInsetsTypes(mHighestZOrder.getInsetTypesToFit()); } } @@ -224,6 +263,10 @@ public class OverlayViewGlobalStateController { mSystemUIOverlayWindowController.setWindowVisible(visible); } + private void setFitInsetsTypes(@InsetsType int types) { + mSystemUIOverlayWindowController.setFitInsetsTypes(types); + } + /** * Sets the {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flag of the * sysui overlay window. diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java index bcd96f63a2b4..c955fab592f3 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java @@ -16,6 +16,7 @@ package com.android.systemui.car.window; +import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import android.content.Context; @@ -25,6 +26,7 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.WindowManager; import com.android.systemui.R; @@ -99,17 +101,23 @@ public class SystemUIOverlayWindowController implements PixelFormat.TRANSLUCENT); mLp.token = new Binder(); mLp.gravity = Gravity.TOP; - mLp.setFitInsetsTypes(/* types= */ 0); mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; mLp.setTitle("SystemUIOverlayWindow"); mLp.packageName = mContext.getPackageName(); mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; mWindowManager.addView(mBaseLayout, mLp); mLpChanged.copyFrom(mLp); setWindowVisible(false); } + /** Sets the types of insets to fit. Note: This should be rarely used. */ + public void setFitInsetsTypes(@WindowInsets.Type.InsetsType int types) { + mLpChanged.setFitInsetsTypes(types); + updateWindow(); + } + /** Sets the window to the visible state. */ public void setWindowVisible(boolean visible) { mVisible = visible; @@ -154,6 +162,7 @@ public class SystemUIOverlayWindowController implements private void updateWindow() { if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { if (isAttached()) { + mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; mWindowManager.updateViewLayout(mBaseLayout, mLp); } } diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/BarControlPolicy.java b/packages/CarSystemUI/src/com/android/systemui/wm/BarControlPolicy.java new file mode 100644 index 000000000000..5f9665ff7632 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/wm/BarControlPolicy.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2020 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.wm; + +import android.car.settings.CarSettings; +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.ArraySet; +import android.util.Slog; +import android.view.WindowInsets; + +import androidx.annotation.VisibleForTesting; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Util class to load PolicyControl and allow for querying if a package matches immersive filters. + * Similar to {@link com.android.server.wm.PolicyControl}, but separate due to CarSystemUI needing + * to set its own policies for system bar visibilities. + * + * This forces immersive mode behavior for one or both system bars (based on a package + * list). + * + * Control by setting {@link Settings.Global#POLICY_CONTROL_AUTO} to one or more name-value pairs. + * e.g. + * to force immersive mode everywhere: + * "immersive.full=*" + * to force hide status bars for com.package1 but not com.package2: + * "immersive.status=com.package1,-com.package2" + * + * Separate multiple name-value pairs with ':' + * e.g. "immersive.status=com.package:immersive.navigation=*" + */ +public class BarControlPolicy { + + private static final String TAG = "BarControlPolicy"; + private static final boolean DEBUG = false; + + private static final String NAME_IMMERSIVE_FULL = "immersive.full"; + private static final String NAME_IMMERSIVE_STATUS = "immersive.status"; + private static final String NAME_IMMERSIVE_NAVIGATION = "immersive.navigation"; + + @VisibleForTesting + static String sSettingValue; + @VisibleForTesting + static Filter sImmersiveStatusFilter; + private static Filter sImmersiveNavigationFilter; + + /** Loads values from the POLICY_CONTROL setting to set filters. */ + static boolean reloadFromSetting(Context context) { + if (DEBUG) Slog.d(TAG, "reloadFromSetting()"); + String value = null; + try { + value = Settings.Global.getStringForUser(context.getContentResolver(), + CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE, + UserHandle.USER_CURRENT); + if (sSettingValue == value || sSettingValue != null && sSettingValue.equals(value)) { + return false; + } + setFilters(value); + sSettingValue = value; + } catch (Throwable t) { + Slog.w(TAG, "Error loading policy control, value=" + value, t); + return false; + } + return true; + } + + /** Used in testing to reset BarControlPolicy. */ + @VisibleForTesting + static void reset() { + sSettingValue = null; + sImmersiveStatusFilter = null; + sImmersiveNavigationFilter = null; + } + + /** + * Registers a content observer to listen to updates to the SYSTEM_BAR_VISIBILITY_OVERRIDE flag. + */ + static void registerContentObserver(Context context, Handler handler, FilterListener listener) { + context.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE), false, + new ContentObserver(handler) { + @Override + public void onChange(boolean selfChange) { + if (reloadFromSetting(context)) { + listener.onFilterUpdated(); + } + } + }, UserHandle.USER_ALL); + } + + /** + * Returns bar visibilities based on POLICY_CONTROL_AUTO filters and window policies. + * @return int[], where the first value is the inset types that should be shown, and the second + * is the inset types that should be hidden. + */ + @WindowInsets.Type.InsetsType + static int[] getBarVisibilities(String packageName) { + int hideTypes = 0; + int showTypes = 0; + if (matchesStatusFilter(packageName)) { + hideTypes |= WindowInsets.Type.statusBars(); + } else { + showTypes |= WindowInsets.Type.statusBars(); + } + if (matchesNavigationFilter(packageName)) { + hideTypes |= WindowInsets.Type.navigationBars(); + } else { + showTypes |= WindowInsets.Type.navigationBars(); + } + + return new int[] {showTypes, hideTypes}; + } + + private static boolean matchesStatusFilter(String packageName) { + return sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(packageName); + } + + private static boolean matchesNavigationFilter(String packageName) { + return sImmersiveNavigationFilter != null + && sImmersiveNavigationFilter.matches(packageName); + } + + private static void setFilters(String value) { + if (DEBUG) Slog.d(TAG, "setFilters: " + value); + sImmersiveStatusFilter = null; + sImmersiveNavigationFilter = null; + if (value != null) { + String[] nvps = value.split(":"); + for (String nvp : nvps) { + int i = nvp.indexOf('='); + if (i == -1) continue; + String n = nvp.substring(0, i); + String v = nvp.substring(i + 1); + if (n.equals(NAME_IMMERSIVE_FULL)) { + Filter f = Filter.parse(v); + sImmersiveStatusFilter = sImmersiveNavigationFilter = f; + } else if (n.equals(NAME_IMMERSIVE_STATUS)) { + Filter f = Filter.parse(v); + sImmersiveStatusFilter = f; + } else if (n.equals(NAME_IMMERSIVE_NAVIGATION)) { + Filter f = Filter.parse(v); + sImmersiveNavigationFilter = f; + } + } + } + if (DEBUG) { + Slog.d(TAG, "immersiveStatusFilter: " + sImmersiveStatusFilter); + Slog.d(TAG, "immersiveNavigationFilter: " + sImmersiveNavigationFilter); + } + } + + private static class Filter { + private static final String ALL = "*"; + + private final ArraySet<String> mWhitelist; + private final ArraySet<String> mBlacklist; + + private Filter(ArraySet<String> whitelist, ArraySet<String> blacklist) { + mWhitelist = whitelist; + mBlacklist = blacklist; + } + + boolean matches(String packageName) { + if (packageName == null) return false; + if (onBlacklist(packageName)) return false; + return onWhitelist(packageName); + } + + private boolean onBlacklist(String packageName) { + return mBlacklist.contains(packageName) || mBlacklist.contains(ALL); + } + + private boolean onWhitelist(String packageName) { + return mWhitelist.contains(ALL) || mWhitelist.contains(packageName); + } + + void dump(PrintWriter pw) { + pw.print("Filter["); + dump("whitelist", mWhitelist, pw); pw.print(','); + dump("blacklist", mBlacklist, pw); pw.print(']'); + } + + private void dump(String name, ArraySet<String> set, PrintWriter pw) { + pw.print(name); pw.print("=("); + int n = set.size(); + for (int i = 0; i < n; i++) { + if (i > 0) pw.print(','); + pw.print(set.valueAt(i)); + } + pw.print(')'); + } + + @Override + public String toString() { + StringWriter sw = new StringWriter(); + dump(new PrintWriter(sw, true)); + return sw.toString(); + } + + // value = comma-delimited list of tokens, where token = (package name|*) + // e.g. "com.package1", or "com.android.systemui, com.android.keyguard" or "*" + static Filter parse(String value) { + if (value == null) return null; + ArraySet<String> whitelist = new ArraySet<String>(); + ArraySet<String> blacklist = new ArraySet<String>(); + for (String token : value.split(",")) { + token = token.trim(); + if (token.startsWith("-") && token.length() > 1) { + token = token.substring(1); + blacklist.add(token); + } else { + whitelist.add(token); + } + } + return new Filter(whitelist, blacklist); + } + } + + /** + * Interface to listen for updates to the filter triggered by the content observer listening to + * the SYSTEM_BAR_VISIBILITY_OVERRIDE flag. + */ + interface FilterListener { + + /** Callback triggered when the content observer updates the filter. */ + void onFilterUpdated(); + } + + private BarControlPolicy() {} +} diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java new file mode 100644 index 000000000000..c9ec34fd5f08 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2020 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.wm; + +import android.os.Handler; +import android.os.RemoteException; +import android.util.ArraySet; +import android.util.Slog; +import android.util.SparseArray; +import android.view.IDisplayWindowInsetsController; +import android.view.InsetsController; +import android.view.InsetsSourceControl; +import android.view.InsetsState; +import android.view.WindowInsets; + +import androidx.annotation.VisibleForTesting; + +import com.android.systemui.TransactionPool; +import com.android.systemui.dagger.qualifiers.Main; + +import java.util.Objects; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Controller that maps between displays and {@link IDisplayWindowInsetsController} in order to + * give system bar control to SystemUI. + * {@link R.bool#config_remoteInsetsControllerControlsSystemBars} determines whether this controller + * takes control or not. + */ +@Singleton +public class DisplaySystemBarsController extends DisplayImeController { + + private static final String TAG = "DisplaySystemBarsController"; + + private SparseArray<PerDisplay> mPerDisplaySparseArray; + + @Inject + public DisplaySystemBarsController( + SystemWindows syswin, + DisplayController displayController, + @Main Handler mainHandler, + TransactionPool transactionPool) { + super(syswin, displayController, mainHandler, transactionPool); + } + + @Override + public void onDisplayAdded(int displayId) { + PerDisplay pd = new PerDisplay(displayId); + try { + mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, pd); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to set insets controller on display " + displayId); + } + // Lazy loading policy control filters instead of during boot. + if (mPerDisplaySparseArray == null) { + mPerDisplaySparseArray = new SparseArray<>(); + BarControlPolicy.reloadFromSetting(mSystemWindows.mContext); + BarControlPolicy.registerContentObserver(mSystemWindows.mContext, mHandler, () -> { + int size = mPerDisplaySparseArray.size(); + for (int i = 0; i < size; i++) { + mPerDisplaySparseArray.valueAt(i).modifyDisplayWindowInsets(); + } + }); + } + mPerDisplaySparseArray.put(displayId, pd); + } + + @Override + public void onDisplayRemoved(int displayId) { + try { + mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, null); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to remove insets controller on display " + displayId); + } + mPerDisplaySparseArray.remove(displayId); + } + + @VisibleForTesting + class PerDisplay extends DisplayImeController.PerDisplay { + + int mDisplayId; + InsetsController mInsetsController; + InsetsState mInsetsState = new InsetsState(); + String mPackageName; + + PerDisplay(int displayId) { + super(displayId, + mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation()); + mDisplayId = displayId; + mInsetsController = new InsetsController( + new DisplaySystemBarsInsetsControllerHost(mHandler, this)); + } + + @Override + public void insetsChanged(InsetsState insetsState) { + super.insetsChanged(insetsState); + if (mInsetsState.equals(insetsState)) { + return; + } + mInsetsState.set(insetsState, true /* copySources */); + mInsetsController.onStateChanged(insetsState); + if (mPackageName != null) { + modifyDisplayWindowInsets(); + } + } + + @Override + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) { + super.insetsControlChanged(insetsState, activeControls); + mInsetsController.onControlsChanged(activeControls); + } + + @Override + public void hideInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) { + if ((types & WindowInsets.Type.ime()) == 0) { + mInsetsController.hide(types); + } else { + super.hideInsets(types, fromIme); + } + + } + + @Override + public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) { + if ((types & WindowInsets.Type.ime()) == 0) { + mInsetsController.show(types); + } else { + super.showInsets(types, fromIme); + } + + } + + @Override + public void topFocusedWindowChanged(String packageName) { + if (Objects.equals(mPackageName, packageName)) { + return; + } + mPackageName = packageName; + modifyDisplayWindowInsets(); + } + + private void modifyDisplayWindowInsets() { + if (mPackageName == null) { + return; + } + int[] barVisibilities = BarControlPolicy.getBarVisibilities(mPackageName); + updateInsetsState(barVisibilities[0], /* visible= */ true); + updateInsetsState(barVisibilities[1], /* visible= */ false); + showInsets(barVisibilities[0], /* fromIme= */ false); + hideInsets(barVisibilities[1], /* fromIme= */ false); + try { + mSystemWindows.mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to update window manager service."); + } + } + + private void updateInsetsState(@WindowInsets.Type.InsetsType int types, boolean visible) { + ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); + for (int i = internalTypes.size() - 1; i >= 0; i--) { + mInsetsState.getSource(internalTypes.valueAt(i)).setVisible(visible); + } + } + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java new file mode 100644 index 000000000000..2f8da44ba851 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2020 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.wm; + +import android.annotation.NonNull; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; +import android.view.IDisplayWindowInsetsController; +import android.view.InsetsController; +import android.view.InsetsState; +import android.view.SurfaceControl; +import android.view.SyncRtSurfaceTransactionApplier; +import android.view.WindowInsets; +import android.view.WindowInsetsAnimation; +import android.view.WindowInsetsController; +import android.view.inputmethod.InputMethodManager; + +import java.util.List; + +/** + * Implements {@link InsetsController.Host} for usage by + * {@link DisplaySystemBarsController.PerDisplay} instances in {@link DisplaySystemBarsController}. + * @hide + */ +public class DisplaySystemBarsInsetsControllerHost implements InsetsController.Host { + + private static final String TAG = DisplaySystemBarsInsetsControllerHost.class.getSimpleName(); + + private final Handler mHandler; + private final IDisplayWindowInsetsController mController; + private final float[] mTmpFloat9 = new float[9]; + + public DisplaySystemBarsInsetsControllerHost( + Handler handler, IDisplayWindowInsetsController controller) { + mHandler = handler; + mController = controller; + } + + @Override + public Handler getHandler() { + return mHandler; + } + + @Override + public void notifyInsetsChanged() { + // no-op + } + + @Override + public void dispatchWindowInsetsAnimationPrepare(@NonNull WindowInsetsAnimation animation) { + // no-op + } + + @Override + public WindowInsetsAnimation.Bounds dispatchWindowInsetsAnimationStart( + @NonNull WindowInsetsAnimation animation, + @NonNull WindowInsetsAnimation.Bounds bounds) { + return null; + } + + @Override + public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets, + @NonNull List<WindowInsetsAnimation> runningAnimations) { + return null; + } + + @Override + public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) { + // no-op + } + + @Override + public void applySurfaceParams(final SyncRtSurfaceTransactionApplier.SurfaceParams... params) { + for (int i = params.length - 1; i >= 0; i--) { + SyncRtSurfaceTransactionApplier.applyParams( + new SurfaceControl.Transaction(), params[i], mTmpFloat9); + } + + } + + @Override + public void updateCompatSysUiVisibility( + @InsetsState.InternalInsetsType int type, boolean visible, boolean hasControl) { + // no-op + } + + @Override + public void onInsetsModified(InsetsState insetsState) { + try { + mController.insetsChanged(insetsState); + } catch (RemoteException e) { + Log.e(TAG, "Failed to send insets to controller"); + } + } + + @Override + public boolean hasAnimationCallbacks() { + return false; + } + + @Override + public void setSystemBarsAppearance( + @WindowInsetsController.Appearance int appearance, + @WindowInsetsController.Appearance int mask) { + // no-op + } + + @Override + public @WindowInsetsController.Appearance int getSystemBarsAppearance() { + return 0; + } + + @Override + public void setSystemBarsBehavior(@WindowInsetsController.Behavior int behavior) { + // no-op + } + + @Override + public @WindowInsetsController.Behavior int getSystemBarsBehavior() { + return 0; + } + + @Override + public void releaseSurfaceControlFromRt(SurfaceControl surfaceControl) { + surfaceControl.release(); + } + + @Override + public void addOnPreDrawRunnable(Runnable r) { + mHandler.post(r); + } + + @Override + public void postInsetsAnimationCallback(Runnable r) { + mHandler.post(r); + } + + @Override + public InputMethodManager getInputMethodManager() { + return null; + } + + @Override + public String getRootViewTitle() { + return null; + } + + @Override + public int dipToPx(int dips) { + return 0; + } + + @Override + public IBinder getWindowToken() { + return null; + } +} |