Loading apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +68 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading @@ -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); } } } Loading @@ -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); } } Loading @@ -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)); } } Loading apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +10 −6 Original line number Diff line number Diff line Loading @@ -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. * Loading Loading @@ -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. * Loading Loading
apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +68 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading @@ -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); } } } Loading @@ -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); } } Loading @@ -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)); } } Loading
apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +10 −6 Original line number Diff line number Diff line Loading @@ -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. * Loading Loading @@ -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. * Loading