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

Commit 76e22a5a authored by Oluwarotimi Adesina's avatar Oluwarotimi Adesina
Browse files

Replace Builder with named constructor

Context: ExecuteAppFunctionResponse Api

Flag: android.app.appfunctions.flags.enable_app_function_manager
Test: added CTS
Bug: 357551503
Change-Id: I62f9897ccde85f99106ff3c60f71a7455a42f813
parent 88f1c7e6
Loading
Loading
Loading
Loading
+2 −7
Original line number Diff line number Diff line
@@ -8756,6 +8756,8 @@ package android.app.appfunctions {
    method public int getResultCode();
    method @NonNull public android.app.appsearch.GenericDocument getResultDocument();
    method public boolean isSuccess();
    method @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") @NonNull public static android.app.appfunctions.ExecuteAppFunctionResponse newFailure(int, @Nullable String, @Nullable android.os.Bundle);
    method @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") @NonNull public static android.app.appfunctions.ExecuteAppFunctionResponse newSuccess(@NonNull android.app.appsearch.GenericDocument, @Nullable android.os.Bundle);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionResponse> CREATOR;
    field public static final String PROPERTY_RETURN_VALUE = "returnValue";
@@ -8767,13 +8769,6 @@ package android.app.appfunctions {
    field public static final int RESULT_TIMED_OUT = 5; // 0x5
  }
  @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final class ExecuteAppFunctionResponse.Builder {
    ctor public ExecuteAppFunctionResponse.Builder(@NonNull android.app.appsearch.GenericDocument);
    ctor public ExecuteAppFunctionResponse.Builder(int, @NonNull String);
    method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse build();
    method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse.Builder setExtras(@NonNull android.os.Bundle);
  }
}
package android.app.assist {
+3 −4
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ public final class AppFunctionManager {
     *
     * @param mService An interface to the backing service.
     * @param context  A {@link Context}.
     *
     * @hide
     */
    public AppFunctionManager(IAppFunctionManager service, Context context) {
@@ -108,8 +107,8 @@ public final class AppFunctionManager {
                            } catch (RuntimeException e) {
                                // Ideally shouldn't happen since errors are wrapped into the
                                // response, but we catch it here for additional safety.
                                callback.accept(new ExecuteAppFunctionResponse.Builder(
                                        getResultCode(e), e.getMessage()).build());
                                callback.accept(ExecuteAppFunctionResponse.newFailure(
                                        getResultCode(e), e.getMessage(), /*extras=*/ null));
                            }
                        }
                    });
+3 −6
Original line number Diff line number Diff line
@@ -81,8 +81,9 @@ public abstract class AppFunctionService extends Service {
                        // Apps should handle exceptions. But if they don't, report the error on
                        // behalf of them.
                        safeCallback.onResult(
                                new ExecuteAppFunctionResponse.Builder(
                                        getResultCode(ex), getExceptionMessage(ex)).build());
                                ExecuteAppFunctionResponse.newFailure(
                                        getResultCode(ex),
                                        ex.getMessage(), /*extras=*/  null));
                    }
                }
            };
@@ -117,8 +118,4 @@ public abstract class AppFunctionService extends Service {
    public abstract void onExecuteFunction(
            @NonNull ExecuteAppFunctionRequest request,
            @NonNull Consumer<ExecuteAppFunctionResponse> callback);

    private String getExceptionMessage(Exception exception) {
        return exception.getMessage() == null ? "" : exception.getMessage();
    }
}
+49 −60
Original line number Diff line number Diff line
@@ -161,6 +161,55 @@ public final class ExecuteAppFunctionResponse implements Parcelable {
        return ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR;
    }

    /**
     * Returns a successful response.
     *
     * @param resultDocument The return value of the executed function.
     * @param extras         The additional metadata data relevant to this function execution
     *                       response.
     */
    @NonNull
    @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
    public static ExecuteAppFunctionResponse newSuccess(@NonNull GenericDocument resultDocument,
                                                        @Nullable Bundle extras) {
        Objects.requireNonNull(resultDocument);
        Bundle actualExtras = getActualExtras(extras);
        GenericDocumentWrapper resultDocumentWrapper = new GenericDocumentWrapper(resultDocument);

        return new ExecuteAppFunctionResponse(
                resultDocumentWrapper, actualExtras, RESULT_OK, /*errorMessage=*/null);
    }

    /**
     * Returns a failure response.
     *
     * @param resultCode   The result code of the app function execution.
     * @param extras       The additional metadata data relevant to this function execution
     *                     response.
     * @param errorMessage The error message associated with the result, if any.
     */
    @NonNull
    @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
    public static ExecuteAppFunctionResponse newFailure(@ResultCode int resultCode,
                                                        @Nullable String errorMessage,
                                                        @Nullable Bundle extras) {
        if (resultCode == RESULT_OK) {
            throw new IllegalArgumentException("resultCode must not be RESULT_OK");
        }
        Bundle actualExtras = getActualExtras(extras);
        GenericDocumentWrapper emptyWrapper = new GenericDocumentWrapper(
                new GenericDocument.Builder<>("", "", "").build());
        return new ExecuteAppFunctionResponse(
                emptyWrapper, actualExtras, resultCode, errorMessage);
    }

    private static Bundle getActualExtras(@Nullable Bundle extras) {
        if (extras == null) {
            return Bundle.EMPTY;
        }
        return extras;
    }

    /**
     * Returns a generic document containing the return value of the executed function.
     *
@@ -250,64 +299,4 @@ public final class ExecuteAppFunctionResponse implements Parcelable {
    @Retention(RetentionPolicy.SOURCE)
    public @interface ResultCode {
    }

    /**
     * The builder for creating {@link ExecuteAppFunctionResponse} instances.
     */
    @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
    public static final class Builder {
        @NonNull
        private GenericDocument mResultDocument =
                new GenericDocument.Builder<>("", "", "").build();
        @NonNull
        private Bundle mExtras = Bundle.EMPTY;
        private int mResultCode;
        @Nullable
        private String mErrorMessage;

        /**
         * Creates a new builder for {@link ExecuteAppFunctionResponse}.
         */
        private Builder() {
        }

        /**
         * Creates a new builder for {@link ExecuteAppFunctionResponse} to build a success response
         * with a result code of {@link #RESULT_OK} and a resultDocument.
         */
        public Builder(@NonNull GenericDocument resultDocument) {
            Objects.requireNonNull(resultDocument);
            mResultDocument = resultDocument;
            mResultCode = RESULT_OK;
        }

        /**
         * Creates a new builder for {@link ExecuteAppFunctionResponse} to build an error response
         * with a result code and an error message.
         */
        public Builder(@ResultCode int resultCode,
                       @NonNull String errorMessage) {
            mResultCode = resultCode;
            mErrorMessage = Objects.requireNonNull(errorMessage);
        }

        /**
         * Sets the extras of the app function execution.
         */
        @NonNull
        public Builder setExtras(@NonNull Bundle extras) {
            mExtras = Objects.requireNonNull(extras);
            return this;
        }

        /**
         * Builds the {@link ExecuteAppFunctionResponse} instance.
         */
        @NonNull
        public ExecuteAppFunctionResponse build() {
            return new ExecuteAppFunctionResponse(
                    new GenericDocumentWrapper(mResultDocument),
                    mExtras, mResultCode, mErrorMessage);
        }
    }
}
+36 −32
Original line number Diff line number Diff line
@@ -94,36 +94,39 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
            targetUser = mCallerValidator.verifyTargetUserHandle(
                    requestInternal.getUserHandle(), validatedCallingPackage);
        } catch (SecurityException exception) {
            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse
                    .Builder(ExecuteAppFunctionResponse.RESULT_DENIED,
                    getExceptionMessage(exception)).build());
            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
                    .newFailure(ExecuteAppFunctionResponse.RESULT_DENIED,
                            exception.getMessage(),
                            /*extras=*/  null));
            return;
        }

        // TODO(b/354956319): Add and honor the new enterprise policies.
        if (mCallerValidator.isUserOrganizationManaged(targetUser)) {
            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder(
            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
                    ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
                    "Cannot run on a device with a device owner or from the managed profile."
            ).build());
                    "Cannot run on a device with a device owner or from the managed profile.",
                    /*extras=*/  null
            ));
            return;
        }

        String targetPackageName = requestInternal.getClientRequest().getTargetPackageName();
        if (TextUtils.isEmpty(targetPackageName)) {
            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder(
            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
                    ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT,
                    "Target package name cannot be empty."
            ).build());
                    "Target package name cannot be empty.",
                    /*extras=*/  null
            ));
            return;
        }

        if (!mCallerValidator.verifyCallerCanExecuteAppFunction(
                validatedCallingPackage, targetPackageName)) {
            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse
                    .Builder(ExecuteAppFunctionResponse.RESULT_DENIED,
                    "Caller does not have permission to execute the appfunction")
                    .build());
            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
                    .newFailure(ExecuteAppFunctionResponse.RESULT_DENIED,
                            "Caller does not have permission to execute the appfunction",
                            /*extras=*/  null));
            return;
        }

@@ -131,10 +134,11 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
                targetPackageName,
                targetUser);
        if (serviceIntent == null) {
            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder(
            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
                    ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
                    "Cannot find the target service."
            ).build());
                    "Cannot find the target service.",
                    /*extras=*/  null
            ));
            return;
        }
        bindAppFunctionServiceUnchecked(requestInternal, serviceIntent, targetUser,
@@ -171,9 +175,10 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
                                    }
                            );
                        } catch (Exception e) {
                            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse
                                    .Builder(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
                                    getExceptionMessage(e)).build());
                            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
                                    .newFailure(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
                                            e.getMessage(),
                                            /*extras=*/  null));
                            serviceUsageCompleteListener.onCompleted();
                        }
                    }
@@ -181,33 +186,32 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
                    @Override
                    public void onFailedToConnect() {
                        Slog.e(TAG, "Failed to connect to service");
                        safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse
                                .Builder(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
                                "Failed to connect to AppFunctionService").build());
                        safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
                                .newFailure(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
                                        "Failed to connect to AppFunctionService",
                                        /*extras=*/  null));
                    }

                    @Override
                    public void onTimedOut() {
                        Slog.e(TAG, "Timed out");
                        safeExecuteAppFunctionCallback.onResult(
                                new ExecuteAppFunctionResponse.Builder(
                                ExecuteAppFunctionResponse.newFailure(
                                        ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
                                        "Binding to AppFunctionService timed out."
                                ).build());
                                        "Binding to AppFunctionService timed out.",
                                        /*extras=*/  null
                                ));
                    }
                }
        );

        if (!bindServiceResult) {
            Slog.e(TAG, "Failed to bind to the AppFunctionService");
            safeExecuteAppFunctionCallback.onResult(new ExecuteAppFunctionResponse.Builder(
            safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
                    ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
                    "Failed to bind the AppFunctionService."
            ).build());
                    "Failed to bind the AppFunctionService.",
                    /*extras=*/  null
            ));
        }
    }

    private String getExceptionMessage(Exception exception) {
        return exception.getMessage() == null ? "" : exception.getMessage();
    }
}