• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #ifndef ANDROIDFW_ASSETMANAGER2_H_
18 #define ANDROIDFW_ASSETMANAGER2_H_
19 
20 #include <utils/RefBase.h>
21 
22 #include <array>
23 #include <limits>
24 #include <optional>
25 #include <set>
26 #include <span>
27 #include <unordered_map>
28 
29 #include "android-base/function_ref.h"
30 #include "android-base/macros.h"
31 #include "androidfw/ApkAssets.h"
32 #include "androidfw/Asset.h"
33 #include "androidfw/AssetManager.h"
34 #include "androidfw/ResourceTypes.h"
35 #include "androidfw/Util.h"
36 #include "ftl/small_vector.h"
37 
38 namespace android {
39 
40 class Theme;
41 
42 using ApkAssetsCookie = int32_t;
43 
44 enum : ApkAssetsCookie {
45   kInvalidCookie = -1,
46 };
47 
48 // Holds a bag that has been merged with its parent, if one exists.
49 struct ResolvedBag {
50   // A single key-value entry in a bag.
51   struct Entry {
52     // The key, as described in ResTable_map::name.
53     uint32_t key;
54 
55     Res_value value;
56 
57     // The resource ID of the origin style associated with the given entry.
58     uint32_t style;
59 
60     // Which ApkAssets this entry came from.
61     ApkAssetsCookie cookie;
62 
63     ResStringPool* key_pool;
64     ResStringPool* type_pool;
65   };
66 
67   // Denotes the configuration axis that this bag varies with.
68   // If a configuration changes with respect to one of these axis,
69   // the bag should be reloaded.
70   uint32_t type_spec_flags;
71 
72   // The number of entries in this bag. Access them by indexing into `entries`.
73   uint32_t entry_count;
74 
75   // The array of entries for this bag. An empty array is a neat trick to force alignment
76   // of the Entry structs that follow this structure and avoids a bunch of casts.
77   Entry entries[0];
78 };
79 
80 struct FindEntryResult;
81 
82 // AssetManager2 is the main entry point for accessing assets and resources.
83 // AssetManager2 provides caching of resources retrieved via the underlying ApkAssets.
84 class AssetManager2 {
85   friend Theme;
86 
87  public:
88   struct ResourceName {
89     const char* package = nullptr;
90     size_t package_len = 0u;
91 
92     const char* type = nullptr;
93     const char16_t* type16 = nullptr;
94     size_t type_len = 0u;
95 
96     const char* entry = nullptr;
97     const char16_t* entry16 = nullptr;
98     size_t entry_len = 0u;
99   };
100 
101   using ApkAssetsPtr = sp<const ApkAssets>;
102   using ApkAssetsWPtr = wp<const ApkAssets>;
103   using ApkAssetsList = std::span<const ApkAssetsPtr>;
104 
105   AssetManager2();
106   explicit AssetManager2(AssetManager2&& other) = default;
107   AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration);
108 
109   struct ScopedOperation {
110     DISALLOW_COPY_AND_ASSIGN(ScopedOperation);
111     friend AssetManager2;
112     const AssetManager2& am_;
113     ScopedOperation(const AssetManager2& am);
114 
115    public:
116     ~ScopedOperation();
117   };
118 
119   [[nodiscard]] ScopedOperation StartOperation() const;
120 
121   // Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets
122   // are not owned by the AssetManager, and must have a longer lifetime.
123   //
124   // Only pass invalidate_caches=false when it is known that the structure
125   // change in ApkAssets is due to a safe addition of resources with completely
126   // new resource IDs.
127   bool SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches = true);
128   bool SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, bool invalidate_caches = true);
129   // This one is an optimization - it skips all calculations for applying the currently set
130   // configuration, expecting a configuration update later with a forced refresh.
131   void PresetApkAssets(ApkAssetsList apk_assets);
132 
133   const ApkAssetsPtr& GetApkAssets(ApkAssetsCookie cookie) const;
GetApkAssetsCount()134   int GetApkAssetsCount() const {
135     return int(apk_assets_.size());
136   }
137 
138   // Returns the string pool for the given asset cookie.
139   // Use the string pool returned here with a valid Res_value object of type Res_value::TYPE_STRING.
140   const ResStringPool* GetStringPoolForCookie(ApkAssetsCookie cookie) const;
141 
142   // Returns the DynamicRefTable for the given package ID.
143   // This may be nullptr if the APK represented by `cookie` has no resource table.
144   const DynamicRefTable* GetDynamicRefTableForPackage(uint32_t package_id) const;
145 
146   // Returns the DynamicRefTable for the ApkAssets represented by the cookie.
147   // This may be nullptr if the APK represented by `cookie` has no resource table.
148   std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
149 
150   // Retrieve the assigned package id of the package if loaded into this AssetManager
151   uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
152 
153   // Returns a string representation of the overlayable API of a package.
154   bool GetOverlayablesToString(android::StringPiece package_name, std::string* out) const;
155 
156   const std::unordered_map<std::string, std::string>* GetOverlayableMapForPackage(
157       uint32_t package_id) const;
158 
159   // Returns whether the resources.arsc of any loaded apk assets is allocated in RAM (not mmapped).
160   bool ContainsAllocatedTable() const;
161 
162   // Sets/resets the configuration for this AssetManager. This will cause all
163   // caches that are related to the configuration change to be invalidated.
164   void SetConfigurations(std::span<const ResTable_config> configurations,
165                          bool force_refresh = false);
166 
GetConfigurations()167   std::span<const ResTable_config> GetConfigurations() const {
168     return configurations_;
169   }
170 
171   void SetDefaultLocale(const std::optional<ResTable_config> default_locale);
172 
173   void SetOverlayConstraints(int32_t display_id, int32_t device_id);
174 
175   // Returns all configurations for which there are resources defined, or an I/O error if reading
176   // resource data failed.
177   //
178   // This includes resource configurations in all the ApkAssets set for this AssetManager.
179   // If `exclude_system` is set to true, resource configurations from system APKs
180   // ('android' package, other libraries) will be excluded from the list.
181   // If `exclude_mipmap` is set to true, resource configurations defined for resource type 'mipmap'
182   // will be excluded from the list.
183   base::expected<std::set<ResTable_config>, IOError> GetResourceConfigurations(
184       bool exclude_system = false, bool exclude_mipmap = false) const;
185 
186   // Returns all the locales for which there are resources defined. This includes resource
187   // locales in all the ApkAssets set for this AssetManager.
188   // If `exclude_system` is set to true, resource locales from system APKs
189   // ('android' package, other libraries) will be excluded from the list.
190   // If `merge_equivalent_languages` is set to true, resource locales will be canonicalized
191   // and de-duped in the resulting list.
192   LoadedPackage::Locales GetResourceLocales(
193       bool exclude_system = false, bool merge_equivalent_languages = false) const;
194 
195   // Searches the set of APKs loaded by this AssetManager and opens the first one found located
196   // in the assets/ directory.
197   // `mode` controls how the file is opened.
198   //
199   // NOTE: The loaded APKs are searched in reverse order.
200   std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode) const;
201 
202   // Opens a file within the assets/ directory of the APK specified by `cookie`.
203   // `mode` controls how the file is opened.
204   std::unique_ptr<Asset> Open(const std::string& filename, ApkAssetsCookie cookie,
205                               Asset::AccessMode mode) const;
206 
207   // Opens the directory specified by `dirname`. The result is an AssetDir that is the combination
208   // of all directories matching `dirname` under the assets/ directory of every ApkAssets loaded.
209   // The entries are sorted by their ASCII name.
210   std::unique_ptr<AssetDir> OpenDir(const std::string& dirname) const;
211 
212   // Searches the set of APKs loaded by this AssetManager and opens the first one found.
213   // `mode` controls how the file is opened.
214   // `out_cookie` is populated with the cookie of the APK this file was found in.
215   //
216   // NOTE: The loaded APKs are searched in reverse order.
217   std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, Asset::AccessMode mode,
218                                       ApkAssetsCookie* out_cookie = nullptr) const;
219 
220   // Opens a file in the APK specified by `cookie`. `mode` controls how the file is opened.
221   // This is typically used to open a specific AndroidManifest.xml, or a binary XML file
222   // referenced by a resource lookup with GetResource().
223   std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, ApkAssetsCookie cookie,
224                                       Asset::AccessMode mode) const;
225 
226   // Returns the resource id of parent style of the specified theme.
227   //
228   // Returns a null error if the name is missing/corrupt, or an I/O error if reading resource data
229   // failed.
230   base::expected<uint32_t, NullOrIOError> GetParentThemeResourceId(uint32_t resid) const;
231 
232   // Returns the resource name of the specified resource ID.
233   //
234   // Utf8 strings are preferred, and only if they are unavailable are the Utf16 variants populated.
235   //
236   // Returns a null error if the name is missing/corrupt, or an I/O error if reading resource data
237   // failed.
238   base::expected<ResourceName, NullOrIOError> GetResourceName(uint32_t resid) const;
239 
240   // Finds the resource ID assigned to `resource_name`.
241   //
242   // `resource_name` must be of the form '[package:][type/]entry'.
243   // If no package is specified in `resource_name`, then `fallback_package` is used as the package.
244   // If no type is specified in `resource_name`, then `fallback_type` is used as the type.
245   //
246   // Returns a null error if no resource by that name was found, or an I/O error if reading resource
247   // data failed.
248   base::expected<uint32_t, NullOrIOError> GetResourceId(
249       const std::string& resource_name, const std::string& fallback_type = {},
250       const std::string& fallback_package = {}) const;
251 
252   struct SelectedValue {
253     friend AssetManager2;
254     friend Theme;
255     SelectedValue() = default;
SelectedValueSelectedValue256     SelectedValue(const ResolvedBag* bag, const ResolvedBag::Entry& entry)
257         : cookie(entry.cookie),
258           data(entry.value.data),
259           type(entry.value.dataType),
260           entry_flags(0U),
261           flags(bag->type_spec_flags),
262           resid(0U),
263           config() {
264     }
265 
266     // The cookie representing the ApkAssets in which the value resides.
267     ApkAssetsCookie cookie = kInvalidCookie;
268 
269     // The data for this value, as interpreted according to `type`.
270     Res_value::data_type data;
271 
272     // Type of the data value.
273     uint8_t type;
274 
275     // The bitmask of ResTable_entry flags
276     uint16_t entry_flags;
277 
278     // The bitmask of configuration axis that this resource varies with.
279     // See ResTable_config::CONFIG_*.
280     uint32_t flags;
281 
282     // The resource ID from which this value was resolved.
283     uint32_t resid;
284 
285     // The configuration for which the resolved value was defined.
286     ResTable_config config;
287 
288    private:
SelectedValueSelectedValue289     SelectedValue(uint8_t value_type, Res_value::data_type value_data, ApkAssetsCookie cookie,
290                   uint16_t entry_flags, uint32_t type_flags, uint32_t resid, ResTable_config config)
291         :
292                   cookie(cookie), data(value_data), type(value_type), entry_flags(entry_flags),
293                   flags(type_flags), resid(resid), config(std::move(config)) {}
294   };
295 
296   // Retrieves the best matching resource value with ID `resid`.
297   //
298   // If `may_be_bag` is false, this function logs if the resource was a map/bag type and returns a
299   // null result. If `density_override` is non-zero, the configuration to match against is
300   // overridden with that density.
301   //
302   // Returns a null error if a best match could not be found, or an I/O error if reading resource
303   // data failed.
304   base::expected<SelectedValue, NullOrIOError> GetResource(uint32_t resid, bool may_be_bag = false,
305                                                            uint16_t density_override = 0U) const;
306 
307   // Resolves the resource referenced in `value` if the type is Res_value::TYPE_REFERENCE.
308   //
309   // If the data type is not Res_value::TYPE_REFERENCE, no work is done. Configuration flags of the
310   // values pointed to by the reference are OR'd into `value.flags`. If `cache_value` is true, then
311   // the resolved value will be cached and used when attempting to resolve the resource id specified
312   // in `value`.
313   //
314   // Returns a null error if the resource could not be resolved, or an I/O error if reading
315   // resource data failed.
316   base::expected<std::monostate, NullOrIOError> ResolveReference(SelectedValue& value,
317                                                                  bool cache_value = false) const;
318 
319   // Retrieves the best matching bag/map resource with ID `resid`.
320   //
321   // This method will resolve all parent references for this bag and merge keys with the child.
322   // To iterate over the keys, use the following idiom:
323   //
324   //  base::expected<const ResolvedBag*, NullOrIOError> bag = asset_manager->GetBag(id);
325   //  if (bag.has_value()) {
326   //    for (auto iter = begin(*bag); iter != end(*bag); ++iter) {
327   //      ...
328   //    }
329   //  }
330   //
331   // Returns a null error if a best match could not be found, or an I/O error if reading resource
332   // data failed.
333   base::expected<const ResolvedBag*, NullOrIOError> GetBag(uint32_t resid) const;
334 
335   // Retrieves the best matching bag/map resource of the resource referenced in `value`.
336   //
337   // If `value.type` is not Res_value::TYPE_REFERENCE, a null result is returned.
338   // Configuration flags of the bag pointed to by the reference are OR'd into `value.flags`.
339   //
340   // Returns a null error if a best match could not be found, or an I/O error if reading resource
341   // data failed.
342   base::expected<const ResolvedBag*, NullOrIOError> ResolveBag(SelectedValue& value) const;
343 
344   // Returns the android::ResTable_typeSpec flags of the resource ID.
345   //
346   // Returns a null error if the resource could not be resolved, or an I/O error if reading
347   // resource data failed.
348   base::expected<uint32_t, NullOrIOError> GetResourceTypeSpecFlags(uint32_t resid) const;
349 
350   base::expected<const std::vector<uint32_t>*, NullOrIOError> GetBagResIdStack(
351       uint32_t resid) const;
352 
353   // Resets the resource resolution structures in preparation for the next resource retrieval.
354   void ResetResourceResolution() const;
355 
356   // Enables or disables resource resolution logging. Clears stored steps when disabled.
357   void SetResourceResolutionLoggingEnabled(bool enabled);
358 
359   // Returns formatted log of last resource resolution path, or empty if no resource has been
360   // resolved yet.
361   std::string GetLastResourceResolution() const;
362 
363   // Creates a new Theme from this AssetManager.
364   std::unique_ptr<Theme> NewTheme();
365 
366   void ForEachPackage(base::function_ref<bool(const std::string&, uint8_t)> func,
367                       package_property_t excluded_property_flags = 0U) const;
368 
369   void DumpToLog() const;
370 
371  private:
372   DISALLOW_COPY_AND_ASSIGN(AssetManager2);
373 
374   // A collection of configurations and their associated ResTable_type that match the current
375   // AssetManager configuration.
376   struct FilteredConfigGroup {
377       std::vector<const TypeSpec::TypeEntry*> type_entries;
378   };
379 
380   // Represents an single package.
381   struct ConfiguredPackage {
382       // A pointer to the immutable, loaded package info.
383       const LoadedPackage* loaded_package_;
384 
385       // A mutable AssetManager-specific list of configurations that match the AssetManager's
386       // current configuration. This is used as an optimization to avoid checking every single
387       // candidate configuration when looking up resources.
388       ByteBucketArray<FilteredConfigGroup> filtered_configs_;
389   };
390 
391   // Represents a Runtime Resource Overlay that overlays resources in the logical package.
392   struct ConfiguredOverlay {
393       // The set of package groups that overlay this package group.
394       IdmapResMap overlay_res_maps_;
395 
396       // The cookie of the overlay assets.
397       ApkAssetsCookie cookie;
398 
399       // Enable/disable status of the overlay based on current constraints of AssetManager.
400       bool enabled;
401   };
402 
403   // Represents a logical package, which can be made up of many individual packages. Each package
404   // in a PackageGroup shares the same package name and package ID.
405   struct PackageGroup {
406       // The set of packages that make-up this group.
407       std::vector<ConfiguredPackage> packages_;
408 
409       // The cookies associated with each package in the group. They share the same order as
410       // packages_.
411       std::vector<ApkAssetsCookie> cookies_;
412 
413       // Runtime Resource Overlays that overlay resources in this package group.
414       std::vector<ConfiguredOverlay> overlays_;
415 
416       // A library reference table that contains build-package ID to runtime-package ID mappings.
417       std::shared_ptr<DynamicRefTable> dynamic_ref_table = std::make_shared<DynamicRefTable>();
418   };
419 
420   // Finds the best entry for `resid` from the set of ApkAssets. The entry can be a simple
421   // Res_value, or a complex map/bag type. Returns a null result if a best entry cannot be found.
422   //
423   // `density_override` overrides the density of the current configuration when doing a search.
424   //
425   // When `stop_at_first_match` is true, the first match found is selected and the search
426   // terminates. This is useful for methods that just look up the name of a resource and don't
427   // care about the value. In this case, the value of `FindEntryResult::type_flags` is incomplete
428   // and should not be used.
429   //
430   // When `ignore_configuration` is true, FindEntry will return always select the first entry in
431   // for the type seen regardless of its configuration.
432   //
433   // NOTE: FindEntry takes care of ensuring that structs within FindEntryResult have been properly
434   // bounds-checked. Callers of FindEntry are free to trust the data if this method succeeds.
435   base::expected<FindEntryResult, NullOrIOError> FindEntry(uint32_t resid,
436                                                            uint16_t density_override,
437                                                            bool stop_at_first_match,
438                                                            bool ignore_configuration) const;
439 
440   base::expected<FindEntryResult, NullOrIOError> FindEntryInternal(
441       const PackageGroup& package_group, uint8_t type_idx, uint16_t entry_idx,
442       const ResTable_config& desired_config, bool stop_at_first_match,
443       bool ignore_configuration) const;
444 
445   // Assigns package IDs to all shared library ApkAssets.
446   // Should be called whenever the ApkAssets are changed.
447   void BuildDynamicRefTable(ApkAssetsList assets);
448 
449   // Purge all resources that are cached and vary by the configuration axis denoted by the
450   // bitmask `diff`.
451   void InvalidateCaches(uint32_t diff);
452 
453   // Triggers the re-construction of lists of types that match the set configuration.
454   // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
455   void RebuildFilterList();
456 
457   // Retrieves the APK paths of overlays that overlay non-system packages.
458   std::set<ApkAssetsPtr> GetNonSystemOverlays() const;
459 
460   // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
461   // been seen while traversing bag parents.
462   base::expected<const ResolvedBag*, NullOrIOError> GetBag(
463       uint32_t resid, std::vector<uint32_t>& child_resids) const;
464 
465   // Finish an operation that was running with the current asset manager, and clean up the
466   // promoted apk assets when the last operation ends.
467   void FinishOperation() const;
468 
469   bool IsAnyOverlayConstraintSatisfied(const Idmap_constraints& constraints) const;
470 
471   // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
472   // have a longer lifetime.
473   // The second pair element is the promoted version of the assets, that is held for the duration
474   // of the currently running operation. FinishOperation() clears all promoted assets to make sure
475   // they can be released when the system needs that.
476   mutable std::vector<std::pair<ApkAssetsWPtr, ApkAssetsPtr>> apk_assets_;
477 
478   // DynamicRefTables for shared library package resolution.
479   // These are ordered according to apk_assets_. The mappings may change depending on what is
480   // in apk_assets_, therefore they must be stored in the AssetManager and not in the
481   // immutable ApkAssets class.
482   std::vector<PackageGroup> package_groups_;
483 
484   // An array mapping package ID to index into package_groups. This keeps the lookup fast
485   // without taking too much memory.
486   std::array<uint8_t, std::numeric_limits<uint8_t>::max() + 1> package_ids_ = {};
487 
488   std::optional<ResTable_config> default_locale_;
489 
490   // The current configurations set for this AssetManager. When this changes, cached resources
491   // may need to be purged.
492   ftl::SmallVector<ResTable_config, 1> configurations_;
493 
494   int32_t display_id_;
495   int32_t device_id_;
496 
497   // Cached set of bags. These are cached because they can inherit keys from parent bags,
498   // which involves some calculation.
499   mutable std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
500 
501   // Cached set of bag resid stacks for each bag. These are cached because they might be requested
502   // a number of times for each view during View inspection.
503   mutable std::unordered_map<uint32_t, std::vector<uint32_t>> cached_bag_resid_stacks_;
504 
505   // Cached set of resolved resource values.
506   mutable std::unordered_map<uint32_t, SelectedValue> cached_resolved_values_;
507 
508   // Tracking the number of the started operations running with the current AssetManager.
509   // Finishing the last one clears all promoted apk assets.
510   mutable int number_of_running_scoped_operations_ = 0;
511 
512   // Whether or not to save resource resolution steps
513   bool resource_resolution_logging_enabled_ = false;
514 
515   struct Resolution {
516     struct Step {
517       enum class Type {
518         INITIAL,
519         BETTER_MATCH,
520         OVERLAID,
521         OVERLAID_INLINE,
522         SKIPPED,
523         NO_ENTRY,
524       };
525 
526       // Marks what kind of override this step was.
527       Type type;
528 
529       ApkAssetsCookie cookie = kInvalidCookie;
530 
531       // Built name of configuration for this step.
532       String8 config_name;
533     };
534 
535     // Last resolved resource ID.
536     uint32_t resid;
537 
538     // Last resolved resource result cookie.
539     ApkAssetsCookie cookie = kInvalidCookie;
540 
541     // Last resolved resource type.
542     StringPoolRef type_string_ref;
543 
544     // Last resolved resource entry.
545     StringPoolRef entry_string_ref;
546 
547     // Steps taken to resolve last resource.
548     std::vector<Step> steps;
549 
550     // The configuration name of the best resource found.
551     String8 best_config_name;
552 
553     // The package name of the best resource found.
554     String8 best_package_name;
555   };
556 
557   // Record of the last resolved resource's resolution path.
558   mutable Resolution last_resolution_;
559 };
560 
561 class Theme {
562   friend class AssetManager2;
563 
564  public:
565   ~Theme();
566 
567   // Applies the style identified by `resid` to this theme.
568   //
569   // This can be called multiple times with different styles. By default, any theme attributes that
570   // are already defined before this call are not overridden. If `force` is set to true, this
571   // behavior is changed and all theme attributes from the style at `resid` are applied.
572   //
573   // Returns a null error if the style could not be applied, or an I/O error if reading resource
574   // data failed.
575   base::expected<std::monostate, NullOrIOError> ApplyStyle(uint32_t resid, bool force = false);
576 
577   // Clears the existing theme, sets the new asset manager to use for this theme, and applies the
578   // styles in `style_ids` through repeated invocations of `ApplyStyle`.
579   void Rebase(AssetManager2* am, const uint32_t* style_ids, const uint8_t* force,
580               size_t style_count);
581 
582   // Sets this Theme to be a copy of `source` if `source` has the same AssetManager as this Theme.
583   //
584   // If `source` does not have the same AssetManager as this theme, only attributes from ApkAssets
585   // loaded into both AssetManagers will be copied to this theme.
586   //
587   // Returns an I/O error if reading resource data failed.
588   base::expected<std::monostate, IOError> SetTo(const Theme& source);
589 
590   void Clear();
591 
592   // Retrieves the value of attribute ID `resid` in the theme.
593   //
594   // NOTE: This function does not do reference traversal. If you want to follow references to other
595   // resources to get the "real" value to use, you need to call ResolveReference() after this
596   // function.
597   std::optional<AssetManager2::SelectedValue> GetAttribute(uint32_t resid) const;
598 
599   // This is like AssetManager2::ResolveReference(), but also takes care of resolving attribute
600   // references to the theme.
601   base::expected<std::monostate, NullOrIOError> ResolveAttributeReference(
602       AssetManager2::SelectedValue& value) const;
603 
GetAssetManager()604   AssetManager2* GetAssetManager() {
605     return asset_manager_;
606   }
607 
GetAssetManager()608   const AssetManager2* GetAssetManager() const {
609     return asset_manager_;
610   }
611 
612   // Returns a bit mask of configuration changes that will impact this
613   // theme (and thus require completely reloading it).
GetChangingConfigurations()614   uint32_t GetChangingConfigurations() const {
615     return type_spec_flags_;
616   }
617 
618   void Dump() const;
619 
620   struct Entry;
621  private:
622   DISALLOW_COPY_AND_ASSIGN(Theme);
623 
624   explicit Theme(AssetManager2* asset_manager);
625 
626   AssetManager2* asset_manager_ = nullptr;
627   uint32_t type_spec_flags_ = 0u;
628 
629   std::vector<uint32_t> keys_;
630   std::vector<Entry> entries_;
631 };
632 
begin(const ResolvedBag * bag)633 inline const ResolvedBag::Entry* begin(const ResolvedBag* bag) {
634   return bag->entries;
635 }
636 
end(const ResolvedBag * bag)637 inline const ResolvedBag::Entry* end(const ResolvedBag* bag) {
638   return bag->entries + bag->entry_count;
639 }
640 
641 }  // namespace android
642 
643 #endif /* ANDROIDFW_ASSETMANAGER2_H_ */
644