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

Commit 19607774 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use display context to inflate navbar on external display

- Disable rotation suggestion button if the navbar is on
  non-default display because there is no accelerometer sensor.
- Avoid leakage by removing navbar fragment from fragment
  host when display is removed.

Bug: 117746225
Bug: 117744614
Test: atest SystemUITests
Test: manual - create a virtual display with system decoration.
      The navbar on the virtual display should not change when
      rotating or changing density of default display.
      And after releasing the display, use command "dumpsys
      activity service com.android.systemui/.SystemUIService |
      grep NavigationBarFragment" to check the number of instances.

Change-Id: Icdc8634628ace21395b7eb9d77c6b1067850d1b2
parent 87fd39b7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_bar_frame"
    android:theme="@style/Theme.SystemUI"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

+1 −1
Original line number Diff line number Diff line
@@ -296,7 +296,7 @@ public class Dependency extends SystemUI {
                new WakefulnessLifecycle());

        mProviders.put(FragmentService.class, () ->
                new FragmentService(mContext));
                new FragmentService());

        mProviders.put(ExtensionController.class, () ->
                new ExtensionControllerImpl(mContext));
+7 −3
Original line number Diff line number Diff line
@@ -59,11 +59,11 @@ public class FragmentHostManager {
    private FragmentController mFragments;
    private FragmentLifecycleCallbacks mLifecycleCallbacks;

    FragmentHostManager(Context context, FragmentService manager, View rootView) {
        mContext = context;
    FragmentHostManager(FragmentService manager, View rootView) {
        mContext = rootView.getContext();
        mManager = manager;
        mRootView = rootView;
        mConfigChanges.applyNewConfig(context.getResources());
        mConfigChanges.applyNewConfig(mContext.getResources());
        createFragmentHost(null);
    }

@@ -203,6 +203,10 @@ public class FragmentHostManager {
        }
    }

    public static void removeAndDestroy(View view) {
        Dependency.get(FragmentService.class).removeAndDestroy(view);
    }

    class HostCallbacks extends FragmentHostCallback<FragmentHostManager> {
        public HostCallbacks() {
            super(mContext, FragmentHostManager.this.mHandler, 0);
+8 −11
Original line number Diff line number Diff line
@@ -14,18 +14,13 @@

package com.android.systemui.fragments;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.util.ArrayMap;
import android.util.Log;
import android.view.View;

import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dumpable;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -40,11 +35,6 @@ public class FragmentService implements ConfigurationChangedReceiver, Dumpable {

    private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
    private final Handler mHandler = new Handler();
    private final Context mContext;

    public FragmentService(Context context) {
        mContext = context;
    }

    public FragmentHostManager getFragmentHostManager(View view) {
        View root = view.getRootView();
@@ -56,6 +46,13 @@ public class FragmentService implements ConfigurationChangedReceiver, Dumpable {
        return state.getFragmentHostManager();
    }

    public void removeAndDestroy(View view) {
        final FragmentHostState state = mHosts.remove(view.getRootView());
        if (state != null) {
            state.mFragmentHostManager.destroy();
        }
    }

    public void destroyAll() {
        for (FragmentHostState state : mHosts.values()) {
            state.mFragmentHostManager.destroy();
@@ -84,7 +81,7 @@ public class FragmentService implements ConfigurationChangedReceiver, Dumpable {

        public FragmentHostState(View view) {
            mView = view;
            mFragmentHostManager = new FragmentHostManager(mContext, FragmentService.this, mView);
            mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);
        }

        public void sendConfigurationChange(Configuration newConfig) {
+46 −22
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {

    private OverviewProxyService mOverviewProxyService;

    private boolean mIsOnDefaultDisplay = true;
    public boolean mHomeBlockedThisTouch;

    private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@@ -241,6 +242,11 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mNavigationBarView = (NavigationBarView) view;
        final Display display = view.getDisplay();
        // It may not have display when running unit test.
        if (display != null) {
            mIsOnDefaultDisplay = display.getDisplayId() == Display.DEFAULT_DISPLAY;
        }

        mNavigationBarView.setComponents(mStatusBar.getPanel());
        mNavigationBarView.setDisabledFlags(mDisabledFlags1);
@@ -253,8 +259,6 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
        prepareNavigationBarView();
        checkNavBarModes();

        setDisabled2Flags(mDisabledFlags2);

        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -262,16 +266,23 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
        notifyNavigationBarScreenOn();
        mOverviewProxyService.addCallback(mOverviewProxyListener);

        RotationContextButton rotationButton = mNavigationBarView.getRotateSuggestionButton();
        // Currently there is no accelerometer sensor on non-default display.
        if (mIsOnDefaultDisplay) {
            final RotationContextButton rotationButton =
                    mNavigationBarView.getRotateSuggestionButton();
            rotationButton.setListener(mRotationButtonListener);
            rotationButton.addRotationCallback(mRotationWatcher);

        // Reset user rotation pref to match that of the WindowManager if starting in locked mode
        // This will automatically happen when switching from auto-rotate to locked mode
        if (rotationButton.isRotationLocked()) {
            final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
            // Reset user rotation pref to match that of the WindowManager if starting in locked
            // mode. This will automatically happen when switching from auto-rotate to locked mode.
            if (display != null && rotationButton.isRotationLocked()) {
                final int winRotation = display.getRotation();
                rotationButton.setRotationLockedAtAngle(winRotation);
            }
        } else {
            mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
        }
        setDisabled2Flags(mDisabledFlags2);
    }

    @Override
@@ -389,7 +400,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {

    @Override
    public void onRotationProposal(final int rotation, boolean isValid) {
        final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
        final int winRotation = mNavigationBarView.getDisplay().getRotation();
        final boolean rotateSuggestionsDisabled = RotationContextButton
                .hasDisable2RotateSuggestionFlag(mDisabledFlags2);
        if (RotationContextButton.DEBUG_ROTATION) {
@@ -477,12 +488,15 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
            updateScreenPinningGestures();
        }

        // Only default display supports rotation suggestions.
        if (mIsOnDefaultDisplay) {
            final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
            if (masked2 != mDisabledFlags2) {
                mDisabledFlags2 = masked2;
                setDisabled2Flags(masked2);
            }
        }
    }

    private void setDisabled2Flags(int state2) {
        // Method only called on change of disable2 flags
@@ -881,13 +895,23 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
        if (navigationBarView == null) return null;

        context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
        FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
        NavigationBarFragment fragment = new NavigationBarFragment();
        final NavigationBarFragment fragment = new NavigationBarFragment();
        navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {
                final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
                fragmentHost.getFragmentManager().beginTransaction()
                        .replace(R.id.navigation_bar_frame, fragment, TAG)
                        .commit();
                fragmentHost.addTagListener(TAG, listener);
            }

            @Override
            public void onViewDetachedFromWindow(View v) {
                FragmentHostManager.removeAndDestroy(v);
            }
        });
        context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
        return navigationBarView;
    }
}
Loading