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