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 android.annotation.CallbackExecutor; 20 import android.annotation.NonNull; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.federatedcompute.aidl.IFederatedComputeCallback; 24 import android.federatedcompute.aidl.IFederatedComputeService; 25 import android.federatedcompute.common.ScheduleFederatedComputeRequest; 26 import android.os.OutcomeReceiver; 27 28 import com.android.federatedcompute.internal.util.AbstractServiceBinder; 29 import com.android.federatedcompute.internal.util.LogUtil; 30 31 import java.util.List; 32 import java.util.Objects; 33 import java.util.concurrent.Executor; 34 35 /** 36 * FederatedCompute Manager. 37 * 38 * @hide 39 */ 40 public final class FederatedComputeManager { 41 /** 42 * Constant that represents the service name for {@link FederatedComputeManager} to be used in 43 * {@link android.ondevicepersonalization.OnDevicePersonalizationFrameworkInitializer 44 * #registerServiceWrappers} 45 * 46 * @hide 47 */ 48 public static final String FEDERATED_COMPUTE_SERVICE = "federated_compute_service"; 49 50 private static final String TAG = FederatedComputeManager.class.getSimpleName(); 51 private static final String FEDERATED_COMPUTATION_SERVICE_INTENT_FILTER_NAME = 52 "android.federatedcompute.FederatedComputeService"; 53 private static final String FEDERATED_COMPUTATION_SERVICE_PACKAGE = 54 "com.android.federatedcompute.services"; 55 private static final String ALT_FEDERATED_COMPUTATION_SERVICE_PACKAGE = 56 "com.google.android.federatedcompute"; 57 58 private final Context mContext; 59 60 private final AbstractServiceBinder<IFederatedComputeService> mServiceBinder; 61 FederatedComputeManager(Context context)62 public FederatedComputeManager(Context context) { 63 this.mContext = context; 64 this.mServiceBinder = 65 AbstractServiceBinder.getServiceBinderByIntent( 66 context, 67 FEDERATED_COMPUTATION_SERVICE_INTENT_FILTER_NAME, 68 List.of( 69 FEDERATED_COMPUTATION_SERVICE_PACKAGE, 70 ALT_FEDERATED_COMPUTATION_SERVICE_PACKAGE), 71 IFederatedComputeService.Stub::asInterface); 72 } 73 74 /** 75 * Schedule FederatedCompute task. 76 * 77 * @hide 78 */ schedule( @onNull ScheduleFederatedComputeRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Object, Exception> callback)79 public void schedule( 80 @NonNull ScheduleFederatedComputeRequest request, 81 @NonNull @CallbackExecutor Executor executor, 82 @NonNull OutcomeReceiver<Object, Exception> callback) { 83 Objects.requireNonNull(request); 84 final IFederatedComputeService service = mServiceBinder.getService(executor); 85 try { 86 IFederatedComputeCallback federatedComputeCallback = 87 new IFederatedComputeCallback.Stub() { 88 @Override 89 public void onSuccess() { 90 LogUtil.d(TAG, ": schedule onSuccess() called"); 91 executor.execute(() -> callback.onResult(null)); 92 unbindFromService(); 93 } 94 95 @Override 96 public void onFailure(int errorCode) { 97 LogUtil.d( 98 TAG, 99 ": schedule onFailure() called with errorCode %d", 100 errorCode); 101 executor.execute( 102 () -> 103 callback.onError( 104 new FederatedComputeException(errorCode))); 105 unbindFromService(); 106 } 107 }; 108 service.schedule( 109 mContext.getPackageName(), 110 request.getTrainingOptions(), 111 federatedComputeCallback); 112 } catch (Exception e) { 113 LogUtil.e(TAG, e, "Exception when schedule federated job"); 114 executor.execute(() -> callback.onError(e)); 115 unbindFromService(); 116 } 117 } 118 119 /** 120 * Cancel FederatedCompute task. 121 * 122 * @hide 123 */ cancel( @onNull ComponentName ownerComponent, @NonNull String populationName, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Object, Exception> callback)124 public void cancel( 125 @NonNull ComponentName ownerComponent, 126 @NonNull String populationName, 127 @NonNull @CallbackExecutor Executor executor, 128 @NonNull OutcomeReceiver<Object, Exception> callback) { 129 Objects.requireNonNull(populationName); 130 final IFederatedComputeService service = mServiceBinder.getService(executor); 131 try { 132 IFederatedComputeCallback federatedComputeCallback = 133 new IFederatedComputeCallback.Stub() { 134 @Override 135 public void onSuccess() { 136 LogUtil.d(TAG, ": cancel onSuccess() called"); 137 executor.execute(() -> callback.onResult(null)); 138 unbindFromService(); 139 } 140 141 @Override 142 public void onFailure(int errorCode) { 143 LogUtil.d( 144 TAG, 145 ": cancel onFailure() called with errorCode %d", 146 errorCode); 147 executor.execute( 148 () -> 149 callback.onError( 150 new FederatedComputeException(errorCode))); 151 unbindFromService(); 152 } 153 }; 154 service.cancel(ownerComponent, populationName, federatedComputeCallback); 155 } catch (Exception e) { 156 LogUtil.e(TAG, e, "Exception when cancel federated job %s", populationName); 157 executor.execute(() -> callback.onError(e)); 158 unbindFromService(); 159 } 160 } 161 unbindFromService()162 public void unbindFromService() { 163 mServiceBinder.unbindFromService(); 164 } 165 } 166