• 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.ondevicepersonalization.services.serviceflow;
18 
19 import android.os.Bundle;
20 
21 import com.android.ondevicepersonalization.internal.util.LoggerFactory;
22 import com.android.ondevicepersonalization.services.OnDevicePersonalizationExecutors;
23 import com.android.ondevicepersonalization.services.process.IsolatedServiceInfo;
24 import com.android.ondevicepersonalization.services.process.ProcessRunner;
25 import com.android.ondevicepersonalization.services.process.ProcessRunnerFactory;
26 
27 import com.google.common.util.concurrent.FluentFuture;
28 import com.google.common.util.concurrent.Futures;
29 import com.google.common.util.concurrent.ListenableFuture;
30 import com.google.common.util.concurrent.ListeningExecutorService;
31 
32 /**
33  * Task object representing a service flow task.
34  */
35 public class ServiceFlowTask {
36 
37     private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger();
38     private static final String TAG = ServiceFlowTask.class.getSimpleName();
39 
40     private final ServiceFlowType mServiceFlowType;
41     private final ServiceFlow mServiceFlow;
42     private final ProcessRunner mProcessRunner;
43     private volatile boolean mIsCompleted;
44     private volatile Throwable mExecutionThrowable;
45 
46     private final ListeningExecutorService mExecutor =
47             OnDevicePersonalizationExecutors.getBackgroundExecutor();
48 
ServiceFlowTask(ServiceFlowType serviceFlowType, ServiceFlow serviceFlow)49     public ServiceFlowTask(ServiceFlowType serviceFlowType, ServiceFlow serviceFlow) {
50         mIsCompleted = false;
51         mServiceFlowType = serviceFlowType;
52         mServiceFlow = serviceFlow;
53         mProcessRunner = ProcessRunnerFactory.getProcessRunner();
54     }
55 
getServiceFlowType()56     public ServiceFlowType getServiceFlowType() {
57         return mServiceFlowType;
58     }
59 
getServiceFlow()60     public ServiceFlow getServiceFlow() {
61         return mServiceFlow;
62     }
63 
isCompleted()64     public boolean isCompleted() {
65         return mIsCompleted;
66     }
67 
getExeuctionThrowable()68     public Throwable getExeuctionThrowable() {
69         return mExecutionThrowable;
70     }
71 
72     /** Executes the given service flow. */
run()73     public void run() {
74         try {
75             boolean isServiceFlowReady = mServiceFlow.isServiceFlowReady();
76             if (mIsCompleted || !isServiceFlowReady) {
77                 sLogger.d(TAG + " skipped running %s, isCompleted: %s, isServiceFlowReady: %s",
78                         mServiceFlowType, mIsCompleted, isServiceFlowReady);
79                 return;
80             }
81 
82             ListenableFuture<IsolatedServiceInfo> loadServiceFuture =
83                     mProcessRunner.loadIsolatedService(
84                             mServiceFlowType.getTaskName(), mServiceFlow.getService());
85 
86             ListenableFuture<Bundle> runServiceFuture = FluentFuture.from(loadServiceFuture)
87                     .transformAsync(
88                             isolatedServiceInfo -> mProcessRunner
89                                     .runIsolatedService(
90                                             isolatedServiceInfo,
91                                             mServiceFlowType.getOperationCode(),
92                                             mServiceFlow.getServiceParams()),
93                             mExecutor);
94 
95             mServiceFlow.uploadServiceFlowMetrics(runServiceFuture);
96 
97             ListenableFuture<?> serviceFlowResultFuture =
98                     mServiceFlow.getServiceFlowResultFuture(runServiceFuture);
99 
100             mServiceFlow.returnResultThroughCallback(serviceFlowResultFuture);
101 
102             var unused =
103                     Futures.whenAllComplete(loadServiceFuture, serviceFlowResultFuture)
104                             .callAsync(
105                                     () -> {
106                                         mServiceFlow.cleanUpServiceParams();
107                                         ListenableFuture<Void> unloadServiceFuture =
108                                                 mProcessRunner.unloadIsolatedService(
109                                                         loadServiceFuture.get());
110                                         mIsCompleted = true;
111                                         return unloadServiceFuture;
112                                     }, mExecutor);
113         } catch (Throwable e) {
114             sLogger.e(e, TAG + ": ServiceFlowTask " + mServiceFlowType + " failed.");
115             mExecutionThrowable = e;
116         }
117     }
118 }
119