Loading apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +48 −26 Original line number Diff line number Diff line Loading @@ -17,11 +17,10 @@ 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.Manifest; import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchMigrationHelper; import android.app.appsearch.AppSearchResult; Loading Loading @@ -63,6 +62,7 @@ import com.android.server.appsearch.external.localstorage.AppSearchImpl; import com.android.server.appsearch.external.localstorage.stats.CallStats; import com.android.server.appsearch.stats.LoggerInstanceManager; import com.android.server.appsearch.stats.PlatformLogger; import com.android.server.appsearch.util.PackageUtil; import com.android.server.usage.StorageStatsManagerLocal; import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter; Loading Loading @@ -124,8 +124,10 @@ public class AppSearchManagerService extends SystemService { } private void registerReceivers() { mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL, new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null, mContext.registerReceiverForAllUsers( new UserActionReceiver(), 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 Loading @@ -135,8 +137,10 @@ public class AppSearchManagerService extends SystemService { 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, mContext.registerReceiverForAllUsers( new PackageChangedReceiver(), packageChangedFilter, /*broadcastPermission=*/ null, /*scheduler=*/ null); } Loading @@ -148,12 +152,13 @@ public class AppSearchManagerService extends SystemService { switch (intent.getAction()) { case Intent.ACTION_USER_REMOVED: int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); if (userId == USER_NULL) { Log.e(TAG, "userId is missing in the intent: " + intent); UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER); if (userHandle == null) { Log.e(TAG, "Extra " + Intent.EXTRA_USER + " is missing in the intent: " + intent); return; } handleUserRemoved(UserHandle.of(userId)); handleUserRemoved(userHandle); break; default: Log.e(TAG, "Received unknown intent: " + intent); Loading Loading @@ -1183,13 +1188,9 @@ public class AppSearchManagerService extends SystemService { Objects.requireNonNull(actualCallingUser); Objects.requireNonNull(claimedCallingPackage); int claimedCallingUid; try { Context claimedCallingContext = mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0); claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid( claimedCallingPackage, /*flags=*/ 0); } catch (PackageManager.NameNotFoundException e) { int claimedCallingUid = PackageUtil.getPackageUidAsUser( mContext, claimedCallingPackage, actualCallingUser); if (claimedCallingUid == INVALID_UID) { throw new SecurityException( "Specified calling package [" + claimedCallingPackage + "] not found"); } Loading Loading @@ -1257,23 +1258,44 @@ public class AppSearchManagerService extends SystemService { * * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user. * * @param requestedUser The user which the caller is requesting to execute as. * @param callingUid The actual uid of the caller as determined by Binder. * @return the user handle that the call should run as. Will always be a concrete user. */ // TODO(b/173553485) verifying that the caller has permission to access target user's data // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast // TODO(b/173553485) Implement SystemService.onUserStopping() @NonNull private static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) { private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) { int callingPid = Binder.getCallingPid(); int finalUserId = ActivityManager.handleIncomingUser( UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid); if (callingUser.equals(requestedUser)) { return requestedUser; } // Duplicates UserController#ensureNotSpecialUser if (requestedUser.getIdentifier() < 0) { throw new IllegalArgumentException( "Call does not support special user " + requestedUser); } boolean canInteractAcrossUsers = mContext.checkPermission( Manifest.permission.INTERACT_ACROSS_USERS, callingPid, callingUid, userHandle.getIdentifier(), /*allowAll=*/ false, /*requireFull=*/ false, /*name=*/ null, /*callerPackage=*/ null); return UserHandle.of(finalUserId); callingUid) == PackageManager.PERMISSION_GRANTED; if (!canInteractAcrossUsers) { canInteractAcrossUsers = mContext.checkPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPid, callingUid) == PackageManager.PERMISSION_GRANTED; } if (canInteractAcrossUsers) { return requestedUser; } throw new SecurityException( "Permission denied while calling from uid " + callingUid + " with " + requestedUser + "; Need to run as either the calling user (" + callingUser + "), or with one of the following permissions: " + Manifest.permission.INTERACT_ACROSS_USERS + " or " + Manifest.permission.INTERACT_ACROSS_USERS_FULL); } // TODO(b/179160886): Cache the previous storage stats. Loading apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +1 −6 Original line number Diff line number Diff line Loading @@ -172,11 +172,6 @@ public final class ImplInstanceManager { @Nullable AppSearchLogger logger) throws AppSearchException { File appSearchDir = getAppSearchDir(userHandle); // TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too return AppSearchImpl.create( appSearchDir, userContext, userHandle.getIdentifier(), /*logger=*/ null); return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null); } } apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java +2 −5 Original line number Diff line number Diff line Loading @@ -201,7 +201,6 @@ public final class AppSearchImpl implements Closeable { public static AppSearchImpl create( @NonNull File icingDir, @NonNull Context userContext, int userId, @Nullable AppSearchLogger logger) throws AppSearchException { Objects.requireNonNull(icingDir); Loading @@ -213,8 +212,7 @@ public final class AppSearchImpl implements Closeable { initStatsBuilder = new InitializeStats.Builder(); } AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, userId, initStatsBuilder); AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder); long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime(); appSearchImpl.initializeVisibilityStore(); Loading @@ -238,7 +236,6 @@ public final class AppSearchImpl implements Closeable { private AppSearchImpl( @NonNull File icingDir, @NonNull Context userContext, int userId, @Nullable InitializeStats.Builder initStatsBuilder) throws AppSearchException { mReadWriteLock.writeLock().lock(); Loading @@ -256,7 +253,7 @@ public final class AppSearchImpl implements Closeable { "Constructing IcingSearchEngine, response", Objects.hashCode(mIcingSearchEngineLocked)); mVisibilityStoreLocked = new VisibilityStore(this, userContext, userId); mVisibilityStoreLocked = new VisibilityStore(this, userContext); // The core initialization procedure. If any part of this fails, we bail into // resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up). Loading apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java +7 −15 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.appsearch.exceptions.AppSearchException; import android.content.Context; import android.content.pm.PackageManager; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; Loading @@ -36,6 +35,7 @@ import com.android.server.appsearch.external.localstorage.stats.InitializeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; import com.android.server.appsearch.util.PackageUtil; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; Loading Loading @@ -493,21 +493,13 @@ public final class PlatformLogger implements AppSearchLogger { @GuardedBy("mLock") private int getPackageUidAsUserLocked(@NonNull String packageName) { Integer packageUid = mPackageUidCacheLocked.get(packageName); if (packageUid != null) { return packageUid; } // TODO(b/173532925) since VisibilityStore has the same method, we can make this a // utility function try { packageUid = mContext.getPackageManager().getPackageUidAsUser( packageName, mUserHandle.getIdentifier()); if (packageUid == null) { packageUid = PackageUtil.getPackageUidAsUser(mContext, packageName, mUserHandle); if (packageUid != Process.INVALID_UID) { mPackageUidCacheLocked.put(packageName, packageUid); return packageUid; } catch (PackageManager.NameNotFoundException e) { // Package doesn't exist, continue } return Process.INVALID_UID; } return packageUid; } // Loading apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appsearch.util; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.os.Process; import android.os.UserHandle; /** * Utilities for interacting with {@link android.content.pm.PackageManager}, * {@link android.os.UserHandle}, and other parts of dealing with apps and binder. * * @hide */ public class PackageUtil { private PackageUtil() {} /** * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to * find the UID. */ public static int getPackageUidAsUser( @NonNull Context context, @NonNull String packageName, @NonNull UserHandle user) { Context userContext = context.createContextAsUser(user, /*flags=*/ 0); return getPackageUid(userContext, packageName); } /** * Finds the UID of the {@code packageName} in the given {@code context}. Returns * {@link Process#INVALID_UID} if unable to find the UID. */ public static int getPackageUid(@NonNull Context context, @NonNull String packageName) { try { return context.getPackageManager().getPackageUid(packageName, /*flags=*/ 0); } catch (PackageManager.NameNotFoundException e) { return Process.INVALID_UID; } } } Loading
apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +48 −26 Original line number Diff line number Diff line Loading @@ -17,11 +17,10 @@ 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.Manifest; import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchMigrationHelper; import android.app.appsearch.AppSearchResult; Loading Loading @@ -63,6 +62,7 @@ import com.android.server.appsearch.external.localstorage.AppSearchImpl; import com.android.server.appsearch.external.localstorage.stats.CallStats; import com.android.server.appsearch.stats.LoggerInstanceManager; import com.android.server.appsearch.stats.PlatformLogger; import com.android.server.appsearch.util.PackageUtil; import com.android.server.usage.StorageStatsManagerLocal; import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter; Loading Loading @@ -124,8 +124,10 @@ public class AppSearchManagerService extends SystemService { } private void registerReceivers() { mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL, new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null, mContext.registerReceiverForAllUsers( new UserActionReceiver(), 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 Loading @@ -135,8 +137,10 @@ public class AppSearchManagerService extends SystemService { 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, mContext.registerReceiverForAllUsers( new PackageChangedReceiver(), packageChangedFilter, /*broadcastPermission=*/ null, /*scheduler=*/ null); } Loading @@ -148,12 +152,13 @@ public class AppSearchManagerService extends SystemService { switch (intent.getAction()) { case Intent.ACTION_USER_REMOVED: int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); if (userId == USER_NULL) { Log.e(TAG, "userId is missing in the intent: " + intent); UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER); if (userHandle == null) { Log.e(TAG, "Extra " + Intent.EXTRA_USER + " is missing in the intent: " + intent); return; } handleUserRemoved(UserHandle.of(userId)); handleUserRemoved(userHandle); break; default: Log.e(TAG, "Received unknown intent: " + intent); Loading Loading @@ -1183,13 +1188,9 @@ public class AppSearchManagerService extends SystemService { Objects.requireNonNull(actualCallingUser); Objects.requireNonNull(claimedCallingPackage); int claimedCallingUid; try { Context claimedCallingContext = mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0); claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid( claimedCallingPackage, /*flags=*/ 0); } catch (PackageManager.NameNotFoundException e) { int claimedCallingUid = PackageUtil.getPackageUidAsUser( mContext, claimedCallingPackage, actualCallingUser); if (claimedCallingUid == INVALID_UID) { throw new SecurityException( "Specified calling package [" + claimedCallingPackage + "] not found"); } Loading Loading @@ -1257,23 +1258,44 @@ public class AppSearchManagerService extends SystemService { * * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user. * * @param requestedUser The user which the caller is requesting to execute as. * @param callingUid The actual uid of the caller as determined by Binder. * @return the user handle that the call should run as. Will always be a concrete user. */ // TODO(b/173553485) verifying that the caller has permission to access target user's data // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast // TODO(b/173553485) Implement SystemService.onUserStopping() @NonNull private static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) { private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) { int callingPid = Binder.getCallingPid(); int finalUserId = ActivityManager.handleIncomingUser( UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid); if (callingUser.equals(requestedUser)) { return requestedUser; } // Duplicates UserController#ensureNotSpecialUser if (requestedUser.getIdentifier() < 0) { throw new IllegalArgumentException( "Call does not support special user " + requestedUser); } boolean canInteractAcrossUsers = mContext.checkPermission( Manifest.permission.INTERACT_ACROSS_USERS, callingPid, callingUid, userHandle.getIdentifier(), /*allowAll=*/ false, /*requireFull=*/ false, /*name=*/ null, /*callerPackage=*/ null); return UserHandle.of(finalUserId); callingUid) == PackageManager.PERMISSION_GRANTED; if (!canInteractAcrossUsers) { canInteractAcrossUsers = mContext.checkPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPid, callingUid) == PackageManager.PERMISSION_GRANTED; } if (canInteractAcrossUsers) { return requestedUser; } throw new SecurityException( "Permission denied while calling from uid " + callingUid + " with " + requestedUser + "; Need to run as either the calling user (" + callingUser + "), or with one of the following permissions: " + Manifest.permission.INTERACT_ACROSS_USERS + " or " + Manifest.permission.INTERACT_ACROSS_USERS_FULL); } // TODO(b/179160886): Cache the previous storage stats. Loading
apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +1 −6 Original line number Diff line number Diff line Loading @@ -172,11 +172,6 @@ public final class ImplInstanceManager { @Nullable AppSearchLogger logger) throws AppSearchException { File appSearchDir = getAppSearchDir(userHandle); // TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too return AppSearchImpl.create( appSearchDir, userContext, userHandle.getIdentifier(), /*logger=*/ null); return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null); } }
apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java +2 −5 Original line number Diff line number Diff line Loading @@ -201,7 +201,6 @@ public final class AppSearchImpl implements Closeable { public static AppSearchImpl create( @NonNull File icingDir, @NonNull Context userContext, int userId, @Nullable AppSearchLogger logger) throws AppSearchException { Objects.requireNonNull(icingDir); Loading @@ -213,8 +212,7 @@ public final class AppSearchImpl implements Closeable { initStatsBuilder = new InitializeStats.Builder(); } AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, userId, initStatsBuilder); AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder); long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime(); appSearchImpl.initializeVisibilityStore(); Loading @@ -238,7 +236,6 @@ public final class AppSearchImpl implements Closeable { private AppSearchImpl( @NonNull File icingDir, @NonNull Context userContext, int userId, @Nullable InitializeStats.Builder initStatsBuilder) throws AppSearchException { mReadWriteLock.writeLock().lock(); Loading @@ -256,7 +253,7 @@ public final class AppSearchImpl implements Closeable { "Constructing IcingSearchEngine, response", Objects.hashCode(mIcingSearchEngineLocked)); mVisibilityStoreLocked = new VisibilityStore(this, userContext, userId); mVisibilityStoreLocked = new VisibilityStore(this, userContext); // The core initialization procedure. If any part of this fails, we bail into // resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up). Loading
apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java +7 −15 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.appsearch.exceptions.AppSearchException; import android.content.Context; import android.content.pm.PackageManager; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; Loading @@ -36,6 +35,7 @@ import com.android.server.appsearch.external.localstorage.stats.InitializeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; import com.android.server.appsearch.util.PackageUtil; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; Loading Loading @@ -493,21 +493,13 @@ public final class PlatformLogger implements AppSearchLogger { @GuardedBy("mLock") private int getPackageUidAsUserLocked(@NonNull String packageName) { Integer packageUid = mPackageUidCacheLocked.get(packageName); if (packageUid != null) { return packageUid; } // TODO(b/173532925) since VisibilityStore has the same method, we can make this a // utility function try { packageUid = mContext.getPackageManager().getPackageUidAsUser( packageName, mUserHandle.getIdentifier()); if (packageUid == null) { packageUid = PackageUtil.getPackageUidAsUser(mContext, packageName, mUserHandle); if (packageUid != Process.INVALID_UID) { mPackageUidCacheLocked.put(packageName, packageUid); return packageUid; } catch (PackageManager.NameNotFoundException e) { // Package doesn't exist, continue } return Process.INVALID_UID; } return packageUid; } // Loading
apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appsearch.util; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.os.Process; import android.os.UserHandle; /** * Utilities for interacting with {@link android.content.pm.PackageManager}, * {@link android.os.UserHandle}, and other parts of dealing with apps and binder. * * @hide */ public class PackageUtil { private PackageUtil() {} /** * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to * find the UID. */ public static int getPackageUidAsUser( @NonNull Context context, @NonNull String packageName, @NonNull UserHandle user) { Context userContext = context.createContextAsUser(user, /*flags=*/ 0); return getPackageUid(userContext, packageName); } /** * Finds the UID of the {@code packageName} in the given {@code context}. Returns * {@link Process#INVALID_UID} if unable to find the UID. */ public static int getPackageUid(@NonNull Context context, @NonNull String packageName) { try { return context.getPackageManager().getPackageUid(packageName, /*flags=*/ 0); } catch (PackageManager.NameNotFoundException e) { return Process.INVALID_UID; } } }