xref: /aosp_15_r20/system/incremental_delivery/libdataloader/DataLoaderConnector.cpp (revision 9190c2a8bd3622b7aa9bd7bfe4b3aec77820f478)
1*9190c2a8SAndroid Build Coastguard Worker /*
2*9190c2a8SAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*9190c2a8SAndroid Build Coastguard Worker  *
4*9190c2a8SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*9190c2a8SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*9190c2a8SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*9190c2a8SAndroid Build Coastguard Worker  *
8*9190c2a8SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*9190c2a8SAndroid Build Coastguard Worker  *
10*9190c2a8SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*9190c2a8SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*9190c2a8SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9190c2a8SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*9190c2a8SAndroid Build Coastguard Worker  * limitations under the License.
15*9190c2a8SAndroid Build Coastguard Worker  */
16*9190c2a8SAndroid Build Coastguard Worker #define LOG_TAG "incfs-dataloaderconnector"
17*9190c2a8SAndroid Build Coastguard Worker 
18*9190c2a8SAndroid Build Coastguard Worker #include <android-base/logging.h>
19*9190c2a8SAndroid Build Coastguard Worker #include <fcntl.h>
20*9190c2a8SAndroid Build Coastguard Worker #include <nativehelper/JNIPlatformHelp.h>
21*9190c2a8SAndroid Build Coastguard Worker #include <nativehelper/scoped_local_ref.h>
22*9190c2a8SAndroid Build Coastguard Worker #include <nativehelper/scoped_utf_chars.h>
23*9190c2a8SAndroid Build Coastguard Worker #include <sys/stat.h>
24*9190c2a8SAndroid Build Coastguard Worker #include <utils/Looper.h>
25*9190c2a8SAndroid Build Coastguard Worker 
26*9190c2a8SAndroid Build Coastguard Worker #include <thread>
27*9190c2a8SAndroid Build Coastguard Worker #include <unordered_map>
28*9190c2a8SAndroid Build Coastguard Worker 
29*9190c2a8SAndroid Build Coastguard Worker #include "JNIHelpers.h"
30*9190c2a8SAndroid Build Coastguard Worker #include "ManagedDataLoader.h"
31*9190c2a8SAndroid Build Coastguard Worker #include "dataloader.h"
32*9190c2a8SAndroid Build Coastguard Worker #include "incfs.h"
33*9190c2a8SAndroid Build Coastguard Worker #include "path.h"
34*9190c2a8SAndroid Build Coastguard Worker 
35*9190c2a8SAndroid Build Coastguard Worker namespace {
36*9190c2a8SAndroid Build Coastguard Worker 
37*9190c2a8SAndroid Build Coastguard Worker using namespace std::literals;
38*9190c2a8SAndroid Build Coastguard Worker 
39*9190c2a8SAndroid Build Coastguard Worker using ReadInfo = android::dataloader::ReadInfo;
40*9190c2a8SAndroid Build Coastguard Worker using ReadInfoWithUid = android::dataloader::ReadInfoWithUid;
41*9190c2a8SAndroid Build Coastguard Worker 
42*9190c2a8SAndroid Build Coastguard Worker using FileId = android::incfs::FileId;
43*9190c2a8SAndroid Build Coastguard Worker using RawMetadata = android::incfs::RawMetadata;
44*9190c2a8SAndroid Build Coastguard Worker using UniqueControl = android::incfs::UniqueControl;
45*9190c2a8SAndroid Build Coastguard Worker 
46*9190c2a8SAndroid Build Coastguard Worker struct JniIds {
47*9190c2a8SAndroid Build Coastguard Worker     struct {
48*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_CREATED;
49*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_DESTROYED;
50*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_STARTED;
51*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_STOPPED;
52*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_IMAGE_READY;
53*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_IMAGE_NOT_READY;
54*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_UNAVAILABLE;
55*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_UNRECOVERABLE;
56*9190c2a8SAndroid Build Coastguard Worker 
57*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_TYPE_NONE;
58*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_TYPE_STREAMING;
59*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_TYPE_INCREMENTAL;
60*9190c2a8SAndroid Build Coastguard Worker 
61*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_LOCATION_DATA_APP;
62*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_LOCATION_MEDIA_OBB;
63*9190c2a8SAndroid Build Coastguard Worker         jint DATA_LOADER_LOCATION_MEDIA_DATA;
64*9190c2a8SAndroid Build Coastguard Worker     } constants;
65*9190c2a8SAndroid Build Coastguard Worker 
66*9190c2a8SAndroid Build Coastguard Worker     jmethodID parcelFileDescriptorGetFileDescriptor;
67*9190c2a8SAndroid Build Coastguard Worker 
68*9190c2a8SAndroid Build Coastguard Worker     jfieldID incremental;
69*9190c2a8SAndroid Build Coastguard Worker     jfieldID service;
70*9190c2a8SAndroid Build Coastguard Worker     jfieldID callback;
71*9190c2a8SAndroid Build Coastguard Worker 
72*9190c2a8SAndroid Build Coastguard Worker     jfieldID controlCmd;
73*9190c2a8SAndroid Build Coastguard Worker     jfieldID controlPendingReads;
74*9190c2a8SAndroid Build Coastguard Worker     jfieldID controlLog;
75*9190c2a8SAndroid Build Coastguard Worker     jfieldID controlBlocksWritten;
76*9190c2a8SAndroid Build Coastguard Worker 
77*9190c2a8SAndroid Build Coastguard Worker     jfieldID paramsType;
78*9190c2a8SAndroid Build Coastguard Worker     jfieldID paramsPackageName;
79*9190c2a8SAndroid Build Coastguard Worker     jfieldID paramsClassName;
80*9190c2a8SAndroid Build Coastguard Worker     jfieldID paramsArguments;
81*9190c2a8SAndroid Build Coastguard Worker 
82*9190c2a8SAndroid Build Coastguard Worker     jclass listener;
83*9190c2a8SAndroid Build Coastguard Worker     jmethodID listenerOnStatusChanged;
84*9190c2a8SAndroid Build Coastguard Worker 
85*9190c2a8SAndroid Build Coastguard Worker     jmethodID callbackControlWriteData;
86*9190c2a8SAndroid Build Coastguard Worker 
87*9190c2a8SAndroid Build Coastguard Worker     jmethodID listGet;
88*9190c2a8SAndroid Build Coastguard Worker     jmethodID listSize;
89*9190c2a8SAndroid Build Coastguard Worker 
90*9190c2a8SAndroid Build Coastguard Worker     jfieldID installationFileLocation;
91*9190c2a8SAndroid Build Coastguard Worker     jfieldID installationFileName;
92*9190c2a8SAndroid Build Coastguard Worker     jfieldID installationFileLengthBytes;
93*9190c2a8SAndroid Build Coastguard Worker     jfieldID installationFileMetadata;
94*9190c2a8SAndroid Build Coastguard Worker 
95*9190c2a8SAndroid Build Coastguard Worker     jmethodID incrementalServiceConnectorSetStorageParams;
96*9190c2a8SAndroid Build Coastguard Worker 
JniIds__anondbccd6f10111::JniIds97*9190c2a8SAndroid Build Coastguard Worker     JniIds(JNIEnv* env) {
98*9190c2a8SAndroid Build Coastguard Worker         listener = (jclass)env->NewGlobalRef(
99*9190c2a8SAndroid Build Coastguard Worker                 FindClassOrDie(env, "android/content/pm/IDataLoaderStatusListener"));
100*9190c2a8SAndroid Build Coastguard Worker         listenerOnStatusChanged = GetMethodIDOrDie(env, listener, "onStatusChanged", "(II)V");
101*9190c2a8SAndroid Build Coastguard Worker 
102*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_CREATED =
103*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_CREATED");
104*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_DESTROYED =
105*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_DESTROYED");
106*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_STARTED =
107*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_STARTED");
108*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_STOPPED =
109*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_STOPPED");
110*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_IMAGE_READY =
111*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_IMAGE_READY");
112*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_IMAGE_NOT_READY =
113*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_IMAGE_NOT_READY");
114*9190c2a8SAndroid Build Coastguard Worker 
115*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_UNAVAILABLE =
116*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_UNAVAILABLE");
117*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_UNRECOVERABLE =
118*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, listener, "DATA_LOADER_UNRECOVERABLE");
119*9190c2a8SAndroid Build Coastguard Worker 
120*9190c2a8SAndroid Build Coastguard Worker         auto packageInstaller = (jclass)FindClassOrDie(env, "android/content/pm/PackageInstaller");
121*9190c2a8SAndroid Build Coastguard Worker 
122*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_TYPE_NONE =
123*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, packageInstaller, "DATA_LOADER_TYPE_NONE");
124*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_TYPE_STREAMING =
125*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, packageInstaller, "DATA_LOADER_TYPE_STREAMING");
126*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_TYPE_INCREMENTAL =
127*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, packageInstaller, "DATA_LOADER_TYPE_INCREMENTAL");
128*9190c2a8SAndroid Build Coastguard Worker 
129*9190c2a8SAndroid Build Coastguard Worker         CHECK(constants.DATA_LOADER_TYPE_NONE == DATA_LOADER_TYPE_NONE);
130*9190c2a8SAndroid Build Coastguard Worker         CHECK(constants.DATA_LOADER_TYPE_STREAMING == DATA_LOADER_TYPE_STREAMING);
131*9190c2a8SAndroid Build Coastguard Worker         CHECK(constants.DATA_LOADER_TYPE_INCREMENTAL == DATA_LOADER_TYPE_INCREMENTAL);
132*9190c2a8SAndroid Build Coastguard Worker 
133*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_LOCATION_DATA_APP =
134*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, packageInstaller, "LOCATION_DATA_APP");
135*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_LOCATION_MEDIA_OBB =
136*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, packageInstaller, "LOCATION_MEDIA_OBB");
137*9190c2a8SAndroid Build Coastguard Worker         constants.DATA_LOADER_LOCATION_MEDIA_DATA =
138*9190c2a8SAndroid Build Coastguard Worker                 GetStaticIntFieldValueOrDie(env, packageInstaller, "LOCATION_MEDIA_DATA");
139*9190c2a8SAndroid Build Coastguard Worker 
140*9190c2a8SAndroid Build Coastguard Worker         CHECK(constants.DATA_LOADER_LOCATION_DATA_APP == DATA_LOADER_LOCATION_DATA_APP);
141*9190c2a8SAndroid Build Coastguard Worker         CHECK(constants.DATA_LOADER_LOCATION_MEDIA_OBB == DATA_LOADER_LOCATION_MEDIA_OBB);
142*9190c2a8SAndroid Build Coastguard Worker         CHECK(constants.DATA_LOADER_LOCATION_MEDIA_DATA == DATA_LOADER_LOCATION_MEDIA_DATA);
143*9190c2a8SAndroid Build Coastguard Worker 
144*9190c2a8SAndroid Build Coastguard Worker         auto parcelFileDescriptor = FindClassOrDie(env, "android/os/ParcelFileDescriptor");
145*9190c2a8SAndroid Build Coastguard Worker         parcelFileDescriptorGetFileDescriptor =
146*9190c2a8SAndroid Build Coastguard Worker                 GetMethodIDOrDie(env, parcelFileDescriptor, "getFileDescriptor",
147*9190c2a8SAndroid Build Coastguard Worker                                  "()Ljava/io/FileDescriptor;");
148*9190c2a8SAndroid Build Coastguard Worker 
149*9190c2a8SAndroid Build Coastguard Worker         auto control = FindClassOrDie(env, "android/content/pm/FileSystemControlParcel");
150*9190c2a8SAndroid Build Coastguard Worker         incremental =
151*9190c2a8SAndroid Build Coastguard Worker                 GetFieldIDOrDie(env, control, "incremental",
152*9190c2a8SAndroid Build Coastguard Worker                                 "Landroid/os/incremental/IncrementalFileSystemControlParcel;");
153*9190c2a8SAndroid Build Coastguard Worker         service = GetFieldIDOrDie(env, control, "service",
154*9190c2a8SAndroid Build Coastguard Worker                                   "Landroid/os/incremental/IIncrementalServiceConnector;");
155*9190c2a8SAndroid Build Coastguard Worker         callback =
156*9190c2a8SAndroid Build Coastguard Worker                 GetFieldIDOrDie(env, control, "callback",
157*9190c2a8SAndroid Build Coastguard Worker                                 "Landroid/content/pm/IPackageInstallerSessionFileSystemConnector;");
158*9190c2a8SAndroid Build Coastguard Worker 
159*9190c2a8SAndroid Build Coastguard Worker         auto incControl =
160*9190c2a8SAndroid Build Coastguard Worker                 FindClassOrDie(env, "android/os/incremental/IncrementalFileSystemControlParcel");
161*9190c2a8SAndroid Build Coastguard Worker         controlCmd = GetFieldIDOrDie(env, incControl, "cmd", "Landroid/os/ParcelFileDescriptor;");
162*9190c2a8SAndroid Build Coastguard Worker         controlPendingReads = GetFieldIDOrDie(env, incControl, "pendingReads",
163*9190c2a8SAndroid Build Coastguard Worker                                               "Landroid/os/ParcelFileDescriptor;");
164*9190c2a8SAndroid Build Coastguard Worker         controlLog = GetFieldIDOrDie(env, incControl, "log", "Landroid/os/ParcelFileDescriptor;");
165*9190c2a8SAndroid Build Coastguard Worker         controlBlocksWritten = GetFieldIDOrDie(env, incControl, "blocksWritten",
166*9190c2a8SAndroid Build Coastguard Worker                                                "Landroid/os/ParcelFileDescriptor;");
167*9190c2a8SAndroid Build Coastguard Worker 
168*9190c2a8SAndroid Build Coastguard Worker         auto params = FindClassOrDie(env, "android/content/pm/DataLoaderParamsParcel");
169*9190c2a8SAndroid Build Coastguard Worker         paramsType = GetFieldIDOrDie(env, params, "type", "I");
170*9190c2a8SAndroid Build Coastguard Worker         paramsPackageName = GetFieldIDOrDie(env, params, "packageName", "Ljava/lang/String;");
171*9190c2a8SAndroid Build Coastguard Worker         paramsClassName = GetFieldIDOrDie(env, params, "className", "Ljava/lang/String;");
172*9190c2a8SAndroid Build Coastguard Worker         paramsArguments = GetFieldIDOrDie(env, params, "arguments", "Ljava/lang/String;");
173*9190c2a8SAndroid Build Coastguard Worker 
174*9190c2a8SAndroid Build Coastguard Worker         auto callbackControl =
175*9190c2a8SAndroid Build Coastguard Worker                 FindClassOrDie(env,
176*9190c2a8SAndroid Build Coastguard Worker                                "android/content/pm/IPackageInstallerSessionFileSystemConnector");
177*9190c2a8SAndroid Build Coastguard Worker         callbackControlWriteData =
178*9190c2a8SAndroid Build Coastguard Worker                 GetMethodIDOrDie(env, callbackControl, "writeData",
179*9190c2a8SAndroid Build Coastguard Worker                                  "(Ljava/lang/String;JJLandroid/os/ParcelFileDescriptor;)V");
180*9190c2a8SAndroid Build Coastguard Worker 
181*9190c2a8SAndroid Build Coastguard Worker         auto list = (jclass)FindClassOrDie(env, "java/util/List");
182*9190c2a8SAndroid Build Coastguard Worker         listGet = GetMethodIDOrDie(env, list, "get", "(I)Ljava/lang/Object;");
183*9190c2a8SAndroid Build Coastguard Worker         listSize = GetMethodIDOrDie(env, list, "size", "()I");
184*9190c2a8SAndroid Build Coastguard Worker 
185*9190c2a8SAndroid Build Coastguard Worker         auto installationFileParcel =
186*9190c2a8SAndroid Build Coastguard Worker                 (jclass)FindClassOrDie(env, "android/content/pm/InstallationFileParcel");
187*9190c2a8SAndroid Build Coastguard Worker         installationFileLocation = GetFieldIDOrDie(env, installationFileParcel, "location", "I");
188*9190c2a8SAndroid Build Coastguard Worker         installationFileName =
189*9190c2a8SAndroid Build Coastguard Worker                 GetFieldIDOrDie(env, installationFileParcel, "name", "Ljava/lang/String;");
190*9190c2a8SAndroid Build Coastguard Worker         installationFileLengthBytes = GetFieldIDOrDie(env, installationFileParcel, "size", "J");
191*9190c2a8SAndroid Build Coastguard Worker         installationFileMetadata = GetFieldIDOrDie(env, installationFileParcel, "metadata", "[B");
192*9190c2a8SAndroid Build Coastguard Worker 
193*9190c2a8SAndroid Build Coastguard Worker         auto incrementalServiceConnector =
194*9190c2a8SAndroid Build Coastguard Worker                 FindClassOrDie(env, "android/os/incremental/IIncrementalServiceConnector");
195*9190c2a8SAndroid Build Coastguard Worker         incrementalServiceConnectorSetStorageParams =
196*9190c2a8SAndroid Build Coastguard Worker                 GetMethodIDOrDie(env, incrementalServiceConnector, "setStorageParams", "(Z)I");
197*9190c2a8SAndroid Build Coastguard Worker     }
198*9190c2a8SAndroid Build Coastguard Worker };
199*9190c2a8SAndroid Build Coastguard Worker 
getJavaVM(JNIEnv * env)200*9190c2a8SAndroid Build Coastguard Worker JavaVM* getJavaVM(JNIEnv* env) {
201*9190c2a8SAndroid Build Coastguard Worker     CHECK(env);
202*9190c2a8SAndroid Build Coastguard Worker     JavaVM* jvm = nullptr;
203*9190c2a8SAndroid Build Coastguard Worker     env->GetJavaVM(&jvm);
204*9190c2a8SAndroid Build Coastguard Worker     CHECK(jvm);
205*9190c2a8SAndroid Build Coastguard Worker     return jvm;
206*9190c2a8SAndroid Build Coastguard Worker }
207*9190c2a8SAndroid Build Coastguard Worker 
jniIds(JNIEnv * env)208*9190c2a8SAndroid Build Coastguard Worker const JniIds& jniIds(JNIEnv* env) {
209*9190c2a8SAndroid Build Coastguard Worker     static const JniIds ids(env);
210*9190c2a8SAndroid Build Coastguard Worker     return ids;
211*9190c2a8SAndroid Build Coastguard Worker }
212*9190c2a8SAndroid Build Coastguard Worker 
checkAndClearJavaException(JNIEnv * env,std::string_view method)213*9190c2a8SAndroid Build Coastguard Worker bool checkAndClearJavaException(JNIEnv* env, std::string_view method) {
214*9190c2a8SAndroid Build Coastguard Worker     if (!env->ExceptionCheck()) {
215*9190c2a8SAndroid Build Coastguard Worker         return false;
216*9190c2a8SAndroid Build Coastguard Worker     }
217*9190c2a8SAndroid Build Coastguard Worker 
218*9190c2a8SAndroid Build Coastguard Worker     LOG(ERROR) << "Java exception during DataLoader::" << method;
219*9190c2a8SAndroid Build Coastguard Worker     env->ExceptionDescribe();
220*9190c2a8SAndroid Build Coastguard Worker     env->ExceptionClear();
221*9190c2a8SAndroid Build Coastguard Worker     return true;
222*9190c2a8SAndroid Build Coastguard Worker }
223*9190c2a8SAndroid Build Coastguard Worker 
reportStatusViaCallback(JNIEnv * env,jobject listener,jint storageId,jint status)224*9190c2a8SAndroid Build Coastguard Worker bool reportStatusViaCallback(JNIEnv* env, jobject listener, jint storageId, jint status) {
225*9190c2a8SAndroid Build Coastguard Worker     if (listener == nullptr) {
226*9190c2a8SAndroid Build Coastguard Worker         ALOGE("No listener object to talk to IncrementalService. "
227*9190c2a8SAndroid Build Coastguard Worker               "DataLoaderId=%d, "
228*9190c2a8SAndroid Build Coastguard Worker               "status=%d",
229*9190c2a8SAndroid Build Coastguard Worker               storageId, status);
230*9190c2a8SAndroid Build Coastguard Worker         return false;
231*9190c2a8SAndroid Build Coastguard Worker     }
232*9190c2a8SAndroid Build Coastguard Worker 
233*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
234*9190c2a8SAndroid Build Coastguard Worker 
235*9190c2a8SAndroid Build Coastguard Worker     env->CallVoidMethod(listener, jni.listenerOnStatusChanged, storageId, status);
236*9190c2a8SAndroid Build Coastguard Worker     ALOGI("Reported status back to IncrementalService. DataLoaderId=%d, "
237*9190c2a8SAndroid Build Coastguard Worker           "status=%d",
238*9190c2a8SAndroid Build Coastguard Worker           storageId, status);
239*9190c2a8SAndroid Build Coastguard Worker 
240*9190c2a8SAndroid Build Coastguard Worker     return true;
241*9190c2a8SAndroid Build Coastguard Worker }
242*9190c2a8SAndroid Build Coastguard Worker 
243*9190c2a8SAndroid Build Coastguard Worker class DataLoaderConnector;
244*9190c2a8SAndroid Build Coastguard Worker using DataLoaderConnectorPtr = std::shared_ptr<DataLoaderConnector>;
245*9190c2a8SAndroid Build Coastguard Worker using DataLoaderConnectorsMap = std::unordered_map<int, DataLoaderConnectorPtr>;
246*9190c2a8SAndroid Build Coastguard Worker 
247*9190c2a8SAndroid Build Coastguard Worker struct Globals {
Globals__anondbccd6f10111::Globals248*9190c2a8SAndroid Build Coastguard Worker     Globals() { managedDataLoaderFactory = new android::dataloader::ManagedDataLoaderFactory(); }
249*9190c2a8SAndroid Build Coastguard Worker 
250*9190c2a8SAndroid Build Coastguard Worker     DataLoaderFactory* managedDataLoaderFactory = nullptr;
251*9190c2a8SAndroid Build Coastguard Worker     DataLoaderFactory* legacyDataLoaderFactory = nullptr;
252*9190c2a8SAndroid Build Coastguard Worker     DataLoaderFactory* dataLoaderFactory = nullptr;
253*9190c2a8SAndroid Build Coastguard Worker 
254*9190c2a8SAndroid Build Coastguard Worker     std::mutex dataLoaderConnectorsLock;
255*9190c2a8SAndroid Build Coastguard Worker     // id->DataLoader map
256*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnectorsMap dataLoaderConnectors GUARDED_BY(dataLoaderConnectorsLock);
257*9190c2a8SAndroid Build Coastguard Worker 
258*9190c2a8SAndroid Build Coastguard Worker     std::atomic_bool stopped;
259*9190c2a8SAndroid Build Coastguard Worker     std::thread pendingReadsLooperThread;
260*9190c2a8SAndroid Build Coastguard Worker     std::thread logLooperThread;
261*9190c2a8SAndroid Build Coastguard Worker     std::vector<ReadInfo> pendingReads;
262*9190c2a8SAndroid Build Coastguard Worker     std::vector<ReadInfo> pageReads;
263*9190c2a8SAndroid Build Coastguard Worker     std::vector<ReadInfoWithUid> pendingReadsWithUid;
264*9190c2a8SAndroid Build Coastguard Worker     std::vector<ReadInfoWithUid> pageReadsWithUid;
265*9190c2a8SAndroid Build Coastguard Worker };
266*9190c2a8SAndroid Build Coastguard Worker 
globals()267*9190c2a8SAndroid Build Coastguard Worker static Globals& globals() {
268*9190c2a8SAndroid Build Coastguard Worker     static Globals globals;
269*9190c2a8SAndroid Build Coastguard Worker     return globals;
270*9190c2a8SAndroid Build Coastguard Worker }
271*9190c2a8SAndroid Build Coastguard Worker 
272*9190c2a8SAndroid Build Coastguard Worker struct IncFsLooper : public android::Looper {
IncFsLooper__anondbccd6f10111::IncFsLooper273*9190c2a8SAndroid Build Coastguard Worker     IncFsLooper() : Looper(/*allowNonCallbacks=*/false) {}
~IncFsLooper__anondbccd6f10111::IncFsLooper274*9190c2a8SAndroid Build Coastguard Worker     ~IncFsLooper() {}
275*9190c2a8SAndroid Build Coastguard Worker };
276*9190c2a8SAndroid Build Coastguard Worker 
pendingReadsLooper()277*9190c2a8SAndroid Build Coastguard Worker static android::Looper& pendingReadsLooper() {
278*9190c2a8SAndroid Build Coastguard Worker     static IncFsLooper pendingReadsLooper;
279*9190c2a8SAndroid Build Coastguard Worker     return pendingReadsLooper;
280*9190c2a8SAndroid Build Coastguard Worker }
281*9190c2a8SAndroid Build Coastguard Worker 
logLooper()282*9190c2a8SAndroid Build Coastguard Worker static android::Looper& logLooper() {
283*9190c2a8SAndroid Build Coastguard Worker     static IncFsLooper logLooper;
284*9190c2a8SAndroid Build Coastguard Worker     return logLooper;
285*9190c2a8SAndroid Build Coastguard Worker }
286*9190c2a8SAndroid Build Coastguard Worker 
287*9190c2a8SAndroid Build Coastguard Worker struct DataLoaderParamsPair {
288*9190c2a8SAndroid Build Coastguard Worker     static DataLoaderParamsPair createFromManaged(JNIEnv* env, jobject params);
289*9190c2a8SAndroid Build Coastguard Worker 
dataLoaderParams__anondbccd6f10111::DataLoaderParamsPair290*9190c2a8SAndroid Build Coastguard Worker     const android::dataloader::DataLoaderParams& dataLoaderParams() const {
291*9190c2a8SAndroid Build Coastguard Worker         return mDataLoaderParams;
292*9190c2a8SAndroid Build Coastguard Worker     }
ndkDataLoaderParams__anondbccd6f10111::DataLoaderParamsPair293*9190c2a8SAndroid Build Coastguard Worker     const ::DataLoaderParams& ndkDataLoaderParams() const { return mNDKDataLoaderParams; }
294*9190c2a8SAndroid Build Coastguard Worker 
295*9190c2a8SAndroid Build Coastguard Worker private:
296*9190c2a8SAndroid Build Coastguard Worker     DataLoaderParamsPair(android::dataloader::DataLoaderParams&& dataLoaderParams);
297*9190c2a8SAndroid Build Coastguard Worker 
298*9190c2a8SAndroid Build Coastguard Worker     android::dataloader::DataLoaderParams mDataLoaderParams;
299*9190c2a8SAndroid Build Coastguard Worker     ::DataLoaderParams mNDKDataLoaderParams;
300*9190c2a8SAndroid Build Coastguard Worker };
301*9190c2a8SAndroid Build Coastguard Worker 
302*9190c2a8SAndroid Build Coastguard Worker static constexpr auto kPendingReadsBufferSize = 256;
303*9190c2a8SAndroid Build Coastguard Worker 
304*9190c2a8SAndroid Build Coastguard Worker class DataLoaderConnector : public android::dataloader::FilesystemConnector,
305*9190c2a8SAndroid Build Coastguard Worker                             public android::dataloader::StatusListener {
306*9190c2a8SAndroid Build Coastguard Worker public:
DataLoaderConnector(JNIEnv * env,jobject service,jint storageId,UniqueControl control,jobject serviceConnector,jobject callbackControl,jobject listener)307*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnector(JNIEnv* env, jobject service, jint storageId, UniqueControl control,
308*9190c2a8SAndroid Build Coastguard Worker                         jobject serviceConnector, jobject callbackControl, jobject listener)
309*9190c2a8SAndroid Build Coastguard Worker           : mJvm(getJavaVM(env)),
310*9190c2a8SAndroid Build Coastguard Worker             mService(env->NewGlobalRef(service)),
311*9190c2a8SAndroid Build Coastguard Worker             mServiceConnector(env->NewGlobalRef(serviceConnector)),
312*9190c2a8SAndroid Build Coastguard Worker             mCallbackControl(env->NewGlobalRef(callbackControl)),
313*9190c2a8SAndroid Build Coastguard Worker             mListener(env->NewGlobalRef(listener)),
314*9190c2a8SAndroid Build Coastguard Worker             mStorageId(storageId),
315*9190c2a8SAndroid Build Coastguard Worker             mControl(std::move(control)) {
316*9190c2a8SAndroid Build Coastguard Worker         CHECK(mJvm != nullptr);
317*9190c2a8SAndroid Build Coastguard Worker     }
318*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnector(const DataLoaderConnector&) = delete;
319*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnector(const DataLoaderConnector&&) = delete;
~DataLoaderConnector()320*9190c2a8SAndroid Build Coastguard Worker     virtual ~DataLoaderConnector() {
321*9190c2a8SAndroid Build Coastguard Worker         if (mDataLoader && mDataLoader->onDestroy) {
322*9190c2a8SAndroid Build Coastguard Worker             mDataLoader->onDestroy(mDataLoader);
323*9190c2a8SAndroid Build Coastguard Worker             checkAndClearJavaException(__func__);
324*9190c2a8SAndroid Build Coastguard Worker         }
325*9190c2a8SAndroid Build Coastguard Worker         mDataLoader = nullptr;
326*9190c2a8SAndroid Build Coastguard Worker 
327*9190c2a8SAndroid Build Coastguard Worker         JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
328*9190c2a8SAndroid Build Coastguard Worker 
329*9190c2a8SAndroid Build Coastguard Worker         const auto& jni = jniIds(env);
330*9190c2a8SAndroid Build Coastguard Worker         reportStatusViaCallback(env, mListener, mStorageId, jni.constants.DATA_LOADER_DESTROYED);
331*9190c2a8SAndroid Build Coastguard Worker 
332*9190c2a8SAndroid Build Coastguard Worker         env->DeleteGlobalRef(mService);
333*9190c2a8SAndroid Build Coastguard Worker         env->DeleteGlobalRef(mServiceConnector);
334*9190c2a8SAndroid Build Coastguard Worker         env->DeleteGlobalRef(mCallbackControl);
335*9190c2a8SAndroid Build Coastguard Worker         env->DeleteGlobalRef(mListener);
336*9190c2a8SAndroid Build Coastguard Worker     } // to avoid delete-non-virtual-dtor
337*9190c2a8SAndroid Build Coastguard Worker 
tryFactory(DataLoaderFactory * factory,bool withFeatures,const DataLoaderParamsPair & params,jobject managedParams)338*9190c2a8SAndroid Build Coastguard Worker     bool tryFactory(DataLoaderFactory* factory, bool withFeatures,
339*9190c2a8SAndroid Build Coastguard Worker                     const DataLoaderParamsPair& params, jobject managedParams) {
340*9190c2a8SAndroid Build Coastguard Worker         if (!factory) {
341*9190c2a8SAndroid Build Coastguard Worker             return true;
342*9190c2a8SAndroid Build Coastguard Worker         }
343*9190c2a8SAndroid Build Coastguard Worker 
344*9190c2a8SAndroid Build Coastguard Worker         // Let's try the non-default first.
345*9190c2a8SAndroid Build Coastguard Worker         mDataLoader = factory->onCreate(factory, &params.ndkDataLoaderParams(), this, this, mJvm,
346*9190c2a8SAndroid Build Coastguard Worker                                         mService, managedParams);
347*9190c2a8SAndroid Build Coastguard Worker         if (checkAndClearJavaException(__func__)) {
348*9190c2a8SAndroid Build Coastguard Worker             return false;
349*9190c2a8SAndroid Build Coastguard Worker         }
350*9190c2a8SAndroid Build Coastguard Worker         if (!mDataLoader) {
351*9190c2a8SAndroid Build Coastguard Worker             return true;
352*9190c2a8SAndroid Build Coastguard Worker         }
353*9190c2a8SAndroid Build Coastguard Worker 
354*9190c2a8SAndroid Build Coastguard Worker         mDataLoaderFeatures = withFeatures && mDataLoader->getFeatures
355*9190c2a8SAndroid Build Coastguard Worker                 ? mDataLoader->getFeatures(mDataLoader)
356*9190c2a8SAndroid Build Coastguard Worker                 : DATA_LOADER_FEATURE_NONE;
357*9190c2a8SAndroid Build Coastguard Worker         if (mDataLoaderFeatures & DATA_LOADER_FEATURE_UID) {
358*9190c2a8SAndroid Build Coastguard Worker             ALOGE("DataLoader supports UID");
359*9190c2a8SAndroid Build Coastguard Worker             CHECK(mDataLoader->onPageReadsWithUid);
360*9190c2a8SAndroid Build Coastguard Worker             CHECK(mDataLoader->onPendingReadsWithUid);
361*9190c2a8SAndroid Build Coastguard Worker         }
362*9190c2a8SAndroid Build Coastguard Worker         return true;
363*9190c2a8SAndroid Build Coastguard Worker     }
364*9190c2a8SAndroid Build Coastguard Worker 
onCreate(const DataLoaderParamsPair & params,jobject managedParams)365*9190c2a8SAndroid Build Coastguard Worker     bool onCreate(const DataLoaderParamsPair& params, jobject managedParams) {
366*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader == nullptr);
367*9190c2a8SAndroid Build Coastguard Worker 
368*9190c2a8SAndroid Build Coastguard Worker         if (!mDataLoader &&
369*9190c2a8SAndroid Build Coastguard Worker             !tryFactory(globals().dataLoaderFactory, /*withFeatures=*/true, params,
370*9190c2a8SAndroid Build Coastguard Worker                         managedParams)) {
371*9190c2a8SAndroid Build Coastguard Worker             return false;
372*9190c2a8SAndroid Build Coastguard Worker         }
373*9190c2a8SAndroid Build Coastguard Worker         if (!mDataLoader &&
374*9190c2a8SAndroid Build Coastguard Worker             !tryFactory(globals().legacyDataLoaderFactory, /*withFeatures=*/false, params,
375*9190c2a8SAndroid Build Coastguard Worker                         managedParams)) {
376*9190c2a8SAndroid Build Coastguard Worker             return false;
377*9190c2a8SAndroid Build Coastguard Worker         }
378*9190c2a8SAndroid Build Coastguard Worker         if (!mDataLoader &&
379*9190c2a8SAndroid Build Coastguard Worker             !tryFactory(globals().managedDataLoaderFactory, /*withFeatures=*/false, params,
380*9190c2a8SAndroid Build Coastguard Worker                         managedParams)) {
381*9190c2a8SAndroid Build Coastguard Worker             return false;
382*9190c2a8SAndroid Build Coastguard Worker         }
383*9190c2a8SAndroid Build Coastguard Worker         if (!mDataLoader) {
384*9190c2a8SAndroid Build Coastguard Worker             return false;
385*9190c2a8SAndroid Build Coastguard Worker         }
386*9190c2a8SAndroid Build Coastguard Worker 
387*9190c2a8SAndroid Build Coastguard Worker         return true;
388*9190c2a8SAndroid Build Coastguard Worker     }
onStart()389*9190c2a8SAndroid Build Coastguard Worker     bool onStart() {
390*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
391*9190c2a8SAndroid Build Coastguard Worker         bool result = !mDataLoader->onStart || mDataLoader->onStart(mDataLoader);
392*9190c2a8SAndroid Build Coastguard Worker         if (checkAndClearJavaException(__func__)) {
393*9190c2a8SAndroid Build Coastguard Worker             result = false;
394*9190c2a8SAndroid Build Coastguard Worker         }
395*9190c2a8SAndroid Build Coastguard Worker         mRunning = result;
396*9190c2a8SAndroid Build Coastguard Worker         return result;
397*9190c2a8SAndroid Build Coastguard Worker     }
onStop()398*9190c2a8SAndroid Build Coastguard Worker     void onStop() {
399*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
400*9190c2a8SAndroid Build Coastguard Worker 
401*9190c2a8SAndroid Build Coastguard Worker         // Stopping both loopers and waiting for them to exit - we should be able to acquire/release
402*9190c2a8SAndroid Build Coastguard Worker         // both mutexes.
403*9190c2a8SAndroid Build Coastguard Worker         mRunning = false;
404*9190c2a8SAndroid Build Coastguard Worker         (void)std::lock_guard{mPendingReadsLooperBusy}; // NOLINT
405*9190c2a8SAndroid Build Coastguard Worker         (void)std::lock_guard{mLogLooperBusy};          // NOLINT
406*9190c2a8SAndroid Build Coastguard Worker 
407*9190c2a8SAndroid Build Coastguard Worker         if (mDataLoader->onStop) {
408*9190c2a8SAndroid Build Coastguard Worker             mDataLoader->onStop(mDataLoader);
409*9190c2a8SAndroid Build Coastguard Worker         }
410*9190c2a8SAndroid Build Coastguard Worker         checkAndClearJavaException(__func__);
411*9190c2a8SAndroid Build Coastguard Worker     }
412*9190c2a8SAndroid Build Coastguard Worker 
onPrepareImage(const android::dataloader::DataLoaderInstallationFiles & addedFiles)413*9190c2a8SAndroid Build Coastguard Worker     bool onPrepareImage(const android::dataloader::DataLoaderInstallationFiles& addedFiles) {
414*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
415*9190c2a8SAndroid Build Coastguard Worker         bool result = !mDataLoader->onPrepareImage ||
416*9190c2a8SAndroid Build Coastguard Worker                 mDataLoader->onPrepareImage(mDataLoader, addedFiles.data(), addedFiles.size());
417*9190c2a8SAndroid Build Coastguard Worker         return result;
418*9190c2a8SAndroid Build Coastguard Worker     }
419*9190c2a8SAndroid Build Coastguard Worker 
420*9190c2a8SAndroid Build Coastguard Worker     template <class ReadInfoType>
onPendingReadsLooperEvent(std::vector<ReadInfoType> & pendingReads)421*9190c2a8SAndroid Build Coastguard Worker     int onPendingReadsLooperEvent(std::vector<ReadInfoType>& pendingReads) {
422*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
423*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{mPendingReadsLooperBusy};
424*9190c2a8SAndroid Build Coastguard Worker         while (mRunning.load(std::memory_order_relaxed)) {
425*9190c2a8SAndroid Build Coastguard Worker             pendingReads.resize(kPendingReadsBufferSize);
426*9190c2a8SAndroid Build Coastguard Worker             if (android::incfs::waitForPendingReads(mControl, 0ms, &pendingReads) !=
427*9190c2a8SAndroid Build Coastguard Worker                         android::incfs::WaitResult::HaveData ||
428*9190c2a8SAndroid Build Coastguard Worker                 pendingReads.empty()) {
429*9190c2a8SAndroid Build Coastguard Worker                 return 1;
430*9190c2a8SAndroid Build Coastguard Worker             }
431*9190c2a8SAndroid Build Coastguard Worker             if constexpr (std::is_same_v<ReadInfoType, ReadInfo>) {
432*9190c2a8SAndroid Build Coastguard Worker                 if (mDataLoader->onPendingReads) {
433*9190c2a8SAndroid Build Coastguard Worker                     mDataLoader->onPendingReads(mDataLoader, pendingReads.data(),
434*9190c2a8SAndroid Build Coastguard Worker                                                 pendingReads.size());
435*9190c2a8SAndroid Build Coastguard Worker                 }
436*9190c2a8SAndroid Build Coastguard Worker             } else {
437*9190c2a8SAndroid Build Coastguard Worker                 if (mDataLoader->onPendingReadsWithUid) {
438*9190c2a8SAndroid Build Coastguard Worker                     mDataLoader->onPendingReadsWithUid(mDataLoader, pendingReads.data(),
439*9190c2a8SAndroid Build Coastguard Worker                                                        pendingReads.size());
440*9190c2a8SAndroid Build Coastguard Worker                 }
441*9190c2a8SAndroid Build Coastguard Worker             }
442*9190c2a8SAndroid Build Coastguard Worker         }
443*9190c2a8SAndroid Build Coastguard Worker         return 1;
444*9190c2a8SAndroid Build Coastguard Worker     }
445*9190c2a8SAndroid Build Coastguard Worker 
446*9190c2a8SAndroid Build Coastguard Worker     template <class ReadInfoType>
onLogLooperEvent(std::vector<ReadInfoType> & pageReads)447*9190c2a8SAndroid Build Coastguard Worker     int onLogLooperEvent(std::vector<ReadInfoType>& pageReads) {
448*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
449*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{mLogLooperBusy};
450*9190c2a8SAndroid Build Coastguard Worker         while (mRunning.load(std::memory_order_relaxed)) {
451*9190c2a8SAndroid Build Coastguard Worker             pageReads.clear();
452*9190c2a8SAndroid Build Coastguard Worker             if (android::incfs::waitForPageReads(mControl, 0ms, &pageReads) !=
453*9190c2a8SAndroid Build Coastguard Worker                         android::incfs::WaitResult::HaveData ||
454*9190c2a8SAndroid Build Coastguard Worker                 pageReads.empty()) {
455*9190c2a8SAndroid Build Coastguard Worker                 return 1;
456*9190c2a8SAndroid Build Coastguard Worker             }
457*9190c2a8SAndroid Build Coastguard Worker             if constexpr (std::is_same_v<ReadInfoType, ReadInfo>) {
458*9190c2a8SAndroid Build Coastguard Worker                 if (mDataLoader->onPageReads) {
459*9190c2a8SAndroid Build Coastguard Worker                     mDataLoader->onPageReads(mDataLoader, pageReads.data(), pageReads.size());
460*9190c2a8SAndroid Build Coastguard Worker                 }
461*9190c2a8SAndroid Build Coastguard Worker             } else {
462*9190c2a8SAndroid Build Coastguard Worker                 if (mDataLoader->onPageReadsWithUid) {
463*9190c2a8SAndroid Build Coastguard Worker                     mDataLoader->onPageReadsWithUid(mDataLoader, pageReads.data(),
464*9190c2a8SAndroid Build Coastguard Worker                                                     pageReads.size());
465*9190c2a8SAndroid Build Coastguard Worker                 }
466*9190c2a8SAndroid Build Coastguard Worker             }
467*9190c2a8SAndroid Build Coastguard Worker         }
468*9190c2a8SAndroid Build Coastguard Worker         return 1;
469*9190c2a8SAndroid Build Coastguard Worker     }
470*9190c2a8SAndroid Build Coastguard Worker 
onPendingReadsLooperEvent(std::vector<ReadInfo> & pendingReads,std::vector<ReadInfoWithUid> & pendingReadsWithUid)471*9190c2a8SAndroid Build Coastguard Worker     int onPendingReadsLooperEvent(std::vector<ReadInfo>& pendingReads,
472*9190c2a8SAndroid Build Coastguard Worker                                   std::vector<ReadInfoWithUid>& pendingReadsWithUid) {
473*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
474*9190c2a8SAndroid Build Coastguard Worker         if (mDataLoaderFeatures & DATA_LOADER_FEATURE_UID) {
475*9190c2a8SAndroid Build Coastguard Worker             return this->onPendingReadsLooperEvent(pendingReadsWithUid);
476*9190c2a8SAndroid Build Coastguard Worker         } else {
477*9190c2a8SAndroid Build Coastguard Worker             return this->onPendingReadsLooperEvent(pendingReads);
478*9190c2a8SAndroid Build Coastguard Worker         }
479*9190c2a8SAndroid Build Coastguard Worker     }
480*9190c2a8SAndroid Build Coastguard Worker 
onLogLooperEvent(std::vector<ReadInfo> & pageReads,std::vector<ReadInfoWithUid> & pageReadsWithUid)481*9190c2a8SAndroid Build Coastguard Worker     int onLogLooperEvent(std::vector<ReadInfo>& pageReads,
482*9190c2a8SAndroid Build Coastguard Worker                          std::vector<ReadInfoWithUid>& pageReadsWithUid) {
483*9190c2a8SAndroid Build Coastguard Worker         CHECK(mDataLoader);
484*9190c2a8SAndroid Build Coastguard Worker         if (mDataLoaderFeatures & DATA_LOADER_FEATURE_UID) {
485*9190c2a8SAndroid Build Coastguard Worker             return this->onLogLooperEvent(pageReadsWithUid);
486*9190c2a8SAndroid Build Coastguard Worker         } else {
487*9190c2a8SAndroid Build Coastguard Worker             return this->onLogLooperEvent(pageReads);
488*9190c2a8SAndroid Build Coastguard Worker         }
489*9190c2a8SAndroid Build Coastguard Worker     }
490*9190c2a8SAndroid Build Coastguard Worker 
writeData(jstring name,jlong offsetBytes,jlong lengthBytes,jobject incomingFd) const491*9190c2a8SAndroid Build Coastguard Worker     void writeData(jstring name, jlong offsetBytes, jlong lengthBytes, jobject incomingFd) const {
492*9190c2a8SAndroid Build Coastguard Worker         CHECK(mCallbackControl);
493*9190c2a8SAndroid Build Coastguard Worker         JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
494*9190c2a8SAndroid Build Coastguard Worker         const auto& jni = jniIds(env);
495*9190c2a8SAndroid Build Coastguard Worker         env->CallVoidMethod(mCallbackControl, jni.callbackControlWriteData, name, offsetBytes,
496*9190c2a8SAndroid Build Coastguard Worker                             lengthBytes, incomingFd);
497*9190c2a8SAndroid Build Coastguard Worker     }
498*9190c2a8SAndroid Build Coastguard Worker 
openForSpecialOps(FileId fid) const499*9190c2a8SAndroid Build Coastguard Worker     android::incfs::UniqueFd openForSpecialOps(FileId fid) const {
500*9190c2a8SAndroid Build Coastguard Worker         return android::incfs::openForSpecialOps(mControl, fid);
501*9190c2a8SAndroid Build Coastguard Worker     }
502*9190c2a8SAndroid Build Coastguard Worker 
writeBlocks(android::dataloader::Span<const IncFsDataBlock> blocks) const503*9190c2a8SAndroid Build Coastguard Worker     int writeBlocks(android::dataloader::Span<const IncFsDataBlock> blocks) const {
504*9190c2a8SAndroid Build Coastguard Worker         return android::incfs::writeBlocks(blocks);
505*9190c2a8SAndroid Build Coastguard Worker     }
506*9190c2a8SAndroid Build Coastguard Worker 
getRawMetadata(FileId fid,char buffer[],size_t * bufferSize) const507*9190c2a8SAndroid Build Coastguard Worker     int getRawMetadata(FileId fid, char buffer[], size_t* bufferSize) const {
508*9190c2a8SAndroid Build Coastguard Worker         return IncFs_GetMetadataById(mControl, fid, buffer, bufferSize);
509*9190c2a8SAndroid Build Coastguard Worker     }
510*9190c2a8SAndroid Build Coastguard Worker 
setParams(DataLoaderFilesystemParams params) const511*9190c2a8SAndroid Build Coastguard Worker     bool setParams(DataLoaderFilesystemParams params) const {
512*9190c2a8SAndroid Build Coastguard Worker         CHECK(mServiceConnector);
513*9190c2a8SAndroid Build Coastguard Worker         JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
514*9190c2a8SAndroid Build Coastguard Worker         const auto& jni = jniIds(env);
515*9190c2a8SAndroid Build Coastguard Worker         int result = env->CallIntMethod(mServiceConnector,
516*9190c2a8SAndroid Build Coastguard Worker                                         jni.incrementalServiceConnectorSetStorageParams,
517*9190c2a8SAndroid Build Coastguard Worker                                         params.readLogsEnabled);
518*9190c2a8SAndroid Build Coastguard Worker         if (result != 0) {
519*9190c2a8SAndroid Build Coastguard Worker             LOG(ERROR) << "setStorageParams failed with error: " << result;
520*9190c2a8SAndroid Build Coastguard Worker         }
521*9190c2a8SAndroid Build Coastguard Worker         if (checkAndClearJavaException(__func__)) {
522*9190c2a8SAndroid Build Coastguard Worker             return false;
523*9190c2a8SAndroid Build Coastguard Worker         }
524*9190c2a8SAndroid Build Coastguard Worker         return (result == 0);
525*9190c2a8SAndroid Build Coastguard Worker     }
526*9190c2a8SAndroid Build Coastguard Worker 
reportStatus(DataLoaderStatus status)527*9190c2a8SAndroid Build Coastguard Worker     bool reportStatus(DataLoaderStatus status) {
528*9190c2a8SAndroid Build Coastguard Worker         JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
529*9190c2a8SAndroid Build Coastguard Worker         const auto& jni = jniIds(env);
530*9190c2a8SAndroid Build Coastguard Worker 
531*9190c2a8SAndroid Build Coastguard Worker         jint osStatus;
532*9190c2a8SAndroid Build Coastguard Worker         switch (status) {
533*9190c2a8SAndroid Build Coastguard Worker             case DATA_LOADER_UNAVAILABLE:
534*9190c2a8SAndroid Build Coastguard Worker                 osStatus = jni.constants.DATA_LOADER_UNAVAILABLE;
535*9190c2a8SAndroid Build Coastguard Worker                 break;
536*9190c2a8SAndroid Build Coastguard Worker             case DATA_LOADER_UNRECOVERABLE:
537*9190c2a8SAndroid Build Coastguard Worker                 osStatus = jni.constants.DATA_LOADER_UNRECOVERABLE;
538*9190c2a8SAndroid Build Coastguard Worker                 break;
539*9190c2a8SAndroid Build Coastguard Worker             default: {
540*9190c2a8SAndroid Build Coastguard Worker                 ALOGE("Unable to report invalid status. status=%d", status);
541*9190c2a8SAndroid Build Coastguard Worker                 return false;
542*9190c2a8SAndroid Build Coastguard Worker             }
543*9190c2a8SAndroid Build Coastguard Worker         }
544*9190c2a8SAndroid Build Coastguard Worker         return reportStatusViaCallback(env, mListener, mStorageId, osStatus);
545*9190c2a8SAndroid Build Coastguard Worker     }
546*9190c2a8SAndroid Build Coastguard Worker 
checkAndClearJavaException(std::string_view method) const547*9190c2a8SAndroid Build Coastguard Worker     bool checkAndClearJavaException(std::string_view method) const {
548*9190c2a8SAndroid Build Coastguard Worker         JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
549*9190c2a8SAndroid Build Coastguard Worker         return ::checkAndClearJavaException(env, method);
550*9190c2a8SAndroid Build Coastguard Worker     }
551*9190c2a8SAndroid Build Coastguard Worker 
control() const552*9190c2a8SAndroid Build Coastguard Worker     const UniqueControl& control() const { return mControl; }
getListenerLocalRef(JNIEnv * env) const553*9190c2a8SAndroid Build Coastguard Worker     jobject getListenerLocalRef(JNIEnv* env) const { return env->NewLocalRef(mListener); }
554*9190c2a8SAndroid Build Coastguard Worker 
555*9190c2a8SAndroid Build Coastguard Worker private:
556*9190c2a8SAndroid Build Coastguard Worker     JavaVM* const mJvm;
557*9190c2a8SAndroid Build Coastguard Worker     jobject const mService;
558*9190c2a8SAndroid Build Coastguard Worker     jobject const mServiceConnector;
559*9190c2a8SAndroid Build Coastguard Worker     jobject const mCallbackControl;
560*9190c2a8SAndroid Build Coastguard Worker     jobject const mListener;
561*9190c2a8SAndroid Build Coastguard Worker 
562*9190c2a8SAndroid Build Coastguard Worker     jint const mStorageId;
563*9190c2a8SAndroid Build Coastguard Worker     UniqueControl const mControl;
564*9190c2a8SAndroid Build Coastguard Worker 
565*9190c2a8SAndroid Build Coastguard Worker     ::DataLoader* mDataLoader = nullptr;
566*9190c2a8SAndroid Build Coastguard Worker     DataLoaderFeatures mDataLoaderFeatures = DATA_LOADER_FEATURE_NONE;
567*9190c2a8SAndroid Build Coastguard Worker 
568*9190c2a8SAndroid Build Coastguard Worker     std::mutex mPendingReadsLooperBusy;
569*9190c2a8SAndroid Build Coastguard Worker     std::mutex mLogLooperBusy;
570*9190c2a8SAndroid Build Coastguard Worker     std::atomic<bool> mRunning{false};
571*9190c2a8SAndroid Build Coastguard Worker };
572*9190c2a8SAndroid Build Coastguard Worker 
onPendingReadsLooperEvent(int fd,int events,void * data)573*9190c2a8SAndroid Build Coastguard Worker static int onPendingReadsLooperEvent(int fd, int events, void* data) {
574*9190c2a8SAndroid Build Coastguard Worker     if (globals().stopped) {
575*9190c2a8SAndroid Build Coastguard Worker         // No more listeners.
576*9190c2a8SAndroid Build Coastguard Worker         return 0;
577*9190c2a8SAndroid Build Coastguard Worker     }
578*9190c2a8SAndroid Build Coastguard Worker     auto&& dataLoaderConnector = (DataLoaderConnector*)data;
579*9190c2a8SAndroid Build Coastguard Worker     return dataLoaderConnector->onPendingReadsLooperEvent(globals().pendingReads,
580*9190c2a8SAndroid Build Coastguard Worker                                                           globals().pendingReadsWithUid);
581*9190c2a8SAndroid Build Coastguard Worker }
582*9190c2a8SAndroid Build Coastguard Worker 
onLogLooperEvent(int fd,int events,void * data)583*9190c2a8SAndroid Build Coastguard Worker static int onLogLooperEvent(int fd, int events, void* data) {
584*9190c2a8SAndroid Build Coastguard Worker     if (globals().stopped) {
585*9190c2a8SAndroid Build Coastguard Worker         // No more listeners.
586*9190c2a8SAndroid Build Coastguard Worker         return 0;
587*9190c2a8SAndroid Build Coastguard Worker     }
588*9190c2a8SAndroid Build Coastguard Worker     auto&& dataLoaderConnector = (DataLoaderConnector*)data;
589*9190c2a8SAndroid Build Coastguard Worker     return dataLoaderConnector->onLogLooperEvent(globals().pageReads, globals().pageReadsWithUid);
590*9190c2a8SAndroid Build Coastguard Worker }
591*9190c2a8SAndroid Build Coastguard Worker 
createFdFromManaged(JNIEnv * env,jobject pfd)592*9190c2a8SAndroid Build Coastguard Worker static int createFdFromManaged(JNIEnv* env, jobject pfd) {
593*9190c2a8SAndroid Build Coastguard Worker     if (!pfd) {
594*9190c2a8SAndroid Build Coastguard Worker         return -1;
595*9190c2a8SAndroid Build Coastguard Worker     }
596*9190c2a8SAndroid Build Coastguard Worker 
597*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
598*9190c2a8SAndroid Build Coastguard Worker     auto managedFd = env->CallObjectMethod(pfd, jni.parcelFileDescriptorGetFileDescriptor);
599*9190c2a8SAndroid Build Coastguard Worker     return fcntl(jniGetFDFromFileDescriptor(env, managedFd), F_DUPFD_CLOEXEC, 0);
600*9190c2a8SAndroid Build Coastguard Worker }
601*9190c2a8SAndroid Build Coastguard Worker 
createServiceConnector(JNIEnv * env,jobject managedControl)602*9190c2a8SAndroid Build Coastguard Worker static jobject createServiceConnector(JNIEnv* env, jobject managedControl) {
603*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
604*9190c2a8SAndroid Build Coastguard Worker     return env->GetObjectField(managedControl, jni.service);
605*9190c2a8SAndroid Build Coastguard Worker }
606*9190c2a8SAndroid Build Coastguard Worker 
createCallbackControl(JNIEnv * env,jobject managedControl)607*9190c2a8SAndroid Build Coastguard Worker static jobject createCallbackControl(JNIEnv* env, jobject managedControl) {
608*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
609*9190c2a8SAndroid Build Coastguard Worker     return env->GetObjectField(managedControl, jni.callback);
610*9190c2a8SAndroid Build Coastguard Worker }
611*9190c2a8SAndroid Build Coastguard Worker 
createIncFsControlFromManaged(JNIEnv * env,jobject managedControl)612*9190c2a8SAndroid Build Coastguard Worker static UniqueControl createIncFsControlFromManaged(JNIEnv* env, jobject managedControl) {
613*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
614*9190c2a8SAndroid Build Coastguard Worker     auto managedIncControl = env->GetObjectField(managedControl, jni.incremental);
615*9190c2a8SAndroid Build Coastguard Worker     if (!managedIncControl) {
616*9190c2a8SAndroid Build Coastguard Worker         return UniqueControl();
617*9190c2a8SAndroid Build Coastguard Worker     }
618*9190c2a8SAndroid Build Coastguard Worker     auto cmd = createFdFromManaged(env, env->GetObjectField(managedIncControl, jni.controlCmd));
619*9190c2a8SAndroid Build Coastguard Worker     auto pr = createFdFromManaged(env,
620*9190c2a8SAndroid Build Coastguard Worker                                   env->GetObjectField(managedIncControl, jni.controlPendingReads));
621*9190c2a8SAndroid Build Coastguard Worker     auto log = createFdFromManaged(env, env->GetObjectField(managedIncControl, jni.controlLog));
622*9190c2a8SAndroid Build Coastguard Worker     auto blocksWritten =
623*9190c2a8SAndroid Build Coastguard Worker             createFdFromManaged(env,
624*9190c2a8SAndroid Build Coastguard Worker                                 env->GetObjectField(managedIncControl, jni.controlBlocksWritten));
625*9190c2a8SAndroid Build Coastguard Worker     return android::incfs::createControl(cmd, pr, log, blocksWritten);
626*9190c2a8SAndroid Build Coastguard Worker }
627*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderParamsPair(android::dataloader::DataLoaderParams && dataLoaderParams)628*9190c2a8SAndroid Build Coastguard Worker DataLoaderParamsPair::DataLoaderParamsPair(android::dataloader::DataLoaderParams&& dataLoaderParams)
629*9190c2a8SAndroid Build Coastguard Worker       : mDataLoaderParams(std::move(dataLoaderParams)) {
630*9190c2a8SAndroid Build Coastguard Worker     mNDKDataLoaderParams.type = mDataLoaderParams.type();
631*9190c2a8SAndroid Build Coastguard Worker     mNDKDataLoaderParams.packageName = mDataLoaderParams.packageName().c_str();
632*9190c2a8SAndroid Build Coastguard Worker     mNDKDataLoaderParams.className = mDataLoaderParams.className().c_str();
633*9190c2a8SAndroid Build Coastguard Worker     mNDKDataLoaderParams.arguments = mDataLoaderParams.arguments().c_str();
634*9190c2a8SAndroid Build Coastguard Worker }
635*9190c2a8SAndroid Build Coastguard Worker 
createFromManaged(JNIEnv * env,jobject managedParams)636*9190c2a8SAndroid Build Coastguard Worker DataLoaderParamsPair DataLoaderParamsPair::createFromManaged(JNIEnv* env, jobject managedParams) {
637*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
638*9190c2a8SAndroid Build Coastguard Worker 
639*9190c2a8SAndroid Build Coastguard Worker     const DataLoaderType type = (DataLoaderType)env->GetIntField(managedParams, jni.paramsType);
640*9190c2a8SAndroid Build Coastguard Worker 
641*9190c2a8SAndroid Build Coastguard Worker     ScopedLocalRef<jstring> paramsPackageName(env,
642*9190c2a8SAndroid Build Coastguard Worker                                               GetStringField(env, managedParams,
643*9190c2a8SAndroid Build Coastguard Worker                                                              jni.paramsPackageName));
644*9190c2a8SAndroid Build Coastguard Worker     ScopedLocalRef<jstring> paramsClassName(env,
645*9190c2a8SAndroid Build Coastguard Worker                                             GetStringField(env, managedParams,
646*9190c2a8SAndroid Build Coastguard Worker                                                            jni.paramsClassName));
647*9190c2a8SAndroid Build Coastguard Worker     ScopedLocalRef<jstring> paramsArguments(env,
648*9190c2a8SAndroid Build Coastguard Worker                                             GetStringField(env, managedParams,
649*9190c2a8SAndroid Build Coastguard Worker                                                            jni.paramsArguments));
650*9190c2a8SAndroid Build Coastguard Worker     ScopedUtfChars package(env, paramsPackageName.get());
651*9190c2a8SAndroid Build Coastguard Worker     ScopedUtfChars className(env, paramsClassName.get());
652*9190c2a8SAndroid Build Coastguard Worker     ScopedUtfChars arguments(env, paramsArguments.get());
653*9190c2a8SAndroid Build Coastguard Worker     return DataLoaderParamsPair(android::dataloader::DataLoaderParams(type, package.c_str(),
654*9190c2a8SAndroid Build Coastguard Worker                                                                       className.c_str(),
655*9190c2a8SAndroid Build Coastguard Worker                                                                       arguments.c_str()));
656*9190c2a8SAndroid Build Coastguard Worker }
657*9190c2a8SAndroid Build Coastguard Worker 
pendingReadsLooperThread()658*9190c2a8SAndroid Build Coastguard Worker static void pendingReadsLooperThread() {
659*9190c2a8SAndroid Build Coastguard Worker     constexpr auto kTimeoutMsecs = -1;
660*9190c2a8SAndroid Build Coastguard Worker     while (!globals().stopped) {
661*9190c2a8SAndroid Build Coastguard Worker         pendingReadsLooper().pollAll(kTimeoutMsecs);
662*9190c2a8SAndroid Build Coastguard Worker     }
663*9190c2a8SAndroid Build Coastguard Worker }
664*9190c2a8SAndroid Build Coastguard Worker 
logLooperThread()665*9190c2a8SAndroid Build Coastguard Worker static void logLooperThread() {
666*9190c2a8SAndroid Build Coastguard Worker     constexpr auto kTimeoutMsecs = -1;
667*9190c2a8SAndroid Build Coastguard Worker     while (!globals().stopped) {
668*9190c2a8SAndroid Build Coastguard Worker         logLooper().pollAll(kTimeoutMsecs);
669*9190c2a8SAndroid Build Coastguard Worker     }
670*9190c2a8SAndroid Build Coastguard Worker }
671*9190c2a8SAndroid Build Coastguard Worker 
pathFromFd(int fd)672*9190c2a8SAndroid Build Coastguard Worker static std::string pathFromFd(int fd) {
673*9190c2a8SAndroid Build Coastguard Worker     static constexpr char fdNameFormat[] = "/proc/self/fd/%d";
674*9190c2a8SAndroid Build Coastguard Worker     char fdNameBuffer[NELEM(fdNameFormat) + 11 + 1]; // max int length + '\0'
675*9190c2a8SAndroid Build Coastguard Worker     snprintf(fdNameBuffer, NELEM(fdNameBuffer), fdNameFormat, fd);
676*9190c2a8SAndroid Build Coastguard Worker 
677*9190c2a8SAndroid Build Coastguard Worker     std::string res;
678*9190c2a8SAndroid Build Coastguard Worker     // lstat() is supposed to return us exactly the needed buffer size, but
679*9190c2a8SAndroid Build Coastguard Worker     // somehow it may also return a smaller (but still >0) st_size field.
680*9190c2a8SAndroid Build Coastguard Worker     // That's why let's only use it for the initial estimate.
681*9190c2a8SAndroid Build Coastguard Worker     struct stat st = {};
682*9190c2a8SAndroid Build Coastguard Worker     if (::lstat(fdNameBuffer, &st) || st.st_size == 0) {
683*9190c2a8SAndroid Build Coastguard Worker         st.st_size = PATH_MAX;
684*9190c2a8SAndroid Build Coastguard Worker     }
685*9190c2a8SAndroid Build Coastguard Worker     auto bufSize = st.st_size;
686*9190c2a8SAndroid Build Coastguard Worker     for (;;) {
687*9190c2a8SAndroid Build Coastguard Worker         res.resize(bufSize + 1, '\0');
688*9190c2a8SAndroid Build Coastguard Worker         auto size = ::readlink(fdNameBuffer, &res[0], res.size());
689*9190c2a8SAndroid Build Coastguard Worker         if (size < 0) {
690*9190c2a8SAndroid Build Coastguard Worker             return {};
691*9190c2a8SAndroid Build Coastguard Worker         }
692*9190c2a8SAndroid Build Coastguard Worker         if (size > bufSize) {
693*9190c2a8SAndroid Build Coastguard Worker             // File got renamed in between lstat() and readlink() calls? Retry.
694*9190c2a8SAndroid Build Coastguard Worker             bufSize *= 2;
695*9190c2a8SAndroid Build Coastguard Worker             continue;
696*9190c2a8SAndroid Build Coastguard Worker         }
697*9190c2a8SAndroid Build Coastguard Worker         res.resize(size);
698*9190c2a8SAndroid Build Coastguard Worker         return res;
699*9190c2a8SAndroid Build Coastguard Worker     }
700*9190c2a8SAndroid Build Coastguard Worker }
701*9190c2a8SAndroid Build Coastguard Worker 
702*9190c2a8SAndroid Build Coastguard Worker } // namespace
703*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_Initialize(struct::DataLoaderFactory * factory)704*9190c2a8SAndroid Build Coastguard Worker void DataLoader_Initialize(struct ::DataLoaderFactory* factory) {
705*9190c2a8SAndroid Build Coastguard Worker     CHECK(factory) << "DataLoader factory is invalid.";
706*9190c2a8SAndroid Build Coastguard Worker     globals().legacyDataLoaderFactory = factory;
707*9190c2a8SAndroid Build Coastguard Worker }
708*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_Initialize_WithFeatures(struct::DataLoaderFactory * factory)709*9190c2a8SAndroid Build Coastguard Worker void DataLoader_Initialize_WithFeatures(struct ::DataLoaderFactory* factory) {
710*9190c2a8SAndroid Build Coastguard Worker     CHECK(factory) << "DataLoader factory is invalid.";
711*9190c2a8SAndroid Build Coastguard Worker     globals().dataLoaderFactory = factory;
712*9190c2a8SAndroid Build Coastguard Worker }
713*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_FilesystemConnector_writeData(DataLoaderFilesystemConnectorPtr ifs,jstring name,jlong offsetBytes,jlong lengthBytes,jobject incomingFd)714*9190c2a8SAndroid Build Coastguard Worker void DataLoader_FilesystemConnector_writeData(DataLoaderFilesystemConnectorPtr ifs, jstring name,
715*9190c2a8SAndroid Build Coastguard Worker                                               jlong offsetBytes, jlong lengthBytes,
716*9190c2a8SAndroid Build Coastguard Worker                                               jobject incomingFd) {
717*9190c2a8SAndroid Build Coastguard Worker     auto connector = static_cast<DataLoaderConnector*>(ifs);
718*9190c2a8SAndroid Build Coastguard Worker     return connector->writeData(name, offsetBytes, lengthBytes, incomingFd);
719*9190c2a8SAndroid Build Coastguard Worker }
720*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_FilesystemConnector_openForSpecialOps(DataLoaderFilesystemConnectorPtr ifs,IncFsFileId fid)721*9190c2a8SAndroid Build Coastguard Worker int DataLoader_FilesystemConnector_openForSpecialOps(DataLoaderFilesystemConnectorPtr ifs,
722*9190c2a8SAndroid Build Coastguard Worker                                                      IncFsFileId fid) {
723*9190c2a8SAndroid Build Coastguard Worker     auto connector = static_cast<DataLoaderConnector*>(ifs);
724*9190c2a8SAndroid Build Coastguard Worker     return connector->openForSpecialOps(fid).release();
725*9190c2a8SAndroid Build Coastguard Worker }
726*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_FilesystemConnector_writeBlocks(DataLoaderFilesystemConnectorPtr ifs,const IncFsDataBlock blocks[],int blocksCount)727*9190c2a8SAndroid Build Coastguard Worker int DataLoader_FilesystemConnector_writeBlocks(DataLoaderFilesystemConnectorPtr ifs,
728*9190c2a8SAndroid Build Coastguard Worker                                                const IncFsDataBlock blocks[], int blocksCount) {
729*9190c2a8SAndroid Build Coastguard Worker     auto connector = static_cast<DataLoaderConnector*>(ifs);
730*9190c2a8SAndroid Build Coastguard Worker     return connector->writeBlocks({blocks, static_cast<size_t>(blocksCount)});
731*9190c2a8SAndroid Build Coastguard Worker }
732*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_FilesystemConnector_getRawMetadata(DataLoaderFilesystemConnectorPtr ifs,IncFsFileId fid,char buffer[],size_t * bufferSize)733*9190c2a8SAndroid Build Coastguard Worker int DataLoader_FilesystemConnector_getRawMetadata(DataLoaderFilesystemConnectorPtr ifs,
734*9190c2a8SAndroid Build Coastguard Worker                                                   IncFsFileId fid, char buffer[],
735*9190c2a8SAndroid Build Coastguard Worker                                                   size_t* bufferSize) {
736*9190c2a8SAndroid Build Coastguard Worker     auto connector = static_cast<DataLoaderConnector*>(ifs);
737*9190c2a8SAndroid Build Coastguard Worker     return connector->getRawMetadata(fid, buffer, bufferSize);
738*9190c2a8SAndroid Build Coastguard Worker }
739*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_FilesystemConnector_setParams(DataLoaderFilesystemConnectorPtr ifs,DataLoaderFilesystemParams params)740*9190c2a8SAndroid Build Coastguard Worker bool DataLoader_FilesystemConnector_setParams(DataLoaderFilesystemConnectorPtr ifs,
741*9190c2a8SAndroid Build Coastguard Worker                                               DataLoaderFilesystemParams params) {
742*9190c2a8SAndroid Build Coastguard Worker     auto connector = static_cast<DataLoaderConnector*>(ifs);
743*9190c2a8SAndroid Build Coastguard Worker     return connector->setParams(params);
744*9190c2a8SAndroid Build Coastguard Worker }
745*9190c2a8SAndroid Build Coastguard Worker 
DataLoader_StatusListener_reportStatus(DataLoaderStatusListenerPtr listener,DataLoaderStatus status)746*9190c2a8SAndroid Build Coastguard Worker int DataLoader_StatusListener_reportStatus(DataLoaderStatusListenerPtr listener,
747*9190c2a8SAndroid Build Coastguard Worker                                            DataLoaderStatus status) {
748*9190c2a8SAndroid Build Coastguard Worker     auto connector = static_cast<DataLoaderConnector*>(listener);
749*9190c2a8SAndroid Build Coastguard Worker     return connector->reportStatus(status);
750*9190c2a8SAndroid Build Coastguard Worker }
751*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderService_OnCreate(JNIEnv * env,jobject service,jint storageId,jobject control,jobject params,jobject listener)752*9190c2a8SAndroid Build Coastguard Worker bool DataLoaderService_OnCreate(JNIEnv* env, jobject service, jint storageId, jobject control,
753*9190c2a8SAndroid Build Coastguard Worker                                 jobject params, jobject listener) {
754*9190c2a8SAndroid Build Coastguard Worker     {
755*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{globals().dataLoaderConnectorsLock};
756*9190c2a8SAndroid Build Coastguard Worker         auto dlIt = globals().dataLoaderConnectors.find(storageId);
757*9190c2a8SAndroid Build Coastguard Worker         if (dlIt != globals().dataLoaderConnectors.end()) {
758*9190c2a8SAndroid Build Coastguard Worker             ALOGI("id(%d): already exist, skipping creation.", storageId);
759*9190c2a8SAndroid Build Coastguard Worker             return true;
760*9190c2a8SAndroid Build Coastguard Worker         }
761*9190c2a8SAndroid Build Coastguard Worker     }
762*9190c2a8SAndroid Build Coastguard Worker     auto nativeControl = createIncFsControlFromManaged(env, control);
763*9190c2a8SAndroid Build Coastguard Worker     if (nativeControl) {
764*9190c2a8SAndroid Build Coastguard Worker         using namespace android::incfs;
765*9190c2a8SAndroid Build Coastguard Worker         ALOGI("DataLoader::create incremental fds: %d/%d/%d/%d", nativeControl.cmd(),
766*9190c2a8SAndroid Build Coastguard Worker               nativeControl.pendingReads(), nativeControl.logs(), nativeControl.blocksWritten());
767*9190c2a8SAndroid Build Coastguard Worker         auto cmdPath = pathFromFd(nativeControl.cmd());
768*9190c2a8SAndroid Build Coastguard Worker         auto dir = path::dirName(cmdPath);
769*9190c2a8SAndroid Build Coastguard Worker         ALOGI("DataLoader::create incremental dir: %s, files: %s/%s/%s/%s",
770*9190c2a8SAndroid Build Coastguard Worker               details::c_str(dir).get(), details::c_str(path::baseName(cmdPath)).get(),
771*9190c2a8SAndroid Build Coastguard Worker               details::c_str(path::baseName(pathFromFd(nativeControl.pendingReads()))).get(),
772*9190c2a8SAndroid Build Coastguard Worker               details::c_str(path::baseName(pathFromFd(nativeControl.logs()))).get(),
773*9190c2a8SAndroid Build Coastguard Worker               details::c_str(path::baseName(pathFromFd(nativeControl.blocksWritten()))).get());
774*9190c2a8SAndroid Build Coastguard Worker     } else {
775*9190c2a8SAndroid Build Coastguard Worker         ALOGI("DataLoader::create no incremental control");
776*9190c2a8SAndroid Build Coastguard Worker     }
777*9190c2a8SAndroid Build Coastguard Worker 
778*9190c2a8SAndroid Build Coastguard Worker     auto nativeParams = DataLoaderParamsPair::createFromManaged(env, params);
779*9190c2a8SAndroid Build Coastguard Worker     ALOGI("DataLoader::create params: %d|%s|%s|%s", nativeParams.dataLoaderParams().type(),
780*9190c2a8SAndroid Build Coastguard Worker           nativeParams.dataLoaderParams().packageName().c_str(),
781*9190c2a8SAndroid Build Coastguard Worker           nativeParams.dataLoaderParams().className().c_str(),
782*9190c2a8SAndroid Build Coastguard Worker           nativeParams.dataLoaderParams().arguments().c_str());
783*9190c2a8SAndroid Build Coastguard Worker 
784*9190c2a8SAndroid Build Coastguard Worker     auto serviceConnector = createServiceConnector(env, control);
785*9190c2a8SAndroid Build Coastguard Worker     auto callbackControl = createCallbackControl(env, control);
786*9190c2a8SAndroid Build Coastguard Worker 
787*9190c2a8SAndroid Build Coastguard Worker     auto reportUnavailable = [env, storageId](jobject listener) {
788*9190c2a8SAndroid Build Coastguard Worker         const auto& jni = jniIds(env);
789*9190c2a8SAndroid Build Coastguard Worker         reportStatusViaCallback(env, listener, storageId, jni.constants.DATA_LOADER_UNAVAILABLE);
790*9190c2a8SAndroid Build Coastguard Worker     };
791*9190c2a8SAndroid Build Coastguard Worker     // By default, it's disabled. Need to assign listener to enable.
792*9190c2a8SAndroid Build Coastguard Worker     std::unique_ptr<_jobject, decltype(reportUnavailable)>
793*9190c2a8SAndroid Build Coastguard Worker             reportUnavailableOnExit(nullptr, reportUnavailable);
794*9190c2a8SAndroid Build Coastguard Worker 
795*9190c2a8SAndroid Build Coastguard Worker     auto dataLoaderConnector =
796*9190c2a8SAndroid Build Coastguard Worker             std::make_unique<DataLoaderConnector>(env, service, storageId, std::move(nativeControl),
797*9190c2a8SAndroid Build Coastguard Worker                                                   serviceConnector, callbackControl, listener);
798*9190c2a8SAndroid Build Coastguard Worker     bool created = dataLoaderConnector->onCreate(nativeParams, params);
799*9190c2a8SAndroid Build Coastguard Worker     {
800*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{globals().dataLoaderConnectorsLock};
801*9190c2a8SAndroid Build Coastguard Worker         auto [dlIt, dlInserted] =
802*9190c2a8SAndroid Build Coastguard Worker                 globals().dataLoaderConnectors.try_emplace(storageId,
803*9190c2a8SAndroid Build Coastguard Worker                                                            std::move(dataLoaderConnector));
804*9190c2a8SAndroid Build Coastguard Worker         if (!dlInserted) {
805*9190c2a8SAndroid Build Coastguard Worker             ALOGE("id(%d): already exist, skipping creation.", storageId);
806*9190c2a8SAndroid Build Coastguard Worker             return false;
807*9190c2a8SAndroid Build Coastguard Worker         }
808*9190c2a8SAndroid Build Coastguard Worker 
809*9190c2a8SAndroid Build Coastguard Worker         if (!created) {
810*9190c2a8SAndroid Build Coastguard Worker             globals().dataLoaderConnectors.erase(dlIt);
811*9190c2a8SAndroid Build Coastguard Worker             // Enable the reporter.
812*9190c2a8SAndroid Build Coastguard Worker             reportUnavailableOnExit.reset(listener);
813*9190c2a8SAndroid Build Coastguard Worker             return false;
814*9190c2a8SAndroid Build Coastguard Worker         }
815*9190c2a8SAndroid Build Coastguard Worker     }
816*9190c2a8SAndroid Build Coastguard Worker 
817*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
818*9190c2a8SAndroid Build Coastguard Worker     reportStatusViaCallback(env, listener, storageId, jni.constants.DATA_LOADER_CREATED);
819*9190c2a8SAndroid Build Coastguard Worker 
820*9190c2a8SAndroid Build Coastguard Worker     return true;
821*9190c2a8SAndroid Build Coastguard Worker }
822*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderService_OnStart(JNIEnv * env,jint storageId)823*9190c2a8SAndroid Build Coastguard Worker bool DataLoaderService_OnStart(JNIEnv* env, jint storageId) {
824*9190c2a8SAndroid Build Coastguard Worker     auto destroyAndReportUnavailable = [env, storageId](jobject listener) {
825*9190c2a8SAndroid Build Coastguard Worker         // Because of the MT the installer can call commit and recreate/restart dataLoader before
826*9190c2a8SAndroid Build Coastguard Worker         // system server has a change to destroy it.
827*9190c2a8SAndroid Build Coastguard Worker         DataLoaderService_OnDestroy(env, storageId);
828*9190c2a8SAndroid Build Coastguard Worker         const auto& jni = jniIds(env);
829*9190c2a8SAndroid Build Coastguard Worker         reportStatusViaCallback(env, listener, storageId, jni.constants.DATA_LOADER_UNAVAILABLE);
830*9190c2a8SAndroid Build Coastguard Worker     };
831*9190c2a8SAndroid Build Coastguard Worker     // By default, it's disabled. Need to assign listener to enable.
832*9190c2a8SAndroid Build Coastguard Worker     std::unique_ptr<_jobject, decltype(destroyAndReportUnavailable)>
833*9190c2a8SAndroid Build Coastguard Worker             destroyAndReportUnavailableOnExit(nullptr, destroyAndReportUnavailable);
834*9190c2a8SAndroid Build Coastguard Worker 
835*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnectorPtr dataLoaderConnector;
836*9190c2a8SAndroid Build Coastguard Worker     {
837*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{globals().dataLoaderConnectorsLock};
838*9190c2a8SAndroid Build Coastguard Worker         auto dlIt = globals().dataLoaderConnectors.find(storageId);
839*9190c2a8SAndroid Build Coastguard Worker         if (dlIt == globals().dataLoaderConnectors.end()) {
840*9190c2a8SAndroid Build Coastguard Worker             ALOGE("Failed to start id(%d): not found", storageId);
841*9190c2a8SAndroid Build Coastguard Worker             return false;
842*9190c2a8SAndroid Build Coastguard Worker         }
843*9190c2a8SAndroid Build Coastguard Worker         dataLoaderConnector = dlIt->second;
844*9190c2a8SAndroid Build Coastguard Worker     }
845*9190c2a8SAndroid Build Coastguard Worker     const UniqueControl* control = &(dataLoaderConnector->control());
846*9190c2a8SAndroid Build Coastguard Worker     jobject listener = dataLoaderConnector->getListenerLocalRef(env);
847*9190c2a8SAndroid Build Coastguard Worker 
848*9190c2a8SAndroid Build Coastguard Worker     if (!dataLoaderConnector->onStart()) {
849*9190c2a8SAndroid Build Coastguard Worker         ALOGE("Failed to start id(%d): onStart returned false", storageId);
850*9190c2a8SAndroid Build Coastguard Worker         destroyAndReportUnavailableOnExit.reset(listener);
851*9190c2a8SAndroid Build Coastguard Worker         return false;
852*9190c2a8SAndroid Build Coastguard Worker     }
853*9190c2a8SAndroid Build Coastguard Worker 
854*9190c2a8SAndroid Build Coastguard Worker     if (control->pendingReads() >= 0) {
855*9190c2a8SAndroid Build Coastguard Worker         auto&& looper = pendingReadsLooper();
856*9190c2a8SAndroid Build Coastguard Worker         if (!globals().pendingReadsLooperThread.joinable()) {
857*9190c2a8SAndroid Build Coastguard Worker             std::lock_guard lock{globals().dataLoaderConnectorsLock};
858*9190c2a8SAndroid Build Coastguard Worker             if (!globals().pendingReadsLooperThread.joinable()) {
859*9190c2a8SAndroid Build Coastguard Worker                 globals().pendingReadsLooperThread = std::thread(&pendingReadsLooperThread);
860*9190c2a8SAndroid Build Coastguard Worker             }
861*9190c2a8SAndroid Build Coastguard Worker         }
862*9190c2a8SAndroid Build Coastguard Worker 
863*9190c2a8SAndroid Build Coastguard Worker         looper.addFd(control->pendingReads(), android::Looper::POLL_CALLBACK,
864*9190c2a8SAndroid Build Coastguard Worker                      android::Looper::EVENT_INPUT, &onPendingReadsLooperEvent,
865*9190c2a8SAndroid Build Coastguard Worker                      dataLoaderConnector.get());
866*9190c2a8SAndroid Build Coastguard Worker         looper.wake();
867*9190c2a8SAndroid Build Coastguard Worker     }
868*9190c2a8SAndroid Build Coastguard Worker 
869*9190c2a8SAndroid Build Coastguard Worker     if (control->logs() >= 0) {
870*9190c2a8SAndroid Build Coastguard Worker         auto&& looper = logLooper();
871*9190c2a8SAndroid Build Coastguard Worker         if (!globals().logLooperThread.joinable()) {
872*9190c2a8SAndroid Build Coastguard Worker             std::lock_guard lock{globals().dataLoaderConnectorsLock};
873*9190c2a8SAndroid Build Coastguard Worker             if (!globals().logLooperThread.joinable()) {
874*9190c2a8SAndroid Build Coastguard Worker                 globals().logLooperThread = std::thread(&logLooperThread);
875*9190c2a8SAndroid Build Coastguard Worker             }
876*9190c2a8SAndroid Build Coastguard Worker         }
877*9190c2a8SAndroid Build Coastguard Worker 
878*9190c2a8SAndroid Build Coastguard Worker         looper.addFd(control->logs(), android::Looper::POLL_CALLBACK, android::Looper::EVENT_INPUT,
879*9190c2a8SAndroid Build Coastguard Worker                      &onLogLooperEvent, dataLoaderConnector.get());
880*9190c2a8SAndroid Build Coastguard Worker         looper.wake();
881*9190c2a8SAndroid Build Coastguard Worker     }
882*9190c2a8SAndroid Build Coastguard Worker 
883*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
884*9190c2a8SAndroid Build Coastguard Worker     reportStatusViaCallback(env, listener, storageId, jni.constants.DATA_LOADER_STARTED);
885*9190c2a8SAndroid Build Coastguard Worker 
886*9190c2a8SAndroid Build Coastguard Worker     return true;
887*9190c2a8SAndroid Build Coastguard Worker }
888*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderService_OnStop_NoStatus(const UniqueControl * control,const DataLoaderConnectorPtr & dataLoaderConnector)889*9190c2a8SAndroid Build Coastguard Worker static void DataLoaderService_OnStop_NoStatus(const UniqueControl* control,
890*9190c2a8SAndroid Build Coastguard Worker                                               const DataLoaderConnectorPtr& dataLoaderConnector) {
891*9190c2a8SAndroid Build Coastguard Worker     if (control->pendingReads() >= 0) {
892*9190c2a8SAndroid Build Coastguard Worker         pendingReadsLooper().removeFd(control->pendingReads());
893*9190c2a8SAndroid Build Coastguard Worker         pendingReadsLooper().wake();
894*9190c2a8SAndroid Build Coastguard Worker     }
895*9190c2a8SAndroid Build Coastguard Worker     if (control->logs() >= 0) {
896*9190c2a8SAndroid Build Coastguard Worker         logLooper().removeFd(control->logs());
897*9190c2a8SAndroid Build Coastguard Worker         logLooper().wake();
898*9190c2a8SAndroid Build Coastguard Worker     }
899*9190c2a8SAndroid Build Coastguard Worker     dataLoaderConnector->onStop();
900*9190c2a8SAndroid Build Coastguard Worker }
901*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderService_OnStop(JNIEnv * env,jint storageId)902*9190c2a8SAndroid Build Coastguard Worker bool DataLoaderService_OnStop(JNIEnv* env, jint storageId) {
903*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnectorPtr dataLoaderConnector;
904*9190c2a8SAndroid Build Coastguard Worker     {
905*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{globals().dataLoaderConnectorsLock};
906*9190c2a8SAndroid Build Coastguard Worker         auto dlIt = globals().dataLoaderConnectors.find(storageId);
907*9190c2a8SAndroid Build Coastguard Worker         if (dlIt == globals().dataLoaderConnectors.end()) {
908*9190c2a8SAndroid Build Coastguard Worker             ALOGI("Failed to stop id(%d): not found", storageId);
909*9190c2a8SAndroid Build Coastguard Worker             return true;
910*9190c2a8SAndroid Build Coastguard Worker         }
911*9190c2a8SAndroid Build Coastguard Worker         dataLoaderConnector = dlIt->second;
912*9190c2a8SAndroid Build Coastguard Worker     }
913*9190c2a8SAndroid Build Coastguard Worker     const UniqueControl* control = &(dataLoaderConnector->control());
914*9190c2a8SAndroid Build Coastguard Worker     jobject listener = dataLoaderConnector->getListenerLocalRef(env);
915*9190c2a8SAndroid Build Coastguard Worker 
916*9190c2a8SAndroid Build Coastguard Worker     // Just stop.
917*9190c2a8SAndroid Build Coastguard Worker     DataLoaderService_OnStop_NoStatus(control, dataLoaderConnector);
918*9190c2a8SAndroid Build Coastguard Worker 
919*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
920*9190c2a8SAndroid Build Coastguard Worker     reportStatusViaCallback(env, listener, storageId, jni.constants.DATA_LOADER_STOPPED);
921*9190c2a8SAndroid Build Coastguard Worker 
922*9190c2a8SAndroid Build Coastguard Worker     return true;
923*9190c2a8SAndroid Build Coastguard Worker }
924*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderService_OnDestroy(JNIEnv * env,jint storageId)925*9190c2a8SAndroid Build Coastguard Worker bool DataLoaderService_OnDestroy(JNIEnv* env, jint storageId) {
926*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnectorPtr dataLoaderConnector;
927*9190c2a8SAndroid Build Coastguard Worker     {
928*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{globals().dataLoaderConnectorsLock};
929*9190c2a8SAndroid Build Coastguard Worker         auto dlIt = globals().dataLoaderConnectors.find(storageId);
930*9190c2a8SAndroid Build Coastguard Worker         if (dlIt == globals().dataLoaderConnectors.end()) {
931*9190c2a8SAndroid Build Coastguard Worker             ALOGI("Failed to destroy id(%d): not found", storageId);
932*9190c2a8SAndroid Build Coastguard Worker             return true;
933*9190c2a8SAndroid Build Coastguard Worker         }
934*9190c2a8SAndroid Build Coastguard Worker         dataLoaderConnector = std::move(dlIt->second);
935*9190c2a8SAndroid Build Coastguard Worker         globals().dataLoaderConnectors.erase(dlIt);
936*9190c2a8SAndroid Build Coastguard Worker     }
937*9190c2a8SAndroid Build Coastguard Worker     const UniqueControl* control = &(dataLoaderConnector->control());
938*9190c2a8SAndroid Build Coastguard Worker 
939*9190c2a8SAndroid Build Coastguard Worker     // Stop/destroy.
940*9190c2a8SAndroid Build Coastguard Worker     DataLoaderService_OnStop_NoStatus(control, dataLoaderConnector);
941*9190c2a8SAndroid Build Coastguard Worker     // This will destroy the last instance of the DataLoaderConnectorPtr and should trigger the
942*9190c2a8SAndroid Build Coastguard Worker     // destruction of the DataLoader. However if there are any hanging instances, the destruction
943*9190c2a8SAndroid Build Coastguard Worker     // will be postponed. E.g. OnPrepareImage in progress at the same time we call OnDestroy.
944*9190c2a8SAndroid Build Coastguard Worker     dataLoaderConnector = {};
945*9190c2a8SAndroid Build Coastguard Worker 
946*9190c2a8SAndroid Build Coastguard Worker     return true;
947*9190c2a8SAndroid Build Coastguard Worker }
948*9190c2a8SAndroid Build Coastguard Worker 
949*9190c2a8SAndroid Build Coastguard Worker struct DataLoaderInstallationFilesPair {
950*9190c2a8SAndroid Build Coastguard Worker     static DataLoaderInstallationFilesPair createFromManaged(JNIEnv* env, jobjectArray jfiles);
951*9190c2a8SAndroid Build Coastguard Worker 
952*9190c2a8SAndroid Build Coastguard Worker     using Files = std::vector<android::dataloader::DataLoaderInstallationFile>;
filesDataLoaderInstallationFilesPair953*9190c2a8SAndroid Build Coastguard Worker     const Files& files() const { return mFiles; }
954*9190c2a8SAndroid Build Coastguard Worker 
955*9190c2a8SAndroid Build Coastguard Worker     using NDKFiles = std::vector<::DataLoaderInstallationFile>;
ndkFilesDataLoaderInstallationFilesPair956*9190c2a8SAndroid Build Coastguard Worker     const NDKFiles& ndkFiles() const { return mNDKFiles; }
957*9190c2a8SAndroid Build Coastguard Worker 
958*9190c2a8SAndroid Build Coastguard Worker private:
959*9190c2a8SAndroid Build Coastguard Worker     DataLoaderInstallationFilesPair(Files&& files);
960*9190c2a8SAndroid Build Coastguard Worker 
961*9190c2a8SAndroid Build Coastguard Worker     Files mFiles;
962*9190c2a8SAndroid Build Coastguard Worker     NDKFiles mNDKFiles;
963*9190c2a8SAndroid Build Coastguard Worker };
964*9190c2a8SAndroid Build Coastguard Worker 
createFromManaged(JNIEnv * env,jobjectArray jfiles)965*9190c2a8SAndroid Build Coastguard Worker DataLoaderInstallationFilesPair DataLoaderInstallationFilesPair::createFromManaged(
966*9190c2a8SAndroid Build Coastguard Worker         JNIEnv* env, jobjectArray jfiles) {
967*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
968*9190c2a8SAndroid Build Coastguard Worker 
969*9190c2a8SAndroid Build Coastguard Worker     // jfiles is a Java array of InstallationFileParcel
970*9190c2a8SAndroid Build Coastguard Worker     auto size = env->GetArrayLength(jfiles);
971*9190c2a8SAndroid Build Coastguard Worker     DataLoaderInstallationFilesPair::Files files;
972*9190c2a8SAndroid Build Coastguard Worker     files.reserve(size);
973*9190c2a8SAndroid Build Coastguard Worker 
974*9190c2a8SAndroid Build Coastguard Worker     for (int i = 0; i < size; ++i) {
975*9190c2a8SAndroid Build Coastguard Worker         ScopedLocalRef<jobject> jfile(env, env->GetObjectArrayElement(jfiles, i));
976*9190c2a8SAndroid Build Coastguard Worker 
977*9190c2a8SAndroid Build Coastguard Worker         DataLoaderLocation location =
978*9190c2a8SAndroid Build Coastguard Worker                 (DataLoaderLocation)env->GetIntField(jfile.get(), jni.installationFileLocation);
979*9190c2a8SAndroid Build Coastguard Worker         ScopedUtfChars name(env, GetStringField(env, jfile.get(), jni.installationFileName));
980*9190c2a8SAndroid Build Coastguard Worker         IncFsSize size = env->GetLongField(jfile.get(), jni.installationFileLengthBytes);
981*9190c2a8SAndroid Build Coastguard Worker 
982*9190c2a8SAndroid Build Coastguard Worker         ScopedLocalRef<jbyteArray> jmetadataBytes(env,
983*9190c2a8SAndroid Build Coastguard Worker                                                   GetByteArrayField(env, jfile.get(),
984*9190c2a8SAndroid Build Coastguard Worker                                                                     jni.installationFileMetadata));
985*9190c2a8SAndroid Build Coastguard Worker         auto metadataElements = env->GetByteArrayElements(jmetadataBytes.get(), nullptr);
986*9190c2a8SAndroid Build Coastguard Worker         auto metadataLength = env->GetArrayLength(jmetadataBytes.get());
987*9190c2a8SAndroid Build Coastguard Worker         RawMetadata metadata(metadataElements, metadataElements + metadataLength);
988*9190c2a8SAndroid Build Coastguard Worker         env->ReleaseByteArrayElements(jmetadataBytes.get(), metadataElements, 0);
989*9190c2a8SAndroid Build Coastguard Worker 
990*9190c2a8SAndroid Build Coastguard Worker         files.emplace_back(location, name.c_str(), size, std::move(metadata));
991*9190c2a8SAndroid Build Coastguard Worker     }
992*9190c2a8SAndroid Build Coastguard Worker 
993*9190c2a8SAndroid Build Coastguard Worker     return DataLoaderInstallationFilesPair(std::move(files));
994*9190c2a8SAndroid Build Coastguard Worker }
995*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderInstallationFilesPair(Files && files)996*9190c2a8SAndroid Build Coastguard Worker DataLoaderInstallationFilesPair::DataLoaderInstallationFilesPair(Files&& files)
997*9190c2a8SAndroid Build Coastguard Worker       : mFiles(std::move(files)) {
998*9190c2a8SAndroid Build Coastguard Worker     const auto size = mFiles.size();
999*9190c2a8SAndroid Build Coastguard Worker     mNDKFiles.resize(size);
1000*9190c2a8SAndroid Build Coastguard Worker     for (size_t i = 0; i < size; ++i) {
1001*9190c2a8SAndroid Build Coastguard Worker         const auto& file = mFiles[i];
1002*9190c2a8SAndroid Build Coastguard Worker         auto&& ndkFile = mNDKFiles[i];
1003*9190c2a8SAndroid Build Coastguard Worker 
1004*9190c2a8SAndroid Build Coastguard Worker         ndkFile.location = file.location();
1005*9190c2a8SAndroid Build Coastguard Worker         ndkFile.name = file.name().c_str();
1006*9190c2a8SAndroid Build Coastguard Worker         ndkFile.size = file.size();
1007*9190c2a8SAndroid Build Coastguard Worker         ndkFile.metadata.data = file.metadata().data();
1008*9190c2a8SAndroid Build Coastguard Worker         ndkFile.metadata.size = file.metadata().size();
1009*9190c2a8SAndroid Build Coastguard Worker     }
1010*9190c2a8SAndroid Build Coastguard Worker }
1011*9190c2a8SAndroid Build Coastguard Worker 
DataLoaderService_OnPrepareImage(JNIEnv * env,jint storageId,jobjectArray addedFiles,jobjectArray removedFiles)1012*9190c2a8SAndroid Build Coastguard Worker bool DataLoaderService_OnPrepareImage(JNIEnv* env, jint storageId, jobjectArray addedFiles,
1013*9190c2a8SAndroid Build Coastguard Worker                                       jobjectArray removedFiles) {
1014*9190c2a8SAndroid Build Coastguard Worker     DataLoaderConnectorPtr dataLoaderConnector;
1015*9190c2a8SAndroid Build Coastguard Worker     {
1016*9190c2a8SAndroid Build Coastguard Worker         std::lock_guard lock{globals().dataLoaderConnectorsLock};
1017*9190c2a8SAndroid Build Coastguard Worker         auto dlIt = globals().dataLoaderConnectors.find(storageId);
1018*9190c2a8SAndroid Build Coastguard Worker         if (dlIt == globals().dataLoaderConnectors.end()) {
1019*9190c2a8SAndroid Build Coastguard Worker             ALOGE("Failed to handle onPrepareImage for id(%d): not found", storageId);
1020*9190c2a8SAndroid Build Coastguard Worker             return false;
1021*9190c2a8SAndroid Build Coastguard Worker         }
1022*9190c2a8SAndroid Build Coastguard Worker         dataLoaderConnector = dlIt->second;
1023*9190c2a8SAndroid Build Coastguard Worker     }
1024*9190c2a8SAndroid Build Coastguard Worker     jobject listener = dataLoaderConnector->getListenerLocalRef(env);
1025*9190c2a8SAndroid Build Coastguard Worker 
1026*9190c2a8SAndroid Build Coastguard Worker     auto addedFilesPair = DataLoaderInstallationFilesPair::createFromManaged(env, addedFiles);
1027*9190c2a8SAndroid Build Coastguard Worker     bool result = dataLoaderConnector->onPrepareImage(addedFilesPair.ndkFiles());
1028*9190c2a8SAndroid Build Coastguard Worker 
1029*9190c2a8SAndroid Build Coastguard Worker     const auto& jni = jniIds(env);
1030*9190c2a8SAndroid Build Coastguard Worker 
1031*9190c2a8SAndroid Build Coastguard Worker     if (checkAndClearJavaException(env, "onPrepareImage")) {
1032*9190c2a8SAndroid Build Coastguard Worker         reportStatusViaCallback(env, listener, storageId, jni.constants.DATA_LOADER_UNAVAILABLE);
1033*9190c2a8SAndroid Build Coastguard Worker         return false;
1034*9190c2a8SAndroid Build Coastguard Worker     }
1035*9190c2a8SAndroid Build Coastguard Worker 
1036*9190c2a8SAndroid Build Coastguard Worker     reportStatusViaCallback(env, listener, storageId,
1037*9190c2a8SAndroid Build Coastguard Worker                             result ? jni.constants.DATA_LOADER_IMAGE_READY
1038*9190c2a8SAndroid Build Coastguard Worker                                    : jni.constants.DATA_LOADER_IMAGE_NOT_READY);
1039*9190c2a8SAndroid Build Coastguard Worker 
1040*9190c2a8SAndroid Build Coastguard Worker     return result;
1041*9190c2a8SAndroid Build Coastguard Worker }
1042