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 47 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 87 const JniIds& jniIds(JNIEnv* env) { 88 static const JniIds ids(env); 89 return ids; 90 } 91 92 } // namespace 93 94 ManagedDataLoader::ManagedDataLoader(JavaVM* jvm) : mJvm(jvm) { 95 CHECK(mJvm); 96 } 97 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 125 void ManagedDataLoader::onDestroy() { 126 CHECK(mDataLoader); 127 128 JNIEnv* env = GetJNIEnvironment(mJvm); 129 130 env->DeleteGlobalRef(mDataLoader); 131 mDataLoader = nullptr; 132 } 133 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 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