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::__anonb0c510dd0111::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)94 ManagedDataLoader::ManagedDataLoader(JavaVM* jvm) : mJvm(jvm) {
95 CHECK(mJvm);
96 }
97
onCreate(const android::dataloader::DataLoaderParams &,android::dataloader::FilesystemConnectorPtr ifs,android::dataloader::StatusListenerPtr listener,android::dataloader::ServiceConnectorPtr service,android::dataloader::ServiceParamsPtr params)98 bool ManagedDataLoader::onCreate(const android::dataloader::DataLoaderParams&,
99 android::dataloader::FilesystemConnectorPtr ifs,
100 android::dataloader::StatusListenerPtr listener,
101 android::dataloader::ServiceConnectorPtr service,
102 android::dataloader::ServiceParamsPtr params) {
103 CHECK(!mDataLoader);
104
105 JNIEnv* env = GetJNIEnvironment(mJvm);
106 const auto& jni = jniIds(env);
107
108 jobject dlp = env->NewObject(jni.dataLoaderParams, jni.dataLoaderParamsConstruct, params);
109 jobject ifsc =
110 env->NewObject(jni.fileSystemConnector, jni.fileSystemConnectorConstruct, (jlong)ifs);
111
112 auto dataLoader = env->CallObjectMethod(service, jni.dataLoaderServiceOnCreateDataLoader, dlp);
113 if (!dataLoader) {
114 LOG(ERROR) << "Failed to create Java DataLoader.";
115 return false;
116 }
117 if (env->ExceptionCheck()) {
118 return false;
119 }
120
121 mDataLoader = env->NewGlobalRef(dataLoader);
122 return env->CallBooleanMethod(mDataLoader, jni.dataLoaderOnCreate, dlp, ifsc);
123 }
124
onDestroy()125 void ManagedDataLoader::onDestroy() {
126 CHECK(mDataLoader);
127
128 JNIEnv* env = GetJNIEnvironment(mJvm);
129
130 env->DeleteGlobalRef(mDataLoader);
131 mDataLoader = nullptr;
132 }
133
toJavaArrayList(JNIEnv * env,const JniIds & jni,const DataLoaderInstallationFiles & files)134 static jobject toJavaArrayList(JNIEnv* env, const JniIds& jni,
135 const DataLoaderInstallationFiles& files) {
136 jobject arrayList =
137 env->NewObject(jni.arrayList, jni.arrayListCtor, static_cast<jint>(files.size()));
138 for (const auto& file : files) {
139 const auto location(file.location);
140 const auto size(file.size);
141
142 jstring name = env->NewStringUTF(file.name);
143 jbyteArray metadata = env->NewByteArray(file.metadata.size);
144 if (metadata != nullptr) {
145 env->SetByteArrayRegion(metadata, 0, file.metadata.size,
146 (const jbyte*)file.metadata.data);
147 }
148
149 jobject jfile = env->NewObject(jni.installationFile, jni.installationFileCtor, location,
150 name, size, metadata, nullptr);
151 env->CallBooleanMethod(arrayList, jni.arrayListAdd, jfile);
152 }
153 return arrayList;
154 }
155
onPrepareImage(DataLoaderInstallationFiles addedFiles)156 bool ManagedDataLoader::onPrepareImage(DataLoaderInstallationFiles addedFiles) {
157 CHECK(mDataLoader);
158
159 auto env = GetOrAttachJNIEnvironment(mJvm);
160 const auto& jni = jniIds(env);
161
162 jobject jaddedFiles = toJavaArrayList(env, jni, addedFiles);
163 return env->CallBooleanMethod(mDataLoader, jni.dataLoaderOnPrepareImage, jaddedFiles, nullptr);
164 }
165
166 } // namespace android::dataloader
167