blob: 8f3e888c4175afe45372b162dd609d406eadb2e9 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "dataloader-manageddataloader"
#include "ManagedDataLoader.h"
#include <android-base/logging.h>
#include "JNIHelpers.h"
namespace android::dataloader {
namespace {
struct JniIds {
jclass dataLoaderParams;
jmethodID dataLoaderParamsConstruct;
jclass fileSystemConnector;
jmethodID fileSystemConnectorConstruct;
jmethodID dataLoaderServiceOnCreateDataLoader;
jmethodID dataLoaderOnCreate;
jmethodID dataLoaderOnPrepareImage;
jclass installationFile;
jmethodID installationFileCtor;
jclass arrayList;
jmethodID arrayListCtor;
jmethodID arrayListAdd;
JniIds(JNIEnv* env) {
dataLoaderParams = (jclass)env->NewGlobalRef(
FindClassOrDie(env, "android/content/pm/DataLoaderParams"));
dataLoaderParamsConstruct =
GetMethodIDOrDie(env, dataLoaderParams, "<init>",
"(Landroid/content/pm/DataLoaderParamsParcel;)V");
fileSystemConnector = (jclass)env->NewGlobalRef(
FindClassOrDie(env,
"android/service/dataloader/DataLoaderService$FileSystemConnector"));
fileSystemConnectorConstruct = GetMethodIDOrDie(env, fileSystemConnector, "<init>", "(J)V");
auto dataLoaderService =
FindClassOrDie(env, "android/service/dataloader/DataLoaderService");
dataLoaderServiceOnCreateDataLoader =
GetMethodIDOrDie(env, dataLoaderService, "onCreateDataLoader",
"(Landroid/content/pm/DataLoaderParams;)Landroid/service/"
"dataloader/DataLoaderService$DataLoader;");
auto dataLoader =
FindClassOrDie(env, "android/service/dataloader/DataLoaderService$DataLoader");
dataLoaderOnCreate =
GetMethodIDOrDie(env, dataLoader, "onCreate",
"(Landroid/content/pm/DataLoaderParams;Landroid/service/"
"dataloader/DataLoaderService$FileSystemConnector;)Z");
dataLoaderOnPrepareImage =
GetMethodIDOrDie(env, dataLoader, "onPrepareImage",
"(Ljava/util/Collection;Ljava/util/Collection;)Z");
arrayList = (jclass)env->NewGlobalRef(FindClassOrDie(env, "java/util/ArrayList"));
arrayListCtor = GetMethodIDOrDie(env, arrayList, "<init>", "(I)V");
arrayListAdd = GetMethodIDOrDie(env, arrayList, "add", "(Ljava/lang/Object;)Z");
installationFile = (jclass)env->NewGlobalRef(
FindClassOrDie(env, "android/content/pm/InstallationFile"));
installationFileCtor =
GetMethodIDOrDie(env, installationFile, "<init>", "(ILjava/lang/String;J[B[B)V");
}
};
const JniIds& jniIds(JNIEnv* env) {
static const JniIds ids(env);
return ids;
}
} // namespace
ManagedDataLoader::ManagedDataLoader(JavaVM* jvm) : mJvm(jvm) {
CHECK(mJvm);
}
bool ManagedDataLoader::onCreate(const android::dataloader::DataLoaderParams&,
android::dataloader::FilesystemConnectorPtr ifs,
android::dataloader::StatusListenerPtr listener,
android::dataloader::ServiceConnectorPtr service,
android::dataloader::ServiceParamsPtr params) {
CHECK(!mDataLoader);
JNIEnv* env = GetJNIEnvironment(mJvm);
const auto& jni = jniIds(env);
jobject dlp = env->NewObject(jni.dataLoaderParams, jni.dataLoaderParamsConstruct, params);
jobject ifsc =
env->NewObject(jni.fileSystemConnector, jni.fileSystemConnectorConstruct, (jlong)ifs);
auto dataLoader = env->CallObjectMethod(service, jni.dataLoaderServiceOnCreateDataLoader, dlp);
if (!dataLoader) {
LOG(ERROR) << "Failed to create Java DataLoader.";
return false;
}
if (env->ExceptionCheck()) {
return false;
}
mDataLoader = env->NewGlobalRef(dataLoader);
return env->CallBooleanMethod(mDataLoader, jni.dataLoaderOnCreate, dlp, ifsc);
}
void ManagedDataLoader::onDestroy() {
CHECK(mDataLoader);
JNIEnv* env = GetJNIEnvironment(mJvm);
env->DeleteGlobalRef(mDataLoader);
mDataLoader = nullptr;
}
static jobject toJavaArrayList(JNIEnv* env, const JniIds& jni,
const DataLoaderInstallationFiles& files) {
jobject arrayList =
env->NewObject(jni.arrayList, jni.arrayListCtor, static_cast<jint>(files.size()));
for (const auto& file : files) {
const auto location(file.location);
const auto size(file.size);
jstring name = env->NewStringUTF(file.name);
jbyteArray metadata = env->NewByteArray(file.metadata.size);
if (metadata != nullptr) {
env->SetByteArrayRegion(metadata, 0, file.metadata.size,
(const jbyte*)file.metadata.data);
}
jobject jfile = env->NewObject(jni.installationFile, jni.installationFileCtor, location,
name, size, metadata, nullptr);
env->CallBooleanMethod(arrayList, jni.arrayListAdd, jfile);
}
return arrayList;
}
bool ManagedDataLoader::onPrepareImage(DataLoaderInstallationFiles addedFiles) {
CHECK(mDataLoader);
auto env = GetOrAttachJNIEnvironment(mJvm);
const auto& jni = jniIds(env);
jobject jaddedFiles = toJavaArrayList(env, jni, addedFiles);
return env->CallBooleanMethod(mDataLoader, jni.dataLoaderOnPrepareImage, jaddedFiles, nullptr);
}
} // namespace android::dataloader