diff options
author | 2024-12-30 12:50:21 +0000 | |
---|---|---|
committer | 2024-12-30 22:37:20 +0000 | |
commit | 1f40027e306493d006cd724e8fcb0dc51d5a4940 (patch) | |
tree | a7517d54f04060da9275f83d8b3c4148851234fd | |
parent | e9f92c9e587ed958de63f56152caf97492a51307 (diff) |
Grant target implicit visibility onExecuteAppFunctions
Flag: android.app.appfunctions.flags.enable_app_function_manager
Test: atest CtsAppFunctionTestCases -c
Bug: 386324561
Change-Id: I4fd8bdad13f69f2e4837b29b5cee5c2c9552152c
5 files changed, 79 insertions, 26 deletions
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java index c293087defb6..dc6afe17403d 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java @@ -19,7 +19,9 @@ package com.android.server.appfunctions; import android.annotation.NonNull; import android.app.appfunctions.AppFunctionManagerConfiguration; import android.content.Context; +import android.content.pm.PackageManagerInternal; +import com.android.server.LocalServices; import com.android.server.SystemService; /** Service that manages app functions. */ @@ -28,7 +30,9 @@ public class AppFunctionManagerService extends SystemService { public AppFunctionManagerService(Context context) { super(context); - mServiceImpl = new AppFunctionManagerServiceImpl(context); + mServiceImpl = + new AppFunctionManagerServiceImpl( + context, LocalServices.getService(PackageManagerInternal.class)); } @Override diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java index 37276ddac75a..57d33f1a051e 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java @@ -50,6 +50,7 @@ import android.app.appsearch.observer.ObserverSpec; import android.app.appsearch.observer.SchemaChangeInfo; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManagerInternal; import android.os.Binder; import android.os.CancellationSignal; import android.os.IBinder; @@ -87,8 +88,10 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { private final Context mContext; private final Map<String, Object> mLocks = new WeakHashMap<>(); private final AppFunctionsLoggerWrapper mLoggerWrapper; + private final PackageManagerInternal mPackageManagerInternal; - public AppFunctionManagerServiceImpl(@NonNull Context context) { + public AppFunctionManagerServiceImpl( + @NonNull Context context, @NonNull PackageManagerInternal packageManagerInternal) { this( context, new RemoteServiceCallerImpl<>( @@ -96,7 +99,8 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { new CallerValidatorImpl(context), new ServiceHelperImpl(context), new ServiceConfigImpl(), - new AppFunctionsLoggerWrapper(context)); + new AppFunctionsLoggerWrapper(context), + packageManagerInternal); } @VisibleForTesting @@ -106,13 +110,15 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { CallerValidator callerValidator, ServiceHelper appFunctionInternalServiceHelper, ServiceConfig serviceConfig, - AppFunctionsLoggerWrapper loggerWrapper) { + AppFunctionsLoggerWrapper loggerWrapper, + PackageManagerInternal packageManagerInternal) { mContext = Objects.requireNonNull(context); mRemoteServiceCaller = Objects.requireNonNull(remoteServiceCaller); mCallerValidator = Objects.requireNonNull(callerValidator); mInternalServiceHelper = Objects.requireNonNull(appFunctionInternalServiceHelper); mServiceConfig = serviceConfig; mLoggerWrapper = loggerWrapper; + mPackageManagerInternal = Objects.requireNonNull(packageManagerInternal); } /** Called when the user is unlocked. */ @@ -260,6 +266,24 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { "Cannot find the target service.")); return; } + // Grant target app implicit visibility to the caller + final int grantRecipientUserId = targetUser.getIdentifier(); + final int grantRecipientAppId = + UserHandle.getAppId( + mPackageManagerInternal.getPackageUid( + requestInternal + .getClientRequest() + .getTargetPackageName(), + /* flags= */ 0, + /* userId= */ grantRecipientUserId)); + if (grantRecipientAppId > 0) { + mPackageManagerInternal.grantImplicitAccess( + grantRecipientUserId, + serviceIntent, + grantRecipientAppId, + callingUid, + /* direct= */ true); + } bindAppFunctionServiceUnchecked( requestInternal, serviceIntent, diff --git a/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java b/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java index 37a377950a87..071fda4f5d0c 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java @@ -31,8 +31,6 @@ import java.util.Objects; class ServiceHelperImpl implements ServiceHelper { private final Context mContext; - // TODO(b/357551503): Keep track of unlocked users. - ServiceHelperImpl(@NonNull Context context) { mContext = Objects.requireNonNull(context); } diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionManagerServiceImplTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionManagerServiceImplTest.kt index a69e9025bfa0..9aaf9ceda93f 100644 --- a/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionManagerServiceImplTest.kt +++ b/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionManagerServiceImplTest.kt @@ -18,28 +18,35 @@ package com.android.server.appfunctions import android.app.appfunctions.flags.Flags import android.content.Context +import android.content.pm.PackageManagerInternal import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.CheckFlagsRule import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.modules.utils.testing.ExtendedMockitoRule +import com.android.server.LocalServices import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.mock @RunWith(AndroidJUnit4::class) @RequiresFlagsEnabled(Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER) class AppFunctionManagerServiceImplTest { + @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + @get:Rule - val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + val extendedMockitoRule = + ExtendedMockitoRule.Builder(this).mockStatic(LocalServices::class.java).build() private val context: Context get() = ApplicationProvider.getApplicationContext() - private val serviceImpl = AppFunctionManagerServiceImpl(context) + private val serviceImpl = AppFunctionManagerServiceImpl(context, mock<PackageManagerInternal>()) @Test fun testGetLockForPackage_samePackage() { diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt index 896d2a21d0ac..687acf569d15 100644 --- a/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt +++ b/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt @@ -25,11 +25,13 @@ import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback import android.app.appsearch.GenericDocument import android.content.Context import android.content.pm.PackageManager +import android.content.pm.PackageManagerInternal import android.os.UserHandle import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.modules.utils.testing.ExtendedMockitoRule +import com.android.server.LocalServices import com.google.common.util.concurrent.MoreExecutors import org.junit.Before import org.junit.Rule @@ -40,24 +42,25 @@ import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever - -/** - * Tests that AppFunctionsStatsLog logs AppFunctionsRequestReported with the expected values. - */ +/** Tests that AppFunctionsStatsLog logs AppFunctionsRequestReported with the expected values. */ @RunWith(AndroidJUnit4::class) class AppFunctionsLoggingTest { @get:Rule val mExtendedMockitoRule: ExtendedMockitoRule = ExtendedMockitoRule.Builder(this) .mockStatic(AppFunctionsStatsLog::class.java) + .mockStatic(LocalServices::class.java) .build() - private val mContext: Context get() = ApplicationProvider.getApplicationContext() + private val mContext: Context + get() = ApplicationProvider.getApplicationContext() + private val mMockPackageManager = mock<PackageManager>() private val mAppFunctionsLoggerWrapper = AppFunctionsLoggerWrapper( mMockPackageManager, MoreExecutors.directExecutor(), - { TEST_CURRENT_TIME_MILLIS }) + { TEST_CURRENT_TIME_MILLIS }, + ) private lateinit var mSafeCallback: SafeOneTimeExecuteAppFunctionCallback private val mServiceImpl = @@ -67,25 +70,40 @@ class AppFunctionsLoggingTest { mock<CallerValidator>(), mock<ServiceHelper>(), ServiceConfigImpl(), - mAppFunctionsLoggerWrapper) + mAppFunctionsLoggerWrapper, + mock<PackageManagerInternal>(), + ) - private val mRequestInternal = ExecuteAppFunctionAidlRequest( - ExecuteAppFunctionRequest.Builder(TEST_TARGET_PACKAGE, TEST_FUNCTION_ID).build(), - UserHandle.CURRENT, TEST_CALLING_PKG, TEST_INITIAL_REQUEST_TIME_MILLIS - ) + private val mRequestInternal = + ExecuteAppFunctionAidlRequest( + ExecuteAppFunctionRequest.Builder(TEST_TARGET_PACKAGE, TEST_FUNCTION_ID).build(), + UserHandle.CURRENT, + TEST_CALLING_PKG, + TEST_INITIAL_REQUEST_TIME_MILLIS, + ) @Before fun setup() { - whenever(mMockPackageManager.getPackageUid(eq(TEST_TARGET_PACKAGE), any<Int>())).thenReturn(TEST_TARGET_UID) - mSafeCallback = mServiceImpl.initializeSafeExecuteAppFunctionCallback(mRequestInternal, mock<IExecuteAppFunctionCallback>(), TEST_CALLING_UID) + whenever(mMockPackageManager.getPackageUid(eq(TEST_TARGET_PACKAGE), any<Int>())) + .thenReturn(TEST_TARGET_UID) + mSafeCallback = + mServiceImpl.initializeSafeExecuteAppFunctionCallback( + mRequestInternal, + mock<IExecuteAppFunctionCallback>(), + TEST_CALLING_UID, + ) mSafeCallback.setExecutionStartTimeAfterBindMillis(TEST_EXECUTION_TIME_AFTER_BIND_MILLIS) } @Test fun testOnSuccess_logsSuccessResponse() { val response = - ExecuteAppFunctionResponse(GenericDocument.Builder<GenericDocument.Builder<*>>("", "", "") - .setPropertyLong("longProperty", 42L).setPropertyString("stringProperty", "text").build()) + ExecuteAppFunctionResponse( + GenericDocument.Builder<GenericDocument.Builder<*>>("", "", "") + .setPropertyLong("longProperty", 42L) + .setPropertyString("stringProperty", "text") + .build() + ) mSafeCallback.onResult(response) @@ -98,14 +116,16 @@ class AppFunctionsLoggingTest { /* requestSizeBytes= */ eq<Int>(mRequestInternal.clientRequest.requestDataSize), /* responseSizeBytes= */ eq<Int>(response.responseDataSize), /* requestDurationMs= */ eq<Long>(TEST_EXPECTED_E2E_DURATION_MILLIS), - /* requestOverheadMs= */ eq<Long>(TEST_EXPECTED_OVERHEAD_DURATION_MILLIS) + /* requestOverheadMs= */ eq<Long>(TEST_EXPECTED_OVERHEAD_DURATION_MILLIS), ) } } @Test fun testOnError_logsFailureResponse() { - mSafeCallback.onError(AppFunctionException(AppFunctionException.ERROR_DENIED, "Error: permission denied")) + mSafeCallback.onError( + AppFunctionException(AppFunctionException.ERROR_DENIED, "Error: permission denied") + ) ExtendedMockito.verify { AppFunctionsStatsLog.write( @@ -116,7 +136,7 @@ class AppFunctionsLoggingTest { /* requestSizeBytes= */ eq<Int>(mRequestInternal.clientRequest.requestDataSize), /* responseSizeBytes= */ eq<Int>(0), /* requestDurationMs= */ eq<Long>(TEST_EXPECTED_E2E_DURATION_MILLIS), - /* requestOverheadMs= */ eq<Long>(TEST_EXPECTED_OVERHEAD_DURATION_MILLIS) + /* requestOverheadMs= */ eq<Long>(TEST_EXPECTED_OVERHEAD_DURATION_MILLIS), ) } } |