diff options
author | 2024-09-12 14:58:46 +0000 | |
---|---|---|
committer | 2024-09-12 16:14:00 +0000 | |
commit | 43db210f0f411fc9886fa7704eab8325b64eb92d (patch) | |
tree | f920048c7c5c442e03ec7b656c646760c86bddea | |
parent | 7cc8ea4c8e0a28751b55abedc1a4b11dcfd9fe28 (diff) |
Handle exceptions in AppFunctionManagerServiceImpl
When an exception occurs, the service will return a failure response to the client instead of throwing an exception,
Change-Id: I2aa8d0e22b9edd0334904186dd9bb118f072f4d7
Flag: android.app.appfunctions.flags.enable_app_function_manager
Test: Verified by running locally. Will add CTS in next cl.
Bug: 360864791
3 files changed, 100 insertions, 3 deletions
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java index f83269f86cd2..269419f70b2f 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java @@ -31,6 +31,7 @@ import android.os.Binder; import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; +import android.app.appsearch.AppSearchResult; import com.android.internal.annotations.VisibleForTesting; import com.android.server.appfunctions.RemoteServiceCaller.RunServiceCallCallback; @@ -81,6 +82,17 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { final SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback = new SafeOneTimeExecuteAppFunctionCallback(executeAppFunctionCallback); + try { + executeAppFunctionInternal(requestInternal, safeExecuteAppFunctionCallback); + } catch (Exception e) { + safeExecuteAppFunctionCallback.onResult(mapExceptionToExecuteAppFunctionResponse(e)); + } + } + + private void executeAppFunctionInternal( + ExecuteAppFunctionAidlRequest requestInternal, + SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) { + String validatedCallingPackage; UserHandle targetUser; try { @@ -119,7 +131,7 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { return; } - mCallerValidator + var unused = mCallerValidator .verifyCallerCanExecuteAppFunction( validatedCallingPackage, targetPackageName, @@ -159,6 +171,12 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { } finally { Binder.restoreCallingIdentity(token); } + }) + .exceptionally( + ex -> { + safeExecuteAppFunctionCallback.onResult( + mapExceptionToExecuteAppFunctionResponse(ex)); + return null; }); } @@ -235,4 +253,37 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { /* extras= */ null)); } } + + private ExecuteAppFunctionResponse mapExceptionToExecuteAppFunctionResponse(Throwable e) { + if (e instanceof AppSearchException) { + AppSearchException appSearchException = (AppSearchException) e; + return ExecuteAppFunctionResponse.newFailure( + mapAppSearchResultFailureCodeToExecuteAppFunctionResponse( + appSearchException.getResultCode()), + appSearchException.getMessage(), + /* extras= */ null); + } + + return ExecuteAppFunctionResponse.newFailure( + ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR, + e.getMessage(), + /* extras= */ null); + } + + private int mapAppSearchResultFailureCodeToExecuteAppFunctionResponse(int resultCode) { + if (resultCode == AppSearchResult.RESULT_OK) { + throw new IllegalArgumentException( + "This method can only be used to convert failure result codes."); + } + + switch (resultCode) { + case AppSearchResult.RESULT_NOT_FOUND: + return ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT; + case AppSearchResult.RESULT_INVALID_ARGUMENT: + case AppSearchResult.RESULT_INTERNAL_ERROR: + case AppSearchResult.RESULT_SECURITY_ERROR: + // fall-through + } + return ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR; + } } diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppSearchException.java b/services/appfunctions/java/com/android/server/appfunctions/AppSearchException.java new file mode 100644 index 000000000000..c23470a68c70 --- /dev/null +++ b/services/appfunctions/java/com/android/server/appfunctions/AppSearchException.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 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.appfunctions; + +import android.app.appsearch.AppSearchResult; + +/** Exception to wrap failure result codes returned by AppSearch. */ +public class AppSearchException extends RuntimeException { + private final int resultCode; + + public AppSearchException(int resultCode, String message) { + super(message); + this.resultCode = resultCode; + } + + /** + * Returns the result code used to create this exception, typically one of the {@link + * AppSearchResult} result codes. + */ + public int getResultCode() { + return resultCode; + } +} diff --git a/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java b/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java index 99984384f455..c4ccdd89ffae 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java @@ -30,6 +30,7 @@ import android.app.admin.DevicePolicyManager; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchManager; import android.app.appsearch.AppSearchManager.SearchContext; +import android.app.appsearch.AppSearchResult; import android.app.appsearch.GenericDocument; import android.app.appsearch.GetByDocumentIdRequest; import android.content.Context; @@ -38,8 +39,9 @@ import android.os.Binder; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; -import java.util.Objects; + import com.android.internal.infra.AndroidFuture; +import java.util.Objects; /* Validates that caller has the correct privilege to call an AppFunctionManager Api. */ class CallerValidatorImpl implements CallerValidator { @@ -144,7 +146,14 @@ class CallerValidatorImpl implements CallerValidator { if (result.isSuccess()) { return result.getSuccesses().get(documentId); } - throw new IllegalArgumentException("No document in the result for id: " + documentId); + + AppSearchResult<GenericDocument> failedResult = result.getFailures().get(documentId); + throw new AppSearchException( + failedResult.getResultCode(), + "Unable to retrieve document with id: " + + documentId + + " due to " + + failedResult.getErrorMessage()); } private static boolean getRestrictCallersWithExecuteAppFunctionsProperty( |