• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.extensions.appfunctions;
18 
19 import static com.android.extensions.appfunctions.SidecarConverter.getPlatformAppFunctionException;
20 import static com.android.extensions.appfunctions.SidecarConverter.getPlatformExecuteAppFunctionResponse;
21 
22 import android.annotation.MainThread;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.SdkConstant;
26 import android.app.Service;
27 import android.content.Intent;
28 import android.os.Binder;
29 import android.os.CancellationSignal;
30 import android.os.IBinder;
31 import android.os.OutcomeReceiver;
32 
33 /**
34  * Abstract base class to provide app functions to the system.
35  *
36  * <p>Include the following in the manifest:
37  *
38  * <pre>
39  * {@literal
40  * <service android:name=".YourService"
41  *       android:permission="android.permission.BIND_APP_FUNCTION_SERVICE">
42  *    <intent-filter>
43  *      <action android:name="android.app.appfunctions.AppFunctionService" />
44  *    </intent-filter>
45  * </service>
46  * }
47  * </pre>
48  *
49  * <p>This class wraps {@link android.app.appfunctions.AppFunctionService} functionalities and
50  * exposes it here as a sidecar library (avoiding direct dependency on the platform API).
51  *
52  * @see AppFunctionManager
53  */
54 public abstract class AppFunctionService extends Service {
55     /**
56      * The permission to only allow system access to the functions through {@link
57      * AppFunctionManagerService}.
58      */
59     @NonNull
60     public static final String BIND_APP_FUNCTION_SERVICE =
61             "android.permission.BIND_APP_FUNCTION_SERVICE";
62 
63     /**
64      * The {@link Intent} that must be declared as handled by the service. To be supported, the
65      * service must also require the {@link BIND_APP_FUNCTION_SERVICE} permission so that other
66      * applications can not abuse it.
67      */
68     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
69     @NonNull
70     public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
71 
72     private final Binder mBinder =
73             android.app.appfunctions.AppFunctionService.createBinder(
74                     /* context= */ this,
75                     /* onExecuteFunction= */ (platformRequest,
76                             callingPackage,
77                             callingPackageSigningInfo,
78                             cancellationSignal,
79                             callback) -> {
80                         AppFunctionService.this.onExecuteFunction(
81                                 SidecarConverter.getSidecarExecuteAppFunctionRequest(
82                                         platformRequest),
83                                 callingPackage,
84                                 cancellationSignal,
85                                 new OutcomeReceiver<>() {
86                                     @Override
87                                     public void onResult(ExecuteAppFunctionResponse result) {
88                                         callback.onResult(
89                                                 getPlatformExecuteAppFunctionResponse(result));
90                                     }
91 
92                                     @Override
93                                     public void onError(AppFunctionException exception) {
94                                         callback.onError(
95                                                 getPlatformAppFunctionException(exception));
96                                     }
97                                 });
98                     });
99 
100     @NonNull
101     @Override
onBind(@ullable Intent intent)102     public final IBinder onBind(@Nullable Intent intent) {
103         return mBinder;
104     }
105 
106     /**
107      * Called by the system to execute a specific app function.
108      *
109      * <p>This method is the entry point for handling all app function requests in an app. When the
110      * system needs your AppFunctionService to perform a function, it will invoke this method.
111      *
112      * <p>Each function you've registered is identified by a unique identifier. This identifier
113      * doesn't need to be globally unique, but it must be unique within your app. For example, a
114      * function to order food could be identified as "orderFood". In most cases, this identifier is
115      * automatically generated by the AppFunctions SDK.
116      *
117      * <p>You can determine which function to execute by calling {@link
118      * ExecuteAppFunctionRequest#getFunctionIdentifier()}. This allows your service to route the
119      * incoming request to the appropriate logic for handling the specific function.
120      *
121      * <p>This method is always triggered in the main thread. You should run heavy tasks on a worker
122      * thread and dispatch the result with the given callback. You should always report back the
123      * result using the callback, no matter if the execution was successful or not.
124      *
125      * <p>This method also accepts a {@link CancellationSignal} that the app should listen to cancel
126      * the execution of function if requested by the system.
127      *
128      * @param request The function execution request.
129      * @param callingPackage The package name of the app that is requesting the execution.
130      * @param cancellationSignal A signal to cancel the execution.
131      * @param callback A callback to report back the result or error.
132      */
133     @MainThread
onExecuteFunction( @onNull ExecuteAppFunctionRequest request, @NonNull String callingPackage, @NonNull CancellationSignal cancellationSignal, @NonNull OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback)134     public abstract void onExecuteFunction(
135             @NonNull ExecuteAppFunctionRequest request,
136             @NonNull String callingPackage,
137             @NonNull CancellationSignal cancellationSignal,
138             @NonNull OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback);
139 }
140