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 "dataloader-manageddataloader"
17*9190c2a8SAndroid Build Coastguard Worker
18*9190c2a8SAndroid Build Coastguard Worker #include "ManagedDataLoader.h"
19*9190c2a8SAndroid Build Coastguard Worker
20*9190c2a8SAndroid Build Coastguard Worker #include <android-base/logging.h>
21*9190c2a8SAndroid Build Coastguard Worker
22*9190c2a8SAndroid Build Coastguard Worker #include "JNIHelpers.h"
23*9190c2a8SAndroid Build Coastguard Worker
24*9190c2a8SAndroid Build Coastguard Worker namespace android::dataloader {
25*9190c2a8SAndroid Build Coastguard Worker
26*9190c2a8SAndroid Build Coastguard Worker namespace {
27*9190c2a8SAndroid Build Coastguard Worker
28*9190c2a8SAndroid Build Coastguard Worker struct JniIds {
29*9190c2a8SAndroid Build Coastguard Worker jclass dataLoaderParams;
30*9190c2a8SAndroid Build Coastguard Worker jmethodID dataLoaderParamsConstruct;
31*9190c2a8SAndroid Build Coastguard Worker
32*9190c2a8SAndroid Build Coastguard Worker jclass fileSystemConnector;
33*9190c2a8SAndroid Build Coastguard Worker jmethodID fileSystemConnectorConstruct;
34*9190c2a8SAndroid Build Coastguard Worker
35*9190c2a8SAndroid Build Coastguard Worker jmethodID dataLoaderServiceOnCreateDataLoader;
36*9190c2a8SAndroid Build Coastguard Worker
37*9190c2a8SAndroid Build Coastguard Worker jmethodID dataLoaderOnCreate;
38*9190c2a8SAndroid Build Coastguard Worker jmethodID dataLoaderOnPrepareImage;
39*9190c2a8SAndroid Build Coastguard Worker
40*9190c2a8SAndroid Build Coastguard Worker jclass installationFile;
41*9190c2a8SAndroid Build Coastguard Worker jmethodID installationFileCtor;
42*9190c2a8SAndroid Build Coastguard Worker
43*9190c2a8SAndroid Build Coastguard Worker jclass arrayList;
44*9190c2a8SAndroid Build Coastguard Worker jmethodID arrayListCtor;
45*9190c2a8SAndroid Build Coastguard Worker jmethodID arrayListAdd;
46*9190c2a8SAndroid Build Coastguard Worker
JniIdsandroid::dataloader::__anon08990d530111::JniIds47*9190c2a8SAndroid Build Coastguard Worker JniIds(JNIEnv* env) {
48*9190c2a8SAndroid Build Coastguard Worker dataLoaderParams = (jclass)env->NewGlobalRef(
49*9190c2a8SAndroid Build Coastguard Worker FindClassOrDie(env, "android/content/pm/DataLoaderParams"));
50*9190c2a8SAndroid Build Coastguard Worker dataLoaderParamsConstruct =
51*9190c2a8SAndroid Build Coastguard Worker GetMethodIDOrDie(env, dataLoaderParams, "<init>",
52*9190c2a8SAndroid Build Coastguard Worker "(Landroid/content/pm/DataLoaderParamsParcel;)V");
53*9190c2a8SAndroid Build Coastguard Worker
54*9190c2a8SAndroid Build Coastguard Worker fileSystemConnector = (jclass)env->NewGlobalRef(
55*9190c2a8SAndroid Build Coastguard Worker FindClassOrDie(env,
56*9190c2a8SAndroid Build Coastguard Worker "android/service/dataloader/DataLoaderService$FileSystemConnector"));
57*9190c2a8SAndroid Build Coastguard Worker fileSystemConnectorConstruct = GetMethodIDOrDie(env, fileSystemConnector, "<init>", "(J)V");
58*9190c2a8SAndroid Build Coastguard Worker
59*9190c2a8SAndroid Build Coastguard Worker auto dataLoaderService =
60*9190c2a8SAndroid Build Coastguard Worker FindClassOrDie(env, "android/service/dataloader/DataLoaderService");
61*9190c2a8SAndroid Build Coastguard Worker dataLoaderServiceOnCreateDataLoader =
62*9190c2a8SAndroid Build Coastguard Worker GetMethodIDOrDie(env, dataLoaderService, "onCreateDataLoader",
63*9190c2a8SAndroid Build Coastguard Worker "(Landroid/content/pm/DataLoaderParams;)Landroid/service/"
64*9190c2a8SAndroid Build Coastguard Worker "dataloader/DataLoaderService$DataLoader;");
65*9190c2a8SAndroid Build Coastguard Worker
66*9190c2a8SAndroid Build Coastguard Worker auto dataLoader =
67*9190c2a8SAndroid Build Coastguard Worker FindClassOrDie(env, "android/service/dataloader/DataLoaderService$DataLoader");
68*9190c2a8SAndroid Build Coastguard Worker dataLoaderOnCreate =
69*9190c2a8SAndroid Build Coastguard Worker GetMethodIDOrDie(env, dataLoader, "onCreate",
70*9190c2a8SAndroid Build Coastguard Worker "(Landroid/content/pm/DataLoaderParams;Landroid/service/"
71*9190c2a8SAndroid Build Coastguard Worker "dataloader/DataLoaderService$FileSystemConnector;)Z");
72*9190c2a8SAndroid Build Coastguard Worker dataLoaderOnPrepareImage =
73*9190c2a8SAndroid Build Coastguard Worker GetMethodIDOrDie(env, dataLoader, "onPrepareImage",
74*9190c2a8SAndroid Build Coastguard Worker "(Ljava/util/Collection;Ljava/util/Collection;)Z");
75*9190c2a8SAndroid Build Coastguard Worker
76*9190c2a8SAndroid Build Coastguard Worker arrayList = (jclass)env->NewGlobalRef(FindClassOrDie(env, "java/util/ArrayList"));
77*9190c2a8SAndroid Build Coastguard Worker arrayListCtor = GetMethodIDOrDie(env, arrayList, "<init>", "(I)V");
78*9190c2a8SAndroid Build Coastguard Worker arrayListAdd = GetMethodIDOrDie(env, arrayList, "add", "(Ljava/lang/Object;)Z");
79*9190c2a8SAndroid Build Coastguard Worker
80*9190c2a8SAndroid Build Coastguard Worker installationFile = (jclass)env->NewGlobalRef(
81*9190c2a8SAndroid Build Coastguard Worker FindClassOrDie(env, "android/content/pm/InstallationFile"));
82*9190c2a8SAndroid Build Coastguard Worker installationFileCtor =
83*9190c2a8SAndroid Build Coastguard Worker GetMethodIDOrDie(env, installationFile, "<init>", "(ILjava/lang/String;J[B[B)V");
84*9190c2a8SAndroid Build Coastguard Worker }
85*9190c2a8SAndroid Build Coastguard Worker };
86*9190c2a8SAndroid Build Coastguard Worker
jniIds(JNIEnv * env)87*9190c2a8SAndroid Build Coastguard Worker const JniIds& jniIds(JNIEnv* env) {
88*9190c2a8SAndroid Build Coastguard Worker static const JniIds ids(env);
89*9190c2a8SAndroid Build Coastguard Worker return ids;
90*9190c2a8SAndroid Build Coastguard Worker }
91*9190c2a8SAndroid Build Coastguard Worker
92*9190c2a8SAndroid Build Coastguard Worker } // namespace
93*9190c2a8SAndroid Build Coastguard Worker
ManagedDataLoader(JavaVM * jvm,jobject dataLoader)94*9190c2a8SAndroid Build Coastguard Worker ManagedDataLoader::ManagedDataLoader(JavaVM* jvm, jobject dataLoader)
95*9190c2a8SAndroid Build Coastguard Worker : mJvm(jvm), mDataLoader(dataLoader) {
96*9190c2a8SAndroid Build Coastguard Worker CHECK(mJvm);
97*9190c2a8SAndroid Build Coastguard Worker
98*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader::onStart = [](auto) -> bool { return true; };
99*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader::onStop = [](auto) {};
100*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader::onDestroy = [](LegacyDataLoader* self) {
101*9190c2a8SAndroid Build Coastguard Worker auto me = static_cast<ManagedDataLoader*>(self);
102*9190c2a8SAndroid Build Coastguard Worker me->onDestroy();
103*9190c2a8SAndroid Build Coastguard Worker delete me;
104*9190c2a8SAndroid Build Coastguard Worker };
105*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader::onPrepareImage = [](auto* self, const auto addedFiles[],
106*9190c2a8SAndroid Build Coastguard Worker int addedFilesCount) -> bool {
107*9190c2a8SAndroid Build Coastguard Worker return static_cast<ManagedDataLoader*>(self)->onPrepareImage(
108*9190c2a8SAndroid Build Coastguard Worker DataLoaderInstallationFiles(addedFiles, addedFilesCount));
109*9190c2a8SAndroid Build Coastguard Worker };
110*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader::onPendingReads = [](auto, auto, auto) {};
111*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader::onPageReads = [](auto, auto, auto) {};
112*9190c2a8SAndroid Build Coastguard Worker }
113*9190c2a8SAndroid Build Coastguard Worker
create(JavaVM * jvm,android::dataloader::FilesystemConnectorPtr ifs,android::dataloader::StatusListenerPtr listener,android::dataloader::ServiceConnectorPtr service,android::dataloader::ServiceParamsPtr params)114*9190c2a8SAndroid Build Coastguard Worker LegacyDataLoader* ManagedDataLoader::create(JavaVM* jvm,
115*9190c2a8SAndroid Build Coastguard Worker android::dataloader::FilesystemConnectorPtr ifs,
116*9190c2a8SAndroid Build Coastguard Worker android::dataloader::StatusListenerPtr listener,
117*9190c2a8SAndroid Build Coastguard Worker android::dataloader::ServiceConnectorPtr service,
118*9190c2a8SAndroid Build Coastguard Worker android::dataloader::ServiceParamsPtr params) {
119*9190c2a8SAndroid Build Coastguard Worker JNIEnv* env = GetJNIEnvironment(jvm);
120*9190c2a8SAndroid Build Coastguard Worker const auto& jni = jniIds(env);
121*9190c2a8SAndroid Build Coastguard Worker
122*9190c2a8SAndroid Build Coastguard Worker jobject dlp = env->NewObject(jni.dataLoaderParams, jni.dataLoaderParamsConstruct, params);
123*9190c2a8SAndroid Build Coastguard Worker jobject ifsc =
124*9190c2a8SAndroid Build Coastguard Worker env->NewObject(jni.fileSystemConnector, jni.fileSystemConnectorConstruct, (jlong)ifs);
125*9190c2a8SAndroid Build Coastguard Worker
126*9190c2a8SAndroid Build Coastguard Worker auto dataLoader = env->CallObjectMethod(service, jni.dataLoaderServiceOnCreateDataLoader, dlp);
127*9190c2a8SAndroid Build Coastguard Worker if (!dataLoader) {
128*9190c2a8SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to create Java DataLoader.";
129*9190c2a8SAndroid Build Coastguard Worker return nullptr;
130*9190c2a8SAndroid Build Coastguard Worker }
131*9190c2a8SAndroid Build Coastguard Worker if (env->ExceptionCheck()) {
132*9190c2a8SAndroid Build Coastguard Worker return nullptr;
133*9190c2a8SAndroid Build Coastguard Worker }
134*9190c2a8SAndroid Build Coastguard Worker if (!env->CallBooleanMethod(dataLoader, jni.dataLoaderOnCreate, dlp, ifsc)) {
135*9190c2a8SAndroid Build Coastguard Worker return nullptr;
136*9190c2a8SAndroid Build Coastguard Worker }
137*9190c2a8SAndroid Build Coastguard Worker
138*9190c2a8SAndroid Build Coastguard Worker return new ManagedDataLoader(jvm, env->NewGlobalRef(dataLoader));
139*9190c2a8SAndroid Build Coastguard Worker }
140*9190c2a8SAndroid Build Coastguard Worker
onDestroy()141*9190c2a8SAndroid Build Coastguard Worker void ManagedDataLoader::onDestroy() {
142*9190c2a8SAndroid Build Coastguard Worker CHECK(mDataLoader);
143*9190c2a8SAndroid Build Coastguard Worker
144*9190c2a8SAndroid Build Coastguard Worker JNIEnv* env = GetJNIEnvironment(mJvm);
145*9190c2a8SAndroid Build Coastguard Worker
146*9190c2a8SAndroid Build Coastguard Worker env->DeleteGlobalRef(mDataLoader);
147*9190c2a8SAndroid Build Coastguard Worker mDataLoader = nullptr;
148*9190c2a8SAndroid Build Coastguard Worker }
149*9190c2a8SAndroid Build Coastguard Worker
toJavaArrayList(JNIEnv * env,const JniIds & jni,const DataLoaderInstallationFiles & files)150*9190c2a8SAndroid Build Coastguard Worker static jobject toJavaArrayList(JNIEnv* env, const JniIds& jni,
151*9190c2a8SAndroid Build Coastguard Worker const DataLoaderInstallationFiles& files) {
152*9190c2a8SAndroid Build Coastguard Worker jobject arrayList =
153*9190c2a8SAndroid Build Coastguard Worker env->NewObject(jni.arrayList, jni.arrayListCtor, static_cast<jint>(files.size()));
154*9190c2a8SAndroid Build Coastguard Worker for (const auto& file : files) {
155*9190c2a8SAndroid Build Coastguard Worker const auto location(file.location);
156*9190c2a8SAndroid Build Coastguard Worker const auto size(file.size);
157*9190c2a8SAndroid Build Coastguard Worker
158*9190c2a8SAndroid Build Coastguard Worker jstring name = env->NewStringUTF(file.name);
159*9190c2a8SAndroid Build Coastguard Worker jbyteArray metadata = env->NewByteArray(file.metadata.size);
160*9190c2a8SAndroid Build Coastguard Worker if (metadata != nullptr) {
161*9190c2a8SAndroid Build Coastguard Worker env->SetByteArrayRegion(metadata, 0, file.metadata.size,
162*9190c2a8SAndroid Build Coastguard Worker (const jbyte*)file.metadata.data);
163*9190c2a8SAndroid Build Coastguard Worker }
164*9190c2a8SAndroid Build Coastguard Worker
165*9190c2a8SAndroid Build Coastguard Worker jobject jfile = env->NewObject(jni.installationFile, jni.installationFileCtor, location,
166*9190c2a8SAndroid Build Coastguard Worker name, size, metadata, nullptr);
167*9190c2a8SAndroid Build Coastguard Worker env->CallBooleanMethod(arrayList, jni.arrayListAdd, jfile);
168*9190c2a8SAndroid Build Coastguard Worker }
169*9190c2a8SAndroid Build Coastguard Worker return arrayList;
170*9190c2a8SAndroid Build Coastguard Worker }
171*9190c2a8SAndroid Build Coastguard Worker
onPrepareImage(DataLoaderInstallationFiles addedFiles)172*9190c2a8SAndroid Build Coastguard Worker bool ManagedDataLoader::onPrepareImage(DataLoaderInstallationFiles addedFiles) {
173*9190c2a8SAndroid Build Coastguard Worker CHECK(mDataLoader);
174*9190c2a8SAndroid Build Coastguard Worker
175*9190c2a8SAndroid Build Coastguard Worker auto env = GetOrAttachJNIEnvironment(mJvm);
176*9190c2a8SAndroid Build Coastguard Worker const auto& jni = jniIds(env);
177*9190c2a8SAndroid Build Coastguard Worker
178*9190c2a8SAndroid Build Coastguard Worker jobject jaddedFiles = toJavaArrayList(env, jni, addedFiles);
179*9190c2a8SAndroid Build Coastguard Worker return env->CallBooleanMethod(mDataLoader, jni.dataLoaderOnPrepareImage, jaddedFiles, nullptr);
180*9190c2a8SAndroid Build Coastguard Worker }
181*9190c2a8SAndroid Build Coastguard Worker
ManagedDataLoaderFactory()182*9190c2a8SAndroid Build Coastguard Worker ManagedDataLoaderFactory::ManagedDataLoaderFactory() {
183*9190c2a8SAndroid Build Coastguard Worker ::DataLoaderFactory::onCreate =
184*9190c2a8SAndroid Build Coastguard Worker [](::DataLoaderFactory* self, const ::DataLoaderParams* ndkParams,
185*9190c2a8SAndroid Build Coastguard Worker ::DataLoaderFilesystemConnectorPtr fsConnector,
186*9190c2a8SAndroid Build Coastguard Worker ::DataLoaderStatusListenerPtr statusListener, ::DataLoaderServiceVmPtr vm,
187*9190c2a8SAndroid Build Coastguard Worker ::DataLoaderServiceConnectorPtr serviceConnector,
188*9190c2a8SAndroid Build Coastguard Worker ::DataLoaderServiceParamsPtr serviceParams) -> ::DataLoader* {
189*9190c2a8SAndroid Build Coastguard Worker return reinterpret_cast<::DataLoader*>(
190*9190c2a8SAndroid Build Coastguard Worker ManagedDataLoader::create(vm, static_cast<FilesystemConnector*>(fsConnector),
191*9190c2a8SAndroid Build Coastguard Worker static_cast<StatusListener*>(statusListener),
192*9190c2a8SAndroid Build Coastguard Worker serviceConnector, serviceParams));
193*9190c2a8SAndroid Build Coastguard Worker };
194*9190c2a8SAndroid Build Coastguard Worker }
195*9190c2a8SAndroid Build Coastguard Worker
196*9190c2a8SAndroid Build Coastguard Worker } // namespace android::dataloader
197