• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.federatedcompute;
18 
19 import static android.federatedcompute.common.ClientConstants.STATUS_SUCCESS;
20 
21 import android.app.Service;
22 import android.content.Intent;
23 import android.federatedcompute.aidl.IFederatedComputeCallback;
24 import android.federatedcompute.aidl.IResultHandlingService;
25 import android.federatedcompute.common.ExampleConsumption;
26 import android.federatedcompute.common.TrainingOptions;
27 import android.os.IBinder;
28 import android.os.RemoteException;
29 import android.util.Log;
30 
31 import java.util.List;
32 import java.util.function.Consumer;
33 
34 /**
35  * The abstract base class that client apps need to implement to handle training results.
36  *
37  * <p>The client app will add a {@code <service>} entry to their manifest so that FederatedCompute
38  * API can bind to the their implementation, like so:
39  *
40  * <pre>{@code
41  * <application>
42  *   <service android:enabled="true" android:exported="true" android:name=".YourServiceClass">
43  *     <intent-filter>
44  *       <action android:name="android.federatedcompute.COMPUTATION_RESULT" />
45  *       <data android:scheme="app" />
46  *     </intent-filter>
47  *   </service>
48  * </application>
49  * }</pre>
50  *
51  * @hide
52  */
53 public abstract class ResultHandlingService extends Service {
54     private static final String TAG = "ResultHandlingService";
55     private IBinder mIBinder;
56 
57     @Override
onCreate()58     public void onCreate() {
59         mIBinder = new ServiceBinder();
60     }
61 
62     @Override
onBind(Intent intent)63     public IBinder onBind(Intent intent) {
64         return mIBinder;
65     }
66 
67     private class ServiceBinder extends IResultHandlingService.Stub {
68         @Override
handleResult( TrainingOptions trainingOptions, boolean success, List<ExampleConsumption> exampleConsumptionList, IFederatedComputeCallback callback)69         public void handleResult(
70                 TrainingOptions trainingOptions,
71                 boolean success,
72                 List<ExampleConsumption> exampleConsumptionList,
73                 IFederatedComputeCallback callback) {
74             ResultHandlingService.this.handleResult(
75                     trainingOptions,
76                     success,
77                     exampleConsumptionList,
78                     new ResultHandlingCallback(callback));
79         }
80     }
81 
82     /** A callback for the user to communicate if the results handling is successful. */
83     private static final class ResultHandlingCallback implements Consumer<Integer> {
84         private final IFederatedComputeCallback mInternalCallback;
85 
86         /** Constructor for this */
ResultHandlingCallback(IFederatedComputeCallback internalCallback)87         ResultHandlingCallback(IFederatedComputeCallback internalCallback) {
88             this.mInternalCallback = internalCallback;
89         }
90 
91         /**
92          * Should be called when finished handling results in your {@link ResultHandlingService}
93          * implementation.
94          */
95         @Override
accept(Integer status)96         public void accept(Integer status) {
97             try {
98                 if (status == STATUS_SUCCESS) {
99                     mInternalCallback.onSuccess();
100                     return;
101                 }
102                 mInternalCallback.onFailure(status);
103             } catch (RemoteException e) {
104                 Log.w(TAG, "An error occurred when trying to communicate with FederatedCompute.");
105             }
106         }
107     }
108 
109     /**
110      * The client app needs to implement this method to handle results. After handling the results,
111      * the client app should signal FederatedCompute via the ResultHandlingCallback.
112      */
handleResult( TrainingOptions trainingOptions, boolean success, List<ExampleConsumption> exampleConsumptionList, Consumer<Integer> callback)113     public abstract void handleResult(
114             TrainingOptions trainingOptions,
115             boolean success,
116             List<ExampleConsumption> exampleConsumptionList,
117             Consumer<Integer> callback);
118 }
119