xref: /aosp_15_r20/frameworks/base/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2022 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 
17 #include <dlfcn.h>
18 
19 #include <optional>
20 
21 #define LOG_TAG "OverlayManagerImpl"
22 
23 #include "android-base/no_destructor.h"
24 #include "androidfw/ResourceTypes.h"
25 #include "core_jni_helpers.h"
26 #include "jni.h"
27 
28 namespace android {
29 
30 static struct fabricated_overlay_internal_offsets_t {
31     jclass classObject;
32     jfieldID packageName;
33     jfieldID overlayName;
34     jfieldID targetPackageName;
35     jfieldID targetOverlayable;
36     jfieldID entries;
37 } gFabricatedOverlayInternalOffsets;
38 
39 static struct fabricated_overlay_internal_entry_offsets_t {
40     jclass classObject;
41     jfieldID resourceName;
42     jfieldID dataType;
43     jfieldID data;
44     jfieldID stringData;
45     jfieldID binaryData;
46     jfieldID configuration;
47     jfieldID binaryDataOffset;
48     jfieldID binaryDataSize;
49     jfieldID isNinePatch;
50 } gFabricatedOverlayInternalEntryOffsets;
51 
52 static struct parcel_file_descriptor_offsets_t {
53     jclass classObject;
54     jmethodID getFd;
55 } gParcelFileDescriptorOffsets;
56 
57 static struct List_offsets_t {
58     jclass classObject;
59     jmethodID size;
60     jmethodID get;
61 } gListOffsets;
62 
63 static struct fabricated_overlay_info_offsets_t {
64     jclass classObject;
65     jmethodID constructor;
66     jfieldID packageName;
67     jfieldID overlayName;
68     jfieldID targetPackageName;
69     jfieldID targetOverlayable;
70     jfieldID path;
71 } gFabricatedOverlayInfoOffsets;
72 
73 namespace self_targeting {
74 
75 constexpr const char kIOException[] = "java/io/IOException";
76 constexpr const char IllegalArgumentException[] = "java/lang/IllegalArgumentException";
77 
78 class DynamicLibraryLoader {
79 public:
DynamicLibraryLoader(JNIEnv * env)80     explicit DynamicLibraryLoader(JNIEnv* env) {
81         /* For SelfTargeting, there are 2 types of files to be handled. One is frro and the other is
82          * idmap. For creating frro/idmap files and reading frro files, it needs libandroid_runtime
83          * to do a shared link to libidmap2. However, libidmap2 contains the codes generated from
84          * google protocol buffer. When libandroid_runtime does a shared link to libidmap2, it will
85          * impact the memory for system_server and zygote(a.k.a. all applications).
86          *
87          * Not all applications need to either create/read frro files or create idmap files all the
88          * time. When the apps apply the SelfTargeting overlay effect, it only needs libandroifw
89          * that is loaded. To use dlopen(libidmap2.so) is to make sure that applications don't
90          * impact themselves' memory by loading libidmap2 until they need to create/read frro files
91          * or create idmap files.
92          */
93         handle_ = dlopen("libidmap2.so", RTLD_NOW);
94         if (handle_ == nullptr) {
95             jniThrowNullPointerException(env);
96             return;
97         }
98 
99         createIdmapFileFuncPtr_ =
100                 reinterpret_cast<CreateIdmapFileFunc>(dlsym(handle_, "CreateIdmapFile"));
101         if (createIdmapFileFuncPtr_ == nullptr) {
102             jniThrowNullPointerException(env, "The symbol CreateIdmapFile is not found.");
103             return;
104         }
105         getFabricatedOverlayInfoFuncPtr_ = reinterpret_cast<GetFabricatedOverlayInfoFunc>(
106                 dlsym(handle_, "GetFabricatedOverlayInfo"));
107         if (getFabricatedOverlayInfoFuncPtr_ == nullptr) {
108             jniThrowNullPointerException(env, "The symbol GetFabricatedOverlayInfo is not found.");
109             return;
110         }
111         createFrroFile_ = reinterpret_cast<CreateFrroFileFunc>(dlsym(handle_, "CreateFrroFile"));
112         if (createFrroFile_ == nullptr) {
113             jniThrowNullPointerException(env, "The symbol CreateFrroFile is not found.");
114             return;
115         }
116     }
117 
callCreateFrroFile(std::string & out_error,const std::string & packageName,const std::string & overlayName,const std::string & targetPackageName,const std::optional<std::string> & targetOverlayable,const std::vector<FabricatedOverlayEntryParameters> & entries_params,const std::string & frro_file_path)118     bool callCreateFrroFile(std::string& out_error, const std::string& packageName,
119                             const std::string& overlayName, const std::string& targetPackageName,
120                             const std::optional<std::string>& targetOverlayable,
121                             const std::vector<FabricatedOverlayEntryParameters>& entries_params,
122                             const std::string& frro_file_path) {
123         return createFrroFile_(out_error, packageName, overlayName, targetPackageName,
124                                targetOverlayable, entries_params, frro_file_path);
125     }
126 
callCreateIdmapFile(std::string & out_error,const std::string & targetPath,const std::string & overlayPath,const std::string & idmapPath,const std::string & overlayName,const bool isSystem,const bool isVendor,const bool isProduct,const bool isTargetSignature,const bool isOdm,const bool isOem)127     bool callCreateIdmapFile(std::string& out_error, const std::string& targetPath,
128                              const std::string& overlayPath, const std::string& idmapPath,
129                              const std::string& overlayName, const bool isSystem,
130                              const bool isVendor, const bool isProduct,
131                              const bool isTargetSignature, const bool isOdm, const bool isOem) {
132         return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName,
133                                        isSystem, isVendor, isProduct, isTargetSignature, isOdm,
134                                        isOem);
135     }
136 
callGetFabricatedOverlayInfo(std::string & out_error,const std::string & overlay_path,OverlayManifestInfo & out_overlay_manifest_info)137     bool callGetFabricatedOverlayInfo(std::string& out_error, const std::string& overlay_path,
138                                       OverlayManifestInfo& out_overlay_manifest_info) {
139         return getFabricatedOverlayInfoFuncPtr_(out_error, overlay_path, out_overlay_manifest_info);
140     }
141 
operator bool() const142     explicit operator bool() const {
143         return handle_ != nullptr && createFrroFile_ != nullptr &&
144                 createIdmapFileFuncPtr_ != nullptr && getFabricatedOverlayInfoFuncPtr_ != nullptr;
145     }
146 
147     DynamicLibraryLoader(const DynamicLibraryLoader&) = delete;
148 
149     DynamicLibraryLoader& operator=(const DynamicLibraryLoader&) = delete;
150 
~DynamicLibraryLoader()151     ~DynamicLibraryLoader() {
152         if (handle_ != nullptr) {
153             dlclose(handle_);
154         }
155     }
156 
157 private:
158     typedef bool (*CreateFrroFileFunc)(
159             std::string& out_error, const std::string& packageName, const std::string& overlayName,
160             const std::string& targetPackageName,
161             const std::optional<std::string>& targetOverlayable,
162             const std::vector<FabricatedOverlayEntryParameters>& entries_params,
163             const std::string& frro_file_path);
164 
165     typedef bool (*CreateIdmapFileFunc)(std::string& out_error, const std::string& targetPath,
166                                         const std::string& overlayPath,
167                                         const std::string& idmapPath,
168                                         const std::string& overlayName, const jboolean isSystem,
169                                         const jboolean isVendor, const jboolean isProduct,
170                                         const jboolean isSameWithTargetSignature,
171                                         const jboolean isOdm, const jboolean isOem);
172 
173     typedef bool (*GetFabricatedOverlayInfoFunc)(std::string& out_error,
174                                                  const std::string& overlay_path,
175                                                  OverlayManifestInfo& out_overlay_manifest_info);
176 
177     void* handle_;
178     CreateFrroFileFunc createFrroFile_;
179     CreateIdmapFileFunc createIdmapFileFuncPtr_;
180     GetFabricatedOverlayInfoFunc getFabricatedOverlayInfoFuncPtr_;
181 };
182 
EnsureDynamicLibraryLoader(JNIEnv * env)183 static DynamicLibraryLoader& EnsureDynamicLibraryLoader(JNIEnv* env) {
184     static android::base::NoDestructor<DynamicLibraryLoader> loader(env);
185     return *loader;
186 }
187 
getNullableString(JNIEnv * env,jobject object,jfieldID field)188 static std::optional<std::string> getNullableString(JNIEnv* env, jobject object, jfieldID field) {
189     auto javaString = reinterpret_cast<jstring>(env->GetObjectField(object, field));
190     if (javaString == nullptr) {
191         return std::nullopt;
192     }
193 
194     const ScopedUtfChars result(env, javaString);
195     if (result.c_str() == nullptr) {
196         return std::nullopt;
197     }
198 
199     return std::optional<std::string>{result.c_str()};
200 }
201 
getNullableFileDescriptor(JNIEnv * env,jobject object,jfieldID field)202 static std::optional<android::base::borrowed_fd> getNullableFileDescriptor(JNIEnv* env,
203                                                                            jobject object,
204                                                                            jfieldID field) {
205     auto binaryData = env->GetObjectField(object, field);
206     if (binaryData == nullptr) {
207         return std::nullopt;
208     }
209 
210     return env->CallIntMethod(binaryData, gParcelFileDescriptorOffsets.getFd);
211 }
212 
CreateFrroFile(JNIEnv * env,jclass,jstring jsFrroFilePath,jobject overlay)213 static void CreateFrroFile(JNIEnv* env, jclass /*clazz*/, jstring jsFrroFilePath, jobject overlay) {
214     DynamicLibraryLoader& dlLoader = EnsureDynamicLibraryLoader(env);
215     if (!dlLoader) {
216         jniThrowNullPointerException(env, "libidmap2 is not loaded");
217         return;
218     }
219 
220     if (overlay == nullptr) {
221         jniThrowNullPointerException(env, "overlay is null");
222         return;
223     }
224     auto jsPackageName =
225             (jstring)env->GetObjectField(overlay, gFabricatedOverlayInternalOffsets.packageName);
226     const ScopedUtfChars packageName(env, jsPackageName);
227     if (packageName.c_str() == nullptr) {
228         jniThrowNullPointerException(env, "packageName is null");
229         return;
230     }
231     auto jsOverlayName =
232             (jstring)env->GetObjectField(overlay, gFabricatedOverlayInternalOffsets.overlayName);
233     const ScopedUtfChars overlayName(env, jsOverlayName);
234     if (overlayName.c_str() == nullptr) {
235         jniThrowNullPointerException(env, "overlayName is null");
236         return;
237     }
238     auto jsTargetPackageName =
239             (jstring)env->GetObjectField(overlay,
240                                          gFabricatedOverlayInternalOffsets.targetPackageName);
241     const ScopedUtfChars targetPackageName(env, jsTargetPackageName);
242     if (targetPackageName.c_str() == nullptr) {
243         jniThrowNullPointerException(env, "targetPackageName is null");
244         return;
245     }
246     auto overlayable =
247             getNullableString(env, overlay, gFabricatedOverlayInternalOffsets.targetOverlayable);
248     const ScopedUtfChars frroFilePath(env, jsFrroFilePath);
249     if (frroFilePath.c_str() == nullptr) {
250         jniThrowNullPointerException(env, "frroFilePath is null");
251         return;
252     }
253     jobject entries = env->GetObjectField(overlay, gFabricatedOverlayInternalOffsets.entries);
254     if (entries == nullptr) {
255         jniThrowNullPointerException(env, "overlay entries is null");
256         return;
257     }
258     const jint size = env->CallIntMethod(entries, gListOffsets.size);
259     ALOGV("frroFilePath = %s, packageName = %s, overlayName = %s, targetPackageName = %s,"
260           " targetOverlayable = %s, size = %d",
261           frroFilePath.c_str(), packageName.c_str(), overlayName.c_str(), targetPackageName.c_str(),
262           overlayable.value_or(std::string()).c_str(), size);
263 
264     std::vector<FabricatedOverlayEntryParameters> entries_params;
265     for (jint i = 0; i < size; i++) {
266         jobject entry = env->CallObjectMethod(entries, gListOffsets.get, i);
267         auto jsResourceName = reinterpret_cast<jstring>(
268                 env->GetObjectField(entry, gFabricatedOverlayInternalEntryOffsets.resourceName));
269         const ScopedUtfChars resourceName(env, jsResourceName);
270         const jint dataType =
271                 env->GetIntField(entry, gFabricatedOverlayInternalEntryOffsets.dataType);
272 
273         // In Java, the data type is int but the maximum value of data Type is less than 0xff.
274         if (dataType >= static_cast<jint>(UCHAR_MAX)) {
275             jniThrowException(env, IllegalArgumentException, "Unsupported data type");
276             return;
277         }
278 
279         const auto data = env->GetIntField(entry, gFabricatedOverlayInternalEntryOffsets.data);
280         auto configuration =
281                 getNullableString(env, entry, gFabricatedOverlayInternalEntryOffsets.configuration);
282         auto string_data =
283                 getNullableString(env, entry, gFabricatedOverlayInternalEntryOffsets.stringData);
284         auto binary_data =
285                 getNullableFileDescriptor(env, entry,
286                                           gFabricatedOverlayInternalEntryOffsets.binaryData);
287 
288         const auto data_offset =
289                 env->GetLongField(entry, gFabricatedOverlayInternalEntryOffsets.binaryDataOffset);
290         const auto data_size =
291                 env->GetLongField(entry, gFabricatedOverlayInternalEntryOffsets.binaryDataSize);
292         const auto nine_patch =
293                 env->GetBooleanField(entry, gFabricatedOverlayInternalEntryOffsets.isNinePatch);
294         entries_params.push_back(
295                 FabricatedOverlayEntryParameters{resourceName.c_str(), (DataType)dataType,
296                                                  (DataValue)data,
297                                                  string_data.value_or(std::string()), binary_data,
298                                                  static_cast<off64_t>(data_offset),
299                                                  static_cast<size_t>(data_size),
300                                                  configuration.value_or(std::string()),
301                                                  static_cast<bool>(nine_patch)});
302         ALOGV("resourceName = %s, dataType = 0x%08x, data = 0x%08x, dataString = %s,"
303               " binaryData = %d, configuration = %s",
304               resourceName.c_str(), dataType, data, string_data.value_or(std::string()).c_str(),
305               binary_data.has_value(), configuration.value_or(std::string()).c_str());
306     }
307 
308     std::string err_result;
309     if (!dlLoader.callCreateFrroFile(err_result, packageName.c_str(), overlayName.c_str(),
310                                      targetPackageName.c_str(), overlayable, entries_params,
311                                      frroFilePath.c_str())) {
312         jniThrowException(env, IllegalArgumentException, err_result.c_str());
313         return;
314     }
315 }
316 
CreateIdmapFile(JNIEnv * env,jclass,jstring jsTargetPath,jstring jsOverlayPath,jstring jsIdmapPath,jstring jsOverlayName,jboolean isSystem,jboolean isVendor,jboolean isProduct,jboolean isTargetSignature,jboolean isOdm,jboolean isOem)317 static void CreateIdmapFile(JNIEnv* env, jclass /* clazz */, jstring jsTargetPath,
318                             jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName,
319                             jboolean isSystem, jboolean isVendor, jboolean isProduct,
320                             jboolean isTargetSignature, jboolean isOdm, jboolean isOem) {
321     DynamicLibraryLoader& dlLoader = EnsureDynamicLibraryLoader(env);
322     if (!dlLoader) {
323         jniThrowNullPointerException(env, "libidmap2 is not loaded");
324         return;
325     }
326 
327     const ScopedUtfChars targetPath(env, jsTargetPath);
328     if (targetPath.c_str() == nullptr) {
329         jniThrowNullPointerException(env, "targetPath is null");
330         return;
331     }
332     const ScopedUtfChars overlayPath(env, jsOverlayPath);
333     if (overlayPath.c_str() == nullptr) {
334         jniThrowNullPointerException(env, "overlayPath is null");
335         return;
336     }
337     const ScopedUtfChars idmapPath(env, jsIdmapPath);
338     if (idmapPath.c_str() == nullptr) {
339         jniThrowNullPointerException(env, "idmapPath is null");
340         return;
341     }
342     const ScopedUtfChars overlayName(env, jsOverlayName);
343     if (overlayName.c_str() == nullptr) {
344         jniThrowNullPointerException(env, "overlayName is null");
345         return;
346     }
347     ALOGV("target_path = %s, overlay_path = %s, idmap_path = %s, overlay_name = %s",
348           targetPath.c_str(), overlayPath.c_str(), idmapPath.c_str(), overlayName.c_str());
349 
350     std::string err_result;
351     if (!dlLoader.callCreateIdmapFile(err_result, targetPath.c_str(), overlayPath.c_str(),
352                                       idmapPath.c_str(), overlayName.c_str(),
353                                       (isSystem == JNI_TRUE), (isVendor == JNI_TRUE),
354                                       (isProduct == JNI_TRUE), (isTargetSignature == JNI_TRUE),
355                                       (isOdm == JNI_TRUE), (isOem == JNI_TRUE))) {
356         jniThrowException(env, kIOException, err_result.c_str());
357         return;
358     }
359 }
360 
GetFabricatedOverlayInfo(JNIEnv * env,jclass,jstring jsOverlayPath)361 static jobject GetFabricatedOverlayInfo(JNIEnv* env, jclass /* clazz */, jstring jsOverlayPath) {
362     const ScopedUtfChars overlay_path(env, jsOverlayPath);
363     if (overlay_path.c_str() == nullptr) {
364         jniThrowNullPointerException(env, "overlay_path is null");
365         return nullptr;
366     }
367     ALOGV("overlay_path = %s", overlay_path.c_str());
368 
369     DynamicLibraryLoader& dlLoader = EnsureDynamicLibraryLoader(env);
370     if (!dlLoader) {
371         return nullptr;
372     }
373 
374     std::string err_result;
375     OverlayManifestInfo overlay_manifest_info;
376     if (!dlLoader.callGetFabricatedOverlayInfo(err_result, overlay_path.c_str(),
377                                                overlay_manifest_info) != 0) {
378         jniThrowException(env, kIOException, err_result.c_str());
379         return nullptr;
380     }
381     jobject info = env->NewObject(gFabricatedOverlayInfoOffsets.classObject,
382                                   gFabricatedOverlayInfoOffsets.constructor);
383     jstring jsOverName = env->NewStringUTF(overlay_manifest_info.name.c_str());
384     jstring jsPackageName = env->NewStringUTF(overlay_manifest_info.package_name.c_str());
385     jstring jsTargetPackage = env->NewStringUTF(overlay_manifest_info.target_package.c_str());
386     jstring jsTargetOverlayable = env->NewStringUTF(overlay_manifest_info.target_name.c_str());
387     env->SetObjectField(info, gFabricatedOverlayInfoOffsets.overlayName, jsOverName);
388     env->SetObjectField(info, gFabricatedOverlayInfoOffsets.packageName, jsPackageName);
389     env->SetObjectField(info, gFabricatedOverlayInfoOffsets.targetPackageName, jsTargetPackage);
390     env->SetObjectField(info, gFabricatedOverlayInfoOffsets.targetOverlayable, jsTargetOverlayable);
391     env->SetObjectField(info, gFabricatedOverlayInfoOffsets.path, jsOverlayPath);
392     return info;
393 }
394 
395 } // namespace self_targeting
396 
397 // JNI registration.
398 static const JNINativeMethod gOverlayManagerMethods[] = {
399         {"createFrroFile", "(Ljava/lang/String;Landroid/os/FabricatedOverlayInternal;)V",
400          reinterpret_cast<void*>(self_targeting::CreateFrroFile)},
401         {"createIdmapFile",
402          "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZZZZ)V",
403          reinterpret_cast<void*>(self_targeting::CreateIdmapFile)},
404         {"getFabricatedOverlayInfo", "(Ljava/lang/String;)Landroid/os/FabricatedOverlayInfo;",
405          reinterpret_cast<void*>(self_targeting::GetFabricatedOverlayInfo)},
406 };
407 
register_com_android_internal_content_om_OverlayManagerImpl(JNIEnv * env)408 int register_com_android_internal_content_om_OverlayManagerImpl(JNIEnv* env) {
409     jclass ListClass = FindClassOrDie(env, "java/util/List");
410     gListOffsets.classObject = MakeGlobalRefOrDie(env, ListClass);
411     gListOffsets.size = GetMethodIDOrDie(env, gListOffsets.classObject, "size", "()I");
412     gListOffsets.get =
413             GetMethodIDOrDie(env, gListOffsets.classObject, "get", "(I)Ljava/lang/Object;");
414 
415     jclass fabricatedOverlayInternalClass =
416             FindClassOrDie(env, "android/os/FabricatedOverlayInternal");
417     gFabricatedOverlayInternalOffsets.classObject =
418             MakeGlobalRefOrDie(env, fabricatedOverlayInternalClass);
419     gFabricatedOverlayInternalOffsets.packageName =
420             GetFieldIDOrDie(env, gFabricatedOverlayInternalOffsets.classObject, "packageName",
421                             "Ljava/lang/String;");
422     gFabricatedOverlayInternalOffsets.overlayName =
423             GetFieldIDOrDie(env, gFabricatedOverlayInternalOffsets.classObject, "overlayName",
424                             "Ljava/lang/String;");
425     gFabricatedOverlayInternalOffsets.targetPackageName =
426             GetFieldIDOrDie(env, gFabricatedOverlayInternalOffsets.classObject, "targetPackageName",
427                             "Ljava/lang/String;");
428     gFabricatedOverlayInternalOffsets.targetOverlayable =
429             GetFieldIDOrDie(env, gFabricatedOverlayInternalOffsets.classObject, "targetOverlayable",
430                             "Ljava/lang/String;");
431     gFabricatedOverlayInternalOffsets.entries =
432             GetFieldIDOrDie(env, gFabricatedOverlayInternalOffsets.classObject, "entries",
433                             "Ljava/util/List;");
434 
435     jclass fabricatedOverlayInternalEntryClass =
436             FindClassOrDie(env, "android/os/FabricatedOverlayInternalEntry");
437     gFabricatedOverlayInternalEntryOffsets.classObject =
438             MakeGlobalRefOrDie(env, fabricatedOverlayInternalEntryClass);
439     gFabricatedOverlayInternalEntryOffsets.resourceName =
440             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "resourceName",
441                             "Ljava/lang/String;");
442     gFabricatedOverlayInternalEntryOffsets.dataType =
443             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "dataType",
444                             "I");
445     gFabricatedOverlayInternalEntryOffsets.data =
446             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "data", "I");
447     gFabricatedOverlayInternalEntryOffsets.stringData =
448             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "stringData",
449                             "Ljava/lang/String;");
450     gFabricatedOverlayInternalEntryOffsets.binaryData =
451             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "binaryData",
452                             "Landroid/os/ParcelFileDescriptor;");
453     gFabricatedOverlayInternalEntryOffsets.configuration =
454             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject,
455                             "configuration", "Ljava/lang/String;");
456     gFabricatedOverlayInternalEntryOffsets.binaryDataOffset =
457             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject,
458                             "binaryDataOffset", "J");
459     gFabricatedOverlayInternalEntryOffsets.binaryDataSize =
460             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject,
461                             "binaryDataSize", "J");
462     gFabricatedOverlayInternalEntryOffsets.isNinePatch =
463             GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "isNinePatch",
464                             "Z");
465 
466     jclass parcelFileDescriptorClass =
467             android::FindClassOrDie(env, "android/os/ParcelFileDescriptor");
468     gParcelFileDescriptorOffsets.classObject = MakeGlobalRefOrDie(env, parcelFileDescriptorClass);
469     gParcelFileDescriptorOffsets.getFd =
470             GetMethodIDOrDie(env, gParcelFileDescriptorOffsets.classObject, "getFd", "()I");
471 
472     jclass fabricatedOverlayInfoClass = FindClassOrDie(env, "android/os/FabricatedOverlayInfo");
473     gFabricatedOverlayInfoOffsets.classObject = MakeGlobalRefOrDie(env, fabricatedOverlayInfoClass);
474     gFabricatedOverlayInfoOffsets.constructor =
475             GetMethodIDOrDie(env, gFabricatedOverlayInfoOffsets.classObject, "<init>", "()V");
476     gFabricatedOverlayInfoOffsets.packageName =
477             GetFieldIDOrDie(env, gFabricatedOverlayInfoOffsets.classObject, "packageName",
478                             "Ljava/lang/String;");
479     gFabricatedOverlayInfoOffsets.overlayName =
480             GetFieldIDOrDie(env, gFabricatedOverlayInfoOffsets.classObject, "overlayName",
481                             "Ljava/lang/String;");
482     gFabricatedOverlayInfoOffsets.targetPackageName =
483             GetFieldIDOrDie(env, gFabricatedOverlayInfoOffsets.classObject, "targetPackageName",
484                             "Ljava/lang/String;");
485     gFabricatedOverlayInfoOffsets.targetOverlayable =
486             GetFieldIDOrDie(env, gFabricatedOverlayInfoOffsets.classObject, "targetOverlayable",
487                             "Ljava/lang/String;");
488     gFabricatedOverlayInfoOffsets.path =
489             GetFieldIDOrDie(env, gFabricatedOverlayInfoOffsets.classObject, "path",
490                             "Ljava/lang/String;");
491 
492     return RegisterMethodsOrDie(env, "com/android/internal/content/om/OverlayManagerImpl",
493                                 gOverlayManagerMethods, NELEM(gOverlayManagerMethods));
494 }
495 
496 } // namespace android
497