Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10ca70b0 authored by Charles Chen's avatar Charles Chen
Browse files

Move all logic of navigation bar to NavigationBarController(2/N)

Since we don't have status bar on external displays, we need to saparate
the logic to make some animations or transitions just work on external
navigation bars. When we set System UI visibility on an external display,
we could make the flag only effect navigation bar. Also, it can simplify
StatusBar code by moving navigation bar related fields into
NavigationBarController.

Test: atest SystemUITests
Bug: 117478341

Change-Id: I1cdf61f6eeb2c377e04a073401efa0cdb45b65cd
parent 2de1d857
Loading
Loading
Loading
Loading
+3 −7
Original line number Diff line number Diff line
@@ -280,7 +280,9 @@ public class CarStatusBar extends StatusBar implements
        buildNavBarContent();
        attachNavBarWindows();

        mNavigationBarController.createNavigationBars();
        // There has been a car customized nav bar on the default display, so just create nav bars
        // on external displays.
        mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */);
    }

    private void buildNavBarContent() {
@@ -447,12 +449,6 @@ public class CarStatusBar extends StatusBar implements
        }
    }


    @Override
    public View getNavigationBarWindow() {
        return mNavigationBarWindow;
    }

    @Override
    protected View.OnTouchListener getStatusBarWindowTouchListener() {
        // Usually, a touch on the background window will dismiss the notification shade. However,
+3 −4
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.DisplayNavigationBarController;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -244,7 +244,7 @@ public class Dependency extends SystemUI {
    @Inject Lazy<NotificationRemoteInputManager.Callback> mNotificationRemoteInputManagerCallback;
    @Inject Lazy<InitController> mInitController;
    @Inject Lazy<AppOpsController> mAppOpsController;
    @Inject Lazy<DisplayNavigationBarController> mDisplayNavigationBarController;
    @Inject Lazy<NavigationBarController> mNavigationBarController;
    @Inject Lazy<StatusBarStateController> mStatusBarStateController;
    @Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
    @Inject Lazy<NotificationGroupAlertTransferHelper> mNotificationGroupAlertTransferHelper;
@@ -410,8 +410,7 @@ public class Dependency extends SystemUI {

        mProviders.put(AppOpsController.class, mAppOpsController::get);

        mProviders.put(DisplayNavigationBarController.class,
                mDisplayNavigationBarController::get);
        mProviders.put(NavigationBarController.class, mNavigationBarController::get);

        mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
        mProviders.put(NotificationLockscreenUserManager.class,
+8 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.plugins.PluginInitializerImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -168,6 +169,13 @@ public class DependencyProvider {
        return new PluginManagerImpl(context, new PluginInitializerImpl());
    }

    @Singleton
    @Provides
    public NavigationBarController provideNavigationBarController(Context context,
            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
        return new NavigationBarController(context, mainHandler);
    }

    @Singleton
    @Provides
    public ConfigurationController provideConfigurationController(Context context) {
+222 −0
Original line number Diff line number Diff line
@@ -32,100 +32,86 @@ import android.view.IWindowManager;
import android.view.View;
import android.view.WindowManagerGlobal;

import com.android.systemui.Dependency;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.policy.BatteryController;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

/**
 * A controller to handle external navigation bars
 */

/** A controller to handle navigation bars. */
@Singleton
public class DisplayNavigationBarController implements DisplayListener {
public class NavigationBarController implements DisplayListener {

    private static final String TAG = DisplayNavigationBarController.class.getName();
    private static final String TAG = NavigationBarController.class.getName();

    private final Context mContext;
    private final Handler mHandler;
    private final DisplayManager mDisplayManager;

    /** A displayId - nav bar mapping */
    private SparseArray<NavigationBarFragment> mExternalNavigationBarMap = new SparseArray<>();
    /** A displayId - nav bar maps. */
    private SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();

    @Inject
    public DisplayNavigationBarController(Context context,
            @Named(MAIN_HANDLER_NAME) Handler handler) {
    public NavigationBarController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
        mContext = context;
        mHandler = handler;
        mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);

        registerListener();
        mDisplayManager.registerDisplayListener(this, mHandler);
    }

    @Override
    public void onDisplayAdded(int displayId) {
        final Display display = mDisplayManager.getDisplay(displayId);
        addExternalNavigationBar(display);
        Display display = mDisplayManager.getDisplay(displayId);
        createNavigationBar(display);
    }

    @Override
    public void onDisplayRemoved(int displayId) {
        final NavigationBarFragment navBar = mExternalNavigationBarMap.get(displayId);
        if (navBar != null) {
            final View navigationView = navBar.getView().getRootView();
            WindowManagerGlobal.getInstance().removeView(navigationView, true);
            mExternalNavigationBarMap.remove(displayId);
        }
        removeNavigationBar(displayId);
    }

    @Override
    public void onDisplayChanged(int displayId) {
    }

    /** Create external navigation bars when car/status bar initializes */
    public void createNavigationBars() {
        // Add external navigation bars if more than one displays exist.
        final Display[] displays = mDisplayManager.getDisplays();
    // TODO(b/117478341): I use {@code includeDefaultDisplay} to make this method compatible to
    // CarStatusBar because they have their own nav bar. Think about a better way for it.
    /**
     * Creates navigation bars when car/status bar initializes.
     *
     * @param includeDefaultDisplay {@code true} to create navigation bar on default display.
     */
    public void createNavigationBars(final boolean includeDefaultDisplay) {
        Display[] displays = mDisplayManager.getDisplays();
        for (Display display : displays) {
            addExternalNavigationBar(display);
        }
    }

    /** remove external navigation bars and unset everything related to external navigation bars */
    public void destroy() {
        unregisterListener();
        if (mExternalNavigationBarMap.size() > 0) {
            for (int i = 0; i < mExternalNavigationBarMap.size(); i++) {
                final View navigationWindow = mExternalNavigationBarMap.valueAt(i)
                        .getView().getRootView();
                WindowManagerGlobal.getInstance()
                        .removeView(navigationWindow, true /* immediate */);
            }
            mExternalNavigationBarMap.clear();
            if (includeDefaultDisplay || display.getDisplayId() != DEFAULT_DISPLAY) {
                createNavigationBar(display);
            }
        }

    private void registerListener() {
        mDisplayManager.registerDisplayListener(this, mHandler);
    }

    private void unregisterListener() {
        mDisplayManager.unregisterDisplayListener(this);
    }

    /**
     * Add a phone navigation bar on an external display if the display supports system decorations.
     * Adds a navigation bar on default display or an external display if the display supports
     * system decorations.
     *
     * @param display the display to add navigation bar on
     * @param display the display to add navigation bar on.
     */
    private void addExternalNavigationBar(Display display) {
        if (display == null || display.getDisplayId() == DEFAULT_DISPLAY
                || !display.supportsSystemDecorations()) {
    private void createNavigationBar(Display display) {
        if (display == null
                || (display.getDisplayId() != DEFAULT_DISPLAY
                        && !display.supportsSystemDecorations())) {
            return;
        }

        final int displayId = display.getDisplayId();
        final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;
        final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();

        try {
@@ -137,12 +123,100 @@ public class DisplayNavigationBarController implements DisplayListener {
            Log.w(TAG, "Cannot get WindowManager.");
            return;
        }
        final Context externalDisplayContext = mContext.createDisplayContext(display);
        NavigationBarFragment.create(externalDisplayContext, (tag, fragment) -> {
            final NavigationBarFragment navBar = (NavigationBarFragment) fragment;
            // TODO(b/115978725): handle external nav bars sysuiVisibility
            navBar.setCurrentSysuiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            mExternalNavigationBarMap.append(displayId, navBar);
        final Context context = isOnDefaultDisplay
                ? mContext
                : mContext.createDisplayContext(display);
        NavigationBarFragment.create(context, (tag, fragment) -> {
            NavigationBarFragment navBar = (NavigationBarFragment) fragment;

            // Unfortunately, we still need it because status bar needs LightBarController
            // before notifications creation. We cannot directly use getLightBarController()
            // from NavigationBarFragment directly.
            LightBarController controller = isOnDefaultDisplay
                    ? Dependency.get(LightBarController.class)
                    : new LightBarController(context,
                            Dependency.get(DarkIconDispatcher.class),
                            Dependency.get(BatteryController.class));
            navBar.setLightBarController(controller);
            navBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            mNavigationBars.append(displayId, navBar);
        });
    }

    /** Removes navigation bars. */
    public void destroy() {
        mDisplayManager.unregisterDisplayListener(this);
        if (mNavigationBars.size() > 0) {
            for (int i = 0; i < mNavigationBars.size(); i++) {
                int displayId = mNavigationBars.keyAt(i);
                removeNavigationBar(displayId);
            }
            mNavigationBars.clear();
        }
    }

    private void removeNavigationBar(int displayId) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            View navigationWindow = navBar.getView().getRootView();
            WindowManagerGlobal.getInstance()
                    .removeView(navigationWindow, true /* immediate */);
            mNavigationBars.remove(displayId);
        }
    }

    /** @see NavigationBarFragment#checkNavBarModes() */
    public void checkNavBarModes(int displayId) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            navBar.checkNavBarModes();
        }
    }

    /** @see NavigationBarFragment#finishBarAnimations() */
    public void finishBarAnimations(int displayId) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            navBar.finishBarAnimations();
        }
    }

    /** @see NavigationBarFragment#touchAutoDim() */
    public void touchAutoDim(int displayId) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            navBar.touchAutoDim();
        }
    }

    /** @see NavigationBarFragment#transitionTo(int, boolean) */
    public void transitionTo(int displayId, @TransitionMode int barMode, boolean animate) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            navBar.transitionTo(barMode, animate);
        }
    }

    /** @see NavigationBarFragment#isSemiTransparent() */
    public boolean isSemiTransparent(int displayId) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            return navBar.isSemiTransparent();
        }
        return false;
    }

    /** @see NavigationBarFragment#disableAnimationsDuringHide(long) */
    public void disableAnimationsDuringHide(int displayId, long delay) {
        NavigationBarFragment navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            navBar.disableAnimationsDuringHide(delay);
        }
    }

    /** @return {@link NavigationBarView} on the default display. */
    public NavigationBarView getDefaultNavigationBarView() {
        NavigationBarFragment navBar = mNavigationBars.get(DEFAULT_DISPLAY);
        return (navBar == null) ? null : (NavigationBarView) navBar.getView();
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar.phone;

import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -36,6 +37,9 @@ import com.android.settingslib.Utils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class BarTransitions {
    private static final boolean DEBUG = false;
    private static final boolean DEBUG_COLORS = false;
@@ -48,6 +52,18 @@ public class BarTransitions {
    public static final int MODE_WARNING = 5;
    public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;

    @IntDef(flag = true, prefix = { "MODE_" }, value = {
            MODE_OPAQUE,
            MODE_SEMI_TRANSPARENT,
            MODE_TRANSLUCENT,
            MODE_LIGHTS_OUT,
            MODE_TRANSPARENT,
            MODE_WARNING,
            MODE_LIGHTS_OUT_TRANSPARENT
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransitionMode {}

    public static final int LIGHTS_IN_DURATION = 250;
    public static final int LIGHTS_OUT_DURATION = 1500;
    public static final int BACKGROUND_DURATION = 200;
Loading