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