• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define LOG_TAG "dataloader-manageddataloader"
17 
18 #include "ManagedDataLoader.h"
19 
20 #include <android-base/logging.h>
21 
22 #include "JNIHelpers.h"
23 
24 namespace android::dataloader {
25 
26 namespace {
27 
28 struct JniIds {
29     jclass dataLoaderParams;
30     jmethodID dataLoaderParamsConstruct;
31 
32     jclass fileSystemConnector;
33     jmethodID fileSystemConnectorConstruct;
34 
35     jmethodID dataLoaderServiceOnCreateDataLoader;
36 
37     jmethodID dataLoaderOnCreate;
38     jmethodID dataLoaderOnPrepareImage;
39 
40     jclass installationFile;
41     jmethodID installationFileCtor;
42 
43     jclass arrayList;
44     jmethodID arrayListCtor;
45     jmethodID arrayListAdd;
46 
JniIdsandroid::dataloader::__anon3d084ec20111::JniIds47     JniIds(JNIEnv* env) {
48         dataLoaderParams = (jclass)env->NewGlobalRef(
49                 FindClassOrDie(env, "android/content/pm/DataLoaderParams"));
50         dataLoaderParamsConstruct =
51                 GetMethodIDOrDie(env, dataLoaderParams, "<init>",
52                                  "(Landroid/content/pm/DataLoaderParamsParcel;)V");
53 
54         fileSystemConnector = (jclass)env->NewGlobalRef(
55                 FindClassOrDie(env,
56                                "android/service/dataloader/DataLoaderService$FileSystemConnector"));
57         fileSystemConnectorConstruct = GetMethodIDOrDie(env, fileSystemConnector, "<init>", "(J)V");
58 
59         auto dataLoaderService =
60                 FindClassOrDie(env, "android/service/dataloader/DataLoaderService");
61         dataLoaderServiceOnCreateDataLoader =
62                 GetMethodIDOrDie(env, dataLoaderService, "onCreateDataLoader",
63                                  "(Landroid/content/pm/DataLoaderParams;)Landroid/service/"
64                                  "dataloader/DataLoaderService$DataLoader;");
65 
66         auto dataLoader =
67                 FindClassOrDie(env, "android/service/dataloader/DataLoaderService$DataLoader");
68         dataLoaderOnCreate =
69                 GetMethodIDOrDie(env, dataLoader, "onCreate",
70                                  "(Landroid/content/pm/DataLoaderParams;Landroid/service/"
71                                  "dataloader/DataLoaderService$FileSystemConnector;)Z");
72         dataLoaderOnPrepareImage =
73                 GetMethodIDOrDie(env, dataLoader, "onPrepareImage",
74                                  "(Ljava/util/Collection;Ljava/util/Collection;)Z");
75 
76         arrayList = (jclass)env->NewGlobalRef(FindClassOrDie(env, "java/util/ArrayList"));
77         arrayListCtor = GetMethodIDOrDie(env, arrayList, "<init>", "(I)V");
78         arrayListAdd = GetMethodIDOrDie(env, arrayList, "add", "(Ljava/lang/Object;)Z");
79 
80         installationFile = (jclass)env->NewGlobalRef(
81                 FindClassOrDie(env, "android/content/pm/InstallationFile"));
82         installationFileCtor =
83                 GetMethodIDOrDie(env, installationFile, "<init>", "(ILjava/lang/String;J[B[B)V");
84     }
85 };
86 
jniIds(JNIEnv * env)87 const JniIds& jniIds(JNIEnv* env) {
88     static const JniIds ids(env);
89     return ids;
90 }
91 
92 } // namespace
93 
ManagedDataLoader(JavaVM * jvm,jobject dataLoader)94 ManagedDataLoader::ManagedDataLoader(JavaVM* jvm, jobject dataLoader)
95       : mJvm(jvm), mDataLoader(dataLoader) {
96     CHECK(mJvm);
97 
98     LegacyDataLoader::onStart = [](auto) -> bool { return true; };
99     LegacyDataLoader::onStop = [](auto) {};
100     LegacyDataLoader::onDestroy = [](LegacyDataLoader* self) {
101         auto me = static_cast<ManagedDataLoader*>(self);
102         me->onDestroy();
103         delete me;
104     };
105     LegacyDataLoader::onPrepareImage = [](auto* self, const auto addedFiles[],
106                                           int addedFilesCount) -> bool {
107         return static_cast<ManagedDataLoader*>(self)->onPrepareImage(
108                 DataLoaderInstallationFiles(addedFiles, addedFilesCount));
109     };
110     LegacyDataLoader::onPendingReads = [](auto, auto, auto) {};
111     LegacyDataLoader::onPageReads = [](auto, auto, auto) {};
112 }
113 
create(JavaVM * jvm,android::dataloader::FilesystemConnectorPtr ifs,android::dataloader::StatusListenerPtr listener,android::dataloader::ServiceConnectorPtr service,android::dataloader::ServiceParamsPtr params)114 LegacyDataLoader* ManagedDataLoader::create(JavaVM* jvm,
115                                             android::dataloader::FilesystemConnectorPtr ifs,
116                                             android::dataloader::StatusListenerPtr listener,
117                                             android::dataloader::ServiceConnectorPtr service,
118                                             android::dataloader::ServiceParamsPtr params) {
119     JNIEnv* env = GetJNIEnvironment(jvm);
120     const auto& jni = jniIds(env);
121 
122     jobject dlp = env->NewObject(jni.dataLoaderParams, jni.dataLoaderParamsConstruct, params);
123     jobject ifsc =
124             env->NewObject(jni.fileSystemConnector, jni.fileSystemConnectorConstruct, (jlong)ifs);
125 
126     auto dataLoader = env->CallObjectMethod(service, jni.dataLoaderServiceOnCreateDataLoader, dlp);
127     if (!dataLoader) {
128         LOG(ERROR) << "Failed to create Java DataLoader.";
129         return nullptr;
130     }
131     if (env->ExceptionCheck()) {
132         return nullptr;
133     }
134     if (!env->CallBooleanMethod(dataLoader, jni.dataLoaderOnCreate, dlp, ifsc)) {
135         return nullptr;
136     }
137 
138     return new ManagedDataLoader(jvm, env->NewGlobalRef(dataLoader));
139 }
140 
onDestroy()141 void ManagedDataLoader::onDestroy() {
142     CHECK(mDataLoader);
143 
144     JNIEnv* env = GetJNIEnvironment(mJvm);
145 
146     env->DeleteGlobalRef(mDataLoader);
147     mDataLoader = nullptr;
148 }
149 
toJavaArrayList(JNIEnv * env,const JniIds & jni,const DataLoaderInstallationFiles & files)150 static jobject toJavaArrayList(JNIEnv* env, const JniIds& jni,
151                                const DataLoaderInstallationFiles& files) {
152     jobject arrayList =
153             env->NewObject(jni.arrayList, jni.arrayListCtor, static_cast<jint>(files.size()));
154     for (const auto& file : files) {
155         const auto location(file.location);
156         const auto size(file.size);
157 
158         jstring name = env->NewStringUTF(file.name);
159         jbyteArray metadata = env->NewByteArray(file.metadata.size);
160         if (metadata != nullptr) {
161             env->SetByteArrayRegion(metadata, 0, file.metadata.size,
162                                     (const jbyte*)file.metadata.data);
163         }
164 
165         jobject jfile = env->NewObject(jni.installationFile, jni.installationFileCtor, location,
166                                        name, size, metadata, nullptr);
167         env->CallBooleanMethod(arrayList, jni.arrayListAdd, jfile);
168     }
169     return arrayList;
170 }
171 
onPrepareImage(DataLoaderInstallationFiles addedFiles)172 bool ManagedDataLoader::onPrepareImage(DataLoaderInstallationFiles addedFiles) {
173     CHECK(mDataLoader);
174 
175     auto env = GetOrAttachJNIEnvironment(mJvm);
176     const auto& jni = jniIds(env);
177 
178     jobject jaddedFiles = toJavaArrayList(env, jni, addedFiles);
179     return env->CallBooleanMethod(mDataLoader, jni.dataLoaderOnPrepareImage, jaddedFiles, nullptr);
180 }
181 
ManagedDataLoaderFactory()182 ManagedDataLoaderFactory::ManagedDataLoaderFactory() {
183     ::DataLoaderFactory::onCreate =
184             [](::DataLoaderFactory* self, const ::DataLoaderParams* ndkParams,
185                ::DataLoaderFilesystemConnectorPtr fsConnector,
186                ::DataLoaderStatusListenerPtr statusListener, ::DataLoaderServiceVmPtr vm,
187                ::DataLoaderServiceConnectorPtr serviceConnector,
188                ::DataLoaderServiceParamsPtr serviceParams) -> ::DataLoader* {
189         return reinterpret_cast<::DataLoader*>(
190                 ManagedDataLoader::create(vm, static_cast<FilesystemConnector*>(fsConnector),
191                                           static_cast<StatusListener*>(statusListener),
192                                           serviceConnector, serviceParams));
193     };
194 }
195 
196 } // namespace android::dataloader
197