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

Commit 1557fc99 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge changes from topic "p4_default_gestural_nav" into qt-dev

* changes:
  Defer applying gestural nav until the device is provisioned and user is setup
  Exposing default theme overlays to system callers
parents 62751b80 facf213b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -152,4 +152,9 @@ interface IOverlayManager {
     * @param userId The user for which to change the overlay.
     */
    boolean setLowestPriority(in String packageName, in int userId);

    /**
     * Returns the list of default overlay packages, or an empty array if there are none.
     */
    String[] getDefaultOverlayPackages();
}
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ import com.android.systemui.util.NotificationChannels;
 */
public class PipNotification {
    private static final String TAG = "PipNotification";
    private static final String NOTIFICATION_TAG = PipNotification.class.getName();
    private static final String NOTIFICATION_TAG = PipNotification.class.getSimpleName();
    private static final boolean DEBUG = PipManager.DEBUG;

    private static final String ACTION_MENU = "PipNotification.menu";
+1 −1
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ import javax.inject.Singleton;
@Singleton
public class NavigationBarController implements Callbacks {

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

    private final Context mContext;
    private final Handler mHandler;
+149 −17
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package com.android.systemui.statusbar.phone;

import static android.content.Intent.ACTION_OVERLAY_CHANGED;
import static android.content.Intent.ACTION_USER_SWITCHED;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;

import android.content.BroadcastReceiver;
import android.content.Context;
@@ -28,16 +30,21 @@ import android.content.om.IOverlayManager;
import android.content.pm.PackageManager;
import android.content.res.ApkAssets;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseBooleanArray;

import com.android.systemui.Dumpable;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;

import javax.inject.Inject;
import javax.inject.Singleton;
@@ -48,7 +55,7 @@ import javax.inject.Singleton;
@Singleton
public class NavigationModeController implements Dumpable {

    private static final String TAG = NavigationModeController.class.getName();
    private static final String TAG = NavigationModeController.class.getSimpleName();
    private static final boolean DEBUG = true;

    public interface ModeChangedListener {
@@ -57,6 +64,10 @@ public class NavigationModeController implements Dumpable {

    private final Context mContext;
    private final IOverlayManager mOverlayManager;
    private final DeviceProvisionedController mDeviceProvisionedController;
    private final UiOffloadThread mUiOffloadThread;

    private SparseBooleanArray mRestoreGesturalNavBarMode = new SparseBooleanArray();

    private int mMode = NAV_BAR_MODE_3BUTTON;
    private ArrayList<ModeChangedListener> mListeners = new ArrayList<>();
@@ -64,36 +75,90 @@ public class NavigationModeController implements Dumpable {
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            context = getCurrentUserContext();
            int mode = getCurrentInteractionMode(context);
            mMode = mode;
            if (intent.getAction().equals(ACTION_OVERLAY_CHANGED)) {
                if (DEBUG) {
                Log.e(TAG, "ACTION_OVERLAY_CHANGED: mode=" + mMode
                        + " contextUser=" + context.getUserId());
                dumpAssetPaths(context);
                    Log.d(TAG, "ACTION_OVERLAY_CHANGED");
                }
                updateCurrentInteractionMode(true /* notify */);
            }
        }
    };

            for (int i = 0; i < mListeners.size(); i++) {
                mListeners.get(i).onNavigationModeChanged(mode);
    private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedCallback =
            new DeviceProvisionedController.DeviceProvisionedListener() {
                @Override
                public void onDeviceProvisionedChanged() {
                    if (DEBUG) {
                        Log.d(TAG, "onDeviceProvisionedChanged: "
                                + mDeviceProvisionedController.isDeviceProvisioned());
                    }
                    // Once the device has been provisioned, check if we can restore gestural nav
                    restoreGesturalNavOverlayIfNecessary();
                }

                @Override
                public void onUserSetupChanged() {
                    if (DEBUG) {
                        Log.d(TAG, "onUserSetupChanged: "
                                + mDeviceProvisionedController.isCurrentUserSetup());
                    }
                    // Once the user has been setup, check if we can restore gestural nav
                    restoreGesturalNavOverlayIfNecessary();
                }

                @Override
                public void onUserSwitched() {
                    if (DEBUG) {
                        Log.d(TAG, "onUserSwitched: "
                                + ActivityManagerWrapper.getInstance().getCurrentUserId());
                    }

                    // Update the nav mode for the current user
                    updateCurrentInteractionMode(true /* notify */);

                    // When switching users, defer enabling the gestural nav overlay until the user
                    // is all set up
                    deferGesturalNavOverlayIfNecessary();
                }
            };

    @Inject
    public NavigationModeController(Context context) {
    public NavigationModeController(Context context,
            DeviceProvisionedController deviceProvisionedController,
            UiOffloadThread uiOffloadThread) {
        mContext = context;
        mOverlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        mUiOffloadThread = uiOffloadThread;
        mDeviceProvisionedController = deviceProvisionedController;
        mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);

        IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
        overlayFilter.addDataScheme("package");
        overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);

        IntentFilter userFilter = new IntentFilter(ACTION_USER_SWITCHED);
        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, userFilter, null, null);
        updateCurrentInteractionMode(false /* notify */);

        // Check if we need to defer enabling gestural nav
        deferGesturalNavOverlayIfNecessary();
    }

    public void updateCurrentInteractionMode(boolean notify) {
        Context context = getCurrentUserContext();
        int mode = getCurrentInteractionMode(context);
        mMode = mode;
        if (DEBUG) {
            Log.e(TAG, "updateCurrentInteractionMode: mode=" + mMode
                    + " contextUser=" + context.getUserId());
            dumpAssetPaths(context);
        }

        mMode = getCurrentInteractionMode(getCurrentUserContext());
        if (notify) {
            for (int i = 0; i < mListeners.size(); i++) {
                mListeners.get(i).onNavigationModeChanged(mode);
            }
        }
    }

    public int addListener(ModeChangedListener listener) {
@@ -129,10 +194,77 @@ public class NavigationModeController implements Dumpable {
        }
    }

    private void deferGesturalNavOverlayIfNecessary() {
        final int userId = mDeviceProvisionedController.getCurrentUser();
        mRestoreGesturalNavBarMode.put(userId, false);
        if (mDeviceProvisionedController.isDeviceProvisioned()
                && mDeviceProvisionedController.isCurrentUserSetup()) {
            // User is already setup and device is provisioned, nothing to do
            if (DEBUG) {
                Log.d(TAG, "deferGesturalNavOverlayIfNecessary: device is provisioned and user is "
                        + "setup");
            }
            return;
        }

        ArrayList<String> defaultOverlays = new ArrayList<>();
        try {
            defaultOverlays.addAll(Arrays.asList(mOverlayManager.getDefaultOverlayPackages()));
        } catch (RemoteException e) {
            Log.e(TAG, "deferGesturalNavOverlayIfNecessary: failed to fetch default overlays");
        }
        if (!defaultOverlays.contains(NAV_BAR_MODE_GESTURAL_OVERLAY)) {
            // No default gesture nav overlay
            if (DEBUG) {
                Log.d(TAG, "deferGesturalNavOverlayIfNecessary: no default gestural overlay, "
                        + "default=" + defaultOverlays);
            }
            return;
        }

        // If the default is gestural, force-enable three button mode until the device is
        // provisioned
        setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
        mRestoreGesturalNavBarMode.put(userId, true);
        if (DEBUG) {
            Log.d(TAG, "deferGesturalNavOverlayIfNecessary: setting to 3 button mode");
        }
    }

    private void restoreGesturalNavOverlayIfNecessary() {
        if (DEBUG) {
            Log.d(TAG, "restoreGesturalNavOverlayIfNecessary: needs restore="
                    + mRestoreGesturalNavBarMode);
        }
        final int userId = mDeviceProvisionedController.getCurrentUser();
        if (mRestoreGesturalNavBarMode.get(userId)) {
            // Restore the gestural state if necessary
            setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
            mRestoreGesturalNavBarMode.put(userId, false);
        }
    }

    public void setModeOverlay(String overlayPkg, int userId) {
        mUiOffloadThread.submit(() -> {
            try {
                mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
            }
        });
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("NavigationModeController:");
        pw.println("  mode=" + mMode);
        String defaultOverlays = "";
        try {
            defaultOverlays = String.join(", ", mOverlayManager.getDefaultOverlayPackages());
        } catch (RemoteException e) {
            defaultOverlays = "failed_to_fetch";
        }
        pw.println("  defaultOverlays=" + defaultOverlays);
        dumpAssetPaths(getCurrentUserContext());
    }

+20 −0
Original line number Diff line number Diff line
@@ -719,6 +719,26 @@ public final class OverlayManagerService extends SystemService {
            }
        }

        @Override
        public String[] getDefaultOverlayPackages() throws RemoteException {
            try {
                traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages");
                getContext().enforceCallingOrSelfPermission(
                        android.Manifest.permission.MODIFY_THEME_OVERLAY, null);

                final long ident = Binder.clearCallingIdentity();
                try {
                    synchronized (mLock) {
                        return mImpl.getDefaultOverlayPackages();
                    }
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            } finally {
                traceEnd(TRACE_TAG_RRO);
            }
        }

        @Override
        public void onShellCommand(@NonNull final FileDescriptor in,
                @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
Loading