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

Commit 7ce25ed8 authored by Terry Wang's avatar Terry Wang Committed by Android (Google) Code Review
Browse files

Merge "Register PackageChangedReceiver to AppSearchManagerService." into sc-dev

parents 1707d126 2f8ab2bd
Loading
Loading
Loading
Loading
+68 −11
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.server.appsearch;

import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
import static android.os.Process.INVALID_UID;
import static android.os.UserHandle.USER_NULL;

import android.annotation.ElapsedRealtimeLong;
@@ -53,7 +54,6 @@ import android.os.UserManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
@@ -128,6 +128,17 @@ public class AppSearchManagerService extends SystemService {
        mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
                new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
                /*scheduler=*/ null);

        //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
        // broadcasts
        IntentFilter packageChangedFilter = new IntentFilter();
        packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
        packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
        packageChangedFilter.addDataScheme("package");
        packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
                packageChangedFilter, /*broadcastPermission=*/ null,
                /*scheduler=*/ null);
    }

    private class UserActionReceiver extends BroadcastReceiver {
@@ -135,15 +146,15 @@ public class AppSearchManagerService extends SystemService {
        public void onReceive(@NonNull Context context, @NonNull Intent intent) {
            switch (intent.getAction()) {
                case Intent.ACTION_USER_REMOVED:
                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
                    if (userId == USER_NULL) {
                        Slog.e(TAG, "userId is missing in the intent: " + intent);
                        Log.e(TAG, "userId is missing in the intent: " + intent);
                        return;
                    }
                    handleUserRemoved(userId);
                    break;
                default:
                    Slog.e(TAG, "Received unknown intent: " + intent);
                    Log.e(TAG, "Received unknown intent: " + intent);
            }
        }
    }
@@ -163,9 +174,52 @@ public class AppSearchManagerService extends SystemService {
        try {
            mImplInstanceManager.removeAppSearchImplForUser(userId);
            mLoggerInstanceManager.removePlatformLoggerForUser(userId);
            Slog.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
            Log.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
        } catch (Throwable t) {
            Slog.e(TAG, "Unable to remove data for user: " + userId, t);
            Log.e(TAG, "Unable to remove data for user: " + userId, t);
        }
    }

    private class PackageChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(@NonNull Context context, @NonNull Intent intent) {
            switch (intent.getAction()) {
                case Intent.ACTION_PACKAGE_FULLY_REMOVED:
                case Intent.ACTION_PACKAGE_DATA_CLEARED:
                    String packageName = intent.getData().getSchemeSpecificPart();
                    if (packageName == null) {
                        Log.e(TAG, "Package name is missing in the intent: " + intent);
                        return;
                    }
                    int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
                    if (uid == INVALID_UID) {
                        Log.e(TAG, "uid is missing in the intent: " + intent);
                        return;
                    }
                    handlePackageRemoved(packageName, uid);
                    break;
                default:
                    Log.e(TAG, "Received unknown intent: " + intent);
            }
        }
    }

    private void handlePackageRemoved(String packageName, int uid) {
        int userId = UserHandle.getUserId(uid);
        try {
            if (isUserLocked(userId)) {
                //TODO(b/186151459) clear the uninstalled package data when user is unlocked.
                return;
            }
            if (ImplInstanceManager.getAppSearchDir(userId).exists()) {
                // Only clear the package's data if AppSearch exists for this user.
                AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
                        userId);
                //TODO(b/145759910) clear visibility setting for package.
                impl.clearPackageData(packageName);
            }
        } catch (Throwable t) {
            Log.e(TAG, "Unable to remove data for package: " + packageName, t);
        }
    }

@@ -177,17 +231,20 @@ public class AppSearchManagerService extends SystemService {
    }

    private void verifyUserUnlocked(int callingUserId) {
        if (isUserLocked(callingUserId)) {
            throw new IllegalStateException("User " + callingUserId + " is locked or not running.");
        }
    }

    private boolean isUserLocked(int callingUserId) {
        synchronized (mUnlockedUserIdsLocked) {
            // First, check the local copy.
            if (mUnlockedUserIdsLocked.contains(callingUserId)) {
                return;
                return false;
            }
            // If the local copy says the user is locked, check with UM for the actual state,
            // since the user might just have been unlocked.
            if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId))) {
                throw new IllegalStateException(
                        "User " + callingUserId + " is locked or not running.");
            }
            return !mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId));
        }
    }

+10 −6
Original line number Diff line number Diff line
@@ -72,6 +72,15 @@ public final class ImplInstanceManager {
        return sImplInstanceManager;
    }

    /**
     * Returns AppSearch directory in the credential encrypted system directory for the given user.
     *
     * <p>This folder should only be accessed after unlock.
     */
    public static File getAppSearchDir(@UserIdInt int userId) {
        return new File(Environment.getDataSystemCeDirectory(userId), APP_SEARCH_DIR);
    }

    /**
     * Gets an instance of AppSearchImpl for the given user, or creates one if none exists.
     *
@@ -139,15 +148,10 @@ public final class ImplInstanceManager {

    private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId)
            throws AppSearchException {
        File appSearchDir = getAppSearchDir(context, userId);
        File appSearchDir = getAppSearchDir(userId);
        return AppSearchImpl.create(appSearchDir, context, userId, mGlobalQuerierPackage);
    }

    private static File getAppSearchDir(@NonNull Context context, @UserIdInt int userId) {
        // See com.android.internal.app.ChooserActivity::getPinnedSharedPrefs
        return new File(Environment.getDataSystemCeDirectory(userId), APP_SEARCH_DIR);
    }

    /**
     * Returns the global querier package if it's a system package. Otherwise, empty string.
     *