1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.appfunctions; 18 19 import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; 20 21 import android.annotation.FlaggedApi; 22 import android.annotation.NonNull; 23 import android.app.appsearch.GenericDocument; 24 import android.os.Bundle; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import java.util.Objects; 29 30 /** 31 * The response to an app function execution. 32 * 33 * <p>The {@link ExecuteAppFunctionResponse#getResultDocument()} contains the function's return 34 * value as a GenericDocument. This can be converted back into a structured class using the 35 * AppFunction SDK. 36 * 37 * <p>The {@link ExecuteAppFunctionResponse#getExtras()} provides any extra metadata returned by the 38 * function. The AppFunction SDK can expose structured APIs by packing and unpacking this Bundle. 39 */ 40 @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) 41 public final class ExecuteAppFunctionResponse implements Parcelable { 42 @NonNull 43 public static final Creator<ExecuteAppFunctionResponse> CREATOR = 44 new Creator<ExecuteAppFunctionResponse>() { 45 @Override 46 public ExecuteAppFunctionResponse createFromParcel(Parcel parcel) { 47 GenericDocumentWrapper resultWrapper = 48 Objects.requireNonNull( 49 GenericDocumentWrapper.CREATOR.createFromParcel(parcel)); 50 Bundle extras = 51 Objects.requireNonNull( 52 parcel.readBundle(Bundle.class.getClassLoader())); 53 return new ExecuteAppFunctionResponse(resultWrapper.getValue(), extras); 54 } 55 56 @Override 57 public ExecuteAppFunctionResponse[] newArray(int size) { 58 return new ExecuteAppFunctionResponse[size]; 59 } 60 }; 61 62 /** 63 * The name of the property that stores the function return value within the {@code 64 * resultDocument}. 65 * 66 * <p>See {@link GenericDocument#getProperty(String)} for more information. 67 * 68 * <p>If the function returns {@code void} or throws an error, the {@code resultDocument} will 69 * be empty {@link GenericDocument}. 70 * 71 * <p>If the {@code resultDocument} is empty, {@link GenericDocument#getProperty(String)} will 72 * return {@code null}. 73 * 74 * <p>See {@link #getResultDocument} for more information on extracting the return value. 75 */ 76 public static final String PROPERTY_RETURN_VALUE = "androidAppfunctionsReturnValue"; 77 78 /** 79 * Returns the return value of the executed function. 80 * 81 * <p>The return value is stored in a {@link GenericDocument} with the key {@link 82 * #PROPERTY_RETURN_VALUE}. 83 * 84 * <p>See {@link #getResultDocument} for more information on extracting the return value. 85 */ 86 @NonNull private final GenericDocumentWrapper mResultDocumentWrapper; 87 88 /** Returns the additional metadata data relevant to this function execution response. */ 89 @NonNull private final Bundle mExtras; 90 91 /** 92 * @param resultDocument The return value of the executed function. 93 */ ExecuteAppFunctionResponse(@onNull GenericDocument resultDocument)94 public ExecuteAppFunctionResponse(@NonNull GenericDocument resultDocument) { 95 this(resultDocument, Bundle.EMPTY); 96 } 97 98 /** 99 * @param resultDocument The return value of the executed function. 100 * @param extras The additional metadata for this function execution response. 101 */ ExecuteAppFunctionResponse( @onNull GenericDocument resultDocument, @NonNull Bundle extras)102 public ExecuteAppFunctionResponse( 103 @NonNull GenericDocument resultDocument, @NonNull Bundle extras) { 104 mResultDocumentWrapper = new GenericDocumentWrapper(Objects.requireNonNull(resultDocument)); 105 mExtras = Objects.requireNonNull(extras); 106 } 107 108 /** 109 * Returns a generic document containing the return value of the executed function. 110 * 111 * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value. 112 * 113 * <p>Sample code for extracting the return value: 114 * 115 * <pre> 116 * GenericDocument resultDocument = response.getResultDocument(); 117 * Object returnValue = resultDocument.getProperty(PROPERTY_RETURN_VALUE); 118 * if (returnValue != null) { 119 * // Cast returnValue to expected type, or use {@link GenericDocument#getPropertyString}, 120 * // {@link GenericDocument#getPropertyLong} etc. 121 * // Do something with the returnValue 122 * } 123 * </pre> 124 * 125 * @see AppFunctionManager on how to determine the expected function return. 126 */ 127 @NonNull getResultDocument()128 public GenericDocument getResultDocument() { 129 return mResultDocumentWrapper.getValue(); 130 } 131 132 /** Returns the additional metadata for this function execution response. */ 133 @NonNull getExtras()134 public Bundle getExtras() { 135 return mExtras; 136 } 137 138 /** 139 * Returns the size of the response in bytes. 140 * 141 * @hide 142 */ getResponseDataSize()143 public int getResponseDataSize() { 144 return mResultDocumentWrapper.getDataSize() + mExtras.getSize(); 145 } 146 147 @Override describeContents()148 public int describeContents() { 149 return 0; 150 } 151 152 @Override writeToParcel(@onNull Parcel dest, int flags)153 public void writeToParcel(@NonNull Parcel dest, int flags) { 154 mResultDocumentWrapper.writeToParcel(dest, flags); 155 dest.writeBundle(mExtras); 156 } 157 } 158