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

Commit 8b875d24 authored by Pinyao Ting's avatar Pinyao Ting
Browse files

Implement Device Flag for shortcut integration with AppSearch

Bug: 185828535
Test: atest ShortcutManagerTest1 ShortcutManagerTest2
ShortcutManagerTest3 ShortcutManagerTest4 ShortcutManagerTest5
ShortcutManagerTest6 ShortcutManagerTest7 ShortcutManagerTest8
ShortcutManagerTest9 ShortcutManagerTest10 ShortcutManagerTest11
Test: atest CtsShortcutManagerTestCases

Change-Id: I6ef8b03cdbc875c965ead30a61d33de838e65b1f
parent 18818b75
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -483,6 +483,12 @@ public final class SystemUiDeviceConfigFlags {
    public static final String HOME_BUTTON_LONG_PRESS_DURATION_MS =
            "home_button_long_press_duration_ms";

    /**
     * (boolean) Whether shortcut integration over app search service is enabled.
     */
    public static final String SHORTCUT_APPSEARCH_INTEGRATION =
            "shortcut_appsearch_integration";

    private SystemUiDeviceConfigFlags() {
    }
}
+68 −15
Original line number Diff line number Diff line
@@ -219,10 +219,12 @@ class ShortcutPackage extends ShortcutPackageItem {
                getPackageName(), getPackageUserId());
    }

    private boolean isAppSearchEnabled() {
        return mShortcutUser.mService.isAppSearchEnabled();
    }

    public int getShortcutCount() {
        final int[] count = new int[1];
        forEachShortcut(si -> count[0]++);
        return count[0];
        return mShortcuts.size();
    }

    @Override
@@ -442,15 +444,18 @@ class ShortcutPackage extends ShortcutPackageItem {
        }

        forceReplaceShortcutInner(newShortcut);
        if (isAppSearchEnabled()) {
            mShortcutUser.mService.injectPostToHandler(() -> awaitInAppSearch("reportUsage",
                    session -> {
                        final AndroidFuture<Boolean> future = new AndroidFuture<>();
                        session.reportUsage(
                                new ReportUsageRequest.Builder(getPackageName())
                                        .setUri(newShortcut.getId()).build(),
                            mShortcutUser.mExecutor, result -> future.complete(result.isSuccess()));
                                mShortcutUser.mExecutor,
                                result -> future.complete(result.isSuccess()));
                        return future;
                    }));
        }
        return deleted;
    }

@@ -960,7 +965,7 @@ class ShortcutPackage extends ShortcutPackageItem {
     * the app's Xml resource.
     */
    int getSharingShortcutCount() {
        if (getShortcutCount() == 0 || mShareTargets.isEmpty()) {
        if (mShareTargets.isEmpty()) {
            return 0;
        }

@@ -1700,7 +1705,7 @@ class ShortcutPackage extends ShortcutPackageItem {
        final int size = mShortcuts.size();
        final int shareTargetSize = mShareTargets.size();

        if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0 && getShortcutCount() == 0) {
        if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0) {
            return; // nothing to write.
        }

@@ -2254,6 +2259,9 @@ class ShortcutPackage extends ShortcutPackageItem {
    }

    void updateVisibility(String packageName, byte[] certificate, boolean visible) {
        if (!isAppSearchEnabled()) {
            return;
        }
        if (visible) {
            mPackageIdentifiers.put(packageName, new PackageIdentifier(packageName, certificate));
        } else {
@@ -2287,6 +2295,14 @@ class ShortcutPackage extends ShortcutPackageItem {

    private void saveShortcut(@NonNull final Collection<ShortcutInfo> shortcuts) {
        Objects.requireNonNull(shortcuts);
        if (!isAppSearchEnabled()) {
            // If AppSearch isn't enabled, save it in memory and we are done.
            for (ShortcutInfo si : shortcuts) {
                mShortcuts.put(si.getId(), si);
            }
            return;
        }
        // Otherwise, save pinned shortcuts in memory.
        shortcuts.forEach(si -> {
            if (si.isPinned()) {
                mShortcuts.put(si.getId(), si);
@@ -2294,12 +2310,13 @@ class ShortcutPackage extends ShortcutPackageItem {
                mShortcuts.remove(si.getId());
            }
        });
        // Then proceed to app search.
        saveToAppSearch(shortcuts);
    }

    private void saveToAppSearch(@NonNull final Collection<ShortcutInfo> shortcuts) {
        Objects.requireNonNull(shortcuts);
        if (shortcuts.isEmpty()) {
        if (!isAppSearchEnabled() || shortcuts.isEmpty()) {
            // No need to invoke AppSearch when there's nothing to save.
            return;
        }
@@ -2335,6 +2352,9 @@ class ShortcutPackage extends ShortcutPackageItem {
     * Removes shortcuts from AppSearch.
     */
    void removeShortcuts() {
        if (!isAppSearchEnabled()) {
            return;
        }
        awaitInAppSearch("Removing all shortcuts from " + getPackageName(), session -> {
            final AndroidFuture<Boolean> future = new AndroidFuture<>();
            session.remove("", getSearchSpec(), mShortcutUser.mExecutor, result -> {
@@ -2352,6 +2372,9 @@ class ShortcutPackage extends ShortcutPackageItem {
    private void removeShortcut(@NonNull final String id) {
        Objects.requireNonNull(id);
        mShortcuts.remove(id);
        if (!isAppSearchEnabled()) {
            return;
        }
        awaitInAppSearch("Removing shortcut with id=" + id, session -> {
            final AndroidFuture<Boolean> future = new AndroidFuture<>();
            session.remove(new RemoveByUriRequest.Builder(getPackageName()).addUris(id).build(),
@@ -2381,6 +2404,16 @@ class ShortcutPackage extends ShortcutPackageItem {
                shortcutIds.add(id);
            }
        }
        if (!isAppSearchEnabled()) {
            final List<ShortcutInfo> ret = new ArrayList<>(1);
            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
                ShortcutInfo si = mShortcuts.valueAt(i);
                if (shortcutIds.contains(si.getId())) {
                    ret.add(si);
                }
            }
            return ret;
        }
        if (ShortcutService.DEBUG_REBOOT) {
            Slog.d(TAG, "Getting shortcuts for user=" + mShortcutUser.getUserId()
                    + " pkg=" + getPackageName() + " ids: [" + String.join(",", ids) + "]");
@@ -2429,6 +2462,13 @@ class ShortcutPackage extends ShortcutPackageItem {

    private void forEachShortcutMutateIf(@NonNull final String query,
            @NonNull final Function<ShortcutInfo, Boolean> cb) {
        if (!isAppSearchEnabled()) {
            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
                ShortcutInfo si = mShortcuts.valueAt(i);
                cb.apply(si);
            }
            return;
        }
        if (ShortcutService.DEBUG_REBOOT) {
            Slog.d(TAG, "Changing shortcuts for user=" + mShortcutUser.getUserId()
                    + " pkg=" + getPackageName());
@@ -2454,6 +2494,15 @@ class ShortcutPackage extends ShortcutPackageItem {

    private void forEachShortcutStopWhen(
            @NonNull final String query, @NonNull final Function<ShortcutInfo, Boolean> cb) {
        if (!isAppSearchEnabled()) {
            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
                final ShortcutInfo si = mShortcuts.valueAt(i);
                if (cb.apply(si)) {
                    return;
                }
            }
            return;
        }
        if (ShortcutService.DEBUG_REBOOT) {
            Slog.d(TAG, "Iterating shortcuts for user=" + mShortcutUser.getUserId()
                    + " pkg=" + getPackageName());
@@ -2517,6 +2566,10 @@ class ShortcutPackage extends ShortcutPackageItem {
            final boolean forceReset,
            @NonNull final String description,
            @NonNull final Function<AppSearchSession, CompletableFuture<T>> cb) {
        if (!isAppSearchEnabled()) {
            throw new IllegalStateException(
                    "awaitInAppSearch called when app search integration is disabled");
        }
        synchronized (mLock) {
            final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
            final long callingIdentity = Binder.clearCallingIdentity();
+12 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.server.pm;

import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;

import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -85,6 +87,7 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.text.format.TimeMigrationUtils;
import android.util.ArraySet;
@@ -104,6 +107,7 @@ import android.view.IWindowManager;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BackgroundThread;
@@ -447,6 +451,8 @@ public class ShortcutService extends IShortcutService.Stub {
    @GuardedBy("mLock")
    private final MetricsLogger mMetricsLogger = new MetricsLogger();

    private final boolean mIsAppSearchEnabled;

    static class InvalidFileFormatException extends Exception {
        public InvalidFileFormatException(String message, Throwable cause) {
            super(message, cause);
@@ -481,6 +487,8 @@ public class ShortcutService extends IShortcutService.Stub {
        mShortcutRequestPinProcessor = new ShortcutRequestPinProcessor(this, mLock);
        mShortcutBitmapSaver = new ShortcutBitmapSaver(this);
        mShortcutDumpFiles = new ShortcutDumpFiles(this);
        mIsAppSearchEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, false);

        if (onlyForPackageManagerApis) {
            return; // Don't do anything further.  For unit tests only.
@@ -518,6 +526,10 @@ public class ShortcutService extends IShortcutService.Stub {
        injectRegisterRoleHoldersListener(mOnRoleHoldersChangedListener);
    }

    boolean isAppSearchEnabled() {
        return mIsAppSearchEnabled;
    }

    long getStatStartTime() {
        return mStatLogger.getTime();
    }
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@
            android:action="action"
            android:data="http://www/"
            android:targetPackage="abc"
            android:targetClass=".xyz"
            android:targetClass="abc.xyz"
            android:mimeType="foo/bar"
            >
            <categories android:name="cat1" />
+11 −1
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.server.pm;

import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;

import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;

import android.app.PendingIntent;
@@ -22,6 +24,9 @@ import android.app.appsearch.PackageIdentifier;
import android.content.pm.AppSearchShortcutInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.DeviceConfig;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;

import java.util.Random;

@@ -33,7 +38,12 @@ import java.util.Random;
public class ShortcutManagerTest12 extends BaseShortcutManagerTest {

    public void testUpdateShortcutVisibility_updatesShortcutSchema() {

        if (!DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.DARK_LAUNCH_REMOTE_PREDICTION_SERVICE_ENABLED,
                false)) {
            // no-op if app-search integration is disabled.
            return;
        }
        final byte[] cert = new byte[20];
        new Random().nextBytes(cert);