197 lines
7.7 KiB
C++
197 lines
7.7 KiB
C++
/*
|
|
* 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, jobject dataLoader)
|
|
: mJvm(jvm), mDataLoader(dataLoader) {
|
|
CHECK(mJvm);
|
|
|
|
LegacyDataLoader::onStart = [](auto) -> bool { return true; };
|
|
LegacyDataLoader::onStop = [](auto) {};
|
|
LegacyDataLoader::onDestroy = [](LegacyDataLoader* self) {
|
|
auto me = static_cast<ManagedDataLoader*>(self);
|
|
me->onDestroy();
|
|
delete me;
|
|
};
|
|
LegacyDataLoader::onPrepareImage = [](auto* self, const auto addedFiles[],
|
|
int addedFilesCount) -> bool {
|
|
return static_cast<ManagedDataLoader*>(self)->onPrepareImage(
|
|
DataLoaderInstallationFiles(addedFiles, addedFilesCount));
|
|
};
|
|
LegacyDataLoader::onPendingReads = [](auto, auto, auto) {};
|
|
LegacyDataLoader::onPageReads = [](auto, auto, auto) {};
|
|
}
|
|
|
|
LegacyDataLoader* ManagedDataLoader::create(JavaVM* jvm,
|
|
android::dataloader::FilesystemConnectorPtr ifs,
|
|
android::dataloader::StatusListenerPtr listener,
|
|
android::dataloader::ServiceConnectorPtr service,
|
|
android::dataloader::ServiceParamsPtr params) {
|
|
JNIEnv* env = GetJNIEnvironment(jvm);
|
|
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 nullptr;
|
|
}
|
|
if (env->ExceptionCheck()) {
|
|
return nullptr;
|
|
}
|
|
if (!env->CallBooleanMethod(dataLoader, jni.dataLoaderOnCreate, dlp, ifsc)) {
|
|
return nullptr;
|
|
}
|
|
|
|
return new ManagedDataLoader(jvm, env->NewGlobalRef(dataLoader));
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
ManagedDataLoaderFactory::ManagedDataLoaderFactory() {
|
|
::DataLoaderFactory::onCreate =
|
|
[](::DataLoaderFactory* self, const ::DataLoaderParams* ndkParams,
|
|
::DataLoaderFilesystemConnectorPtr fsConnector,
|
|
::DataLoaderStatusListenerPtr statusListener, ::DataLoaderServiceVmPtr vm,
|
|
::DataLoaderServiceConnectorPtr serviceConnector,
|
|
::DataLoaderServiceParamsPtr serviceParams) -> ::DataLoader* {
|
|
return reinterpret_cast<::DataLoader*>(
|
|
ManagedDataLoader::create(vm, static_cast<FilesystemConnector*>(fsConnector),
|
|
static_cast<StatusListener*>(statusListener),
|
|
serviceConnector, serviceParams));
|
|
};
|
|
}
|
|
|
|
} // namespace android::dataloader
|