Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a37b74d authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Add tests for attribute resolution

- Adds unit tests for attribute resolution. These include
  some test data resource tables and compiled XML files.
- Convert touched files to Google style guide.

Test: make libandroidfw_tests
Change-Id: Ib3a36061dc874de5f6a266b4e82c0a12ef435f23
parent 047f5a7b
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -97,16 +97,6 @@ jclass g_stringClass = NULL;

// ----------------------------------------------------------------------------

enum {
    STYLE_NUM_ENTRIES = 6,
    STYLE_TYPE = 0,
    STYLE_DATA = 1,
    STYLE_ASSET_COOKIE = 2,
    STYLE_RESOURCE_ID = 3,
    STYLE_CHANGING_CONFIGURATIONS = 4,
    STYLE_DENSITY = 5
};

static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
                      const Res_value& value, uint32_t ref, ssize_t block,
                      uint32_t typeSpecFlags, ResTable_config* config = NULL);
@@ -1171,7 +1161,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
    }

    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
    bool result = resolveAttrs(theme, defStyleAttr, defStyleRes,
    bool result = ResolveAttrs(theme, defStyleAttr, defStyleRes,
                               (uint32_t*) srcValues, NSV,
                               (uint32_t*) src, NI,
                               (uint32_t*) baseDest,
@@ -1235,7 +1225,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla

    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
    bool result = applyStyle(theme, xmlParser,
    bool result = ApplyStyle(theme, xmlParser,
                             defStyleAttr, defStyleRes,
                             (uint32_t*) src, NI,
                             (uint32_t*) baseDest,
@@ -1300,7 +1290,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
        }
    }

    bool result = retrieveAttributes(&res, xmlParser,
    bool result = RetrieveAttributes(&res, xmlParser,
                                     (uint32_t*) src, NI,
                                     (uint32_t*) baseDest,
                                     (uint32_t*) indices);
+24 −21
Original line number Diff line number Diff line
@@ -21,6 +21,18 @@

namespace android {

// Offsets into the outValues array populated by the methods below. outValues is a uint32_t
// array, but each logical element takes up 6 uint32_t-sized physical elements.
enum {
  STYLE_NUM_ENTRIES = 6,
  STYLE_TYPE = 0,
  STYLE_DATA = 1,
  STYLE_ASSET_COOKIE = 2,
  STYLE_RESOURCE_ID = 3,
  STYLE_CHANGING_CONFIGURATIONS = 4,
  STYLE_DENSITY = 5
};

// These are all variations of the same method. They each perform the exact same operation,
// but on various data sources. I *think* they are re-written to avoid an extra branch
// in the inner loop, but after one branch miss (some pointer != null), the branch predictor should
@@ -28,25 +40,16 @@ namespace android {
// TODO(adamlesinski): Run performance tests against these methods and a new, single method
// that uses all the sources and branches to the right ones within the inner loop.

bool resolveAttrs(ResTable::Theme* theme,
                  uint32_t defStyleAttr,
                  uint32_t defStyleRes,
                  uint32_t* srcValues, size_t srcValuesLength,
                  uint32_t* attrs, size_t attrsLength,
                  uint32_t* outValues,
                  uint32_t* outIndices);

bool applyStyle(ResTable::Theme* theme, ResXMLParser* xmlParser,
                uint32_t defStyleAttr,
                uint32_t defStyleRes,
                uint32_t* attrs, size_t attrsLength,
                uint32_t* outValues,
                uint32_t* outIndices);

bool retrieveAttributes(const ResTable* res, ResXMLParser* xmlParser,
                        uint32_t* attrs, size_t attrsLength,
                        uint32_t* outValues,
                        uint32_t* outIndices);
bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
                  uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
                  size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);

bool ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
                uint32_t def_style_res, uint32_t* attrs, size_t attrs_length, uint32_t* out_values,
                uint32_t* out_indices);

bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
                        size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);

}  // namespace android

+2 −0
Original line number Diff line number Diff line
BasedOnStyle: Google
ColumnLimit: 100
+206 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -14,17 +14,16 @@
 * limitations under the License.
 */

#ifndef H_ATTRIBUTE_FINDER
#define H_ATTRIBUTE_FINDER
#ifndef ANDROIDFW_ATTRIBUTE_FINDER_H
#define ANDROIDFW_ATTRIBUTE_FINDER_H

#include <stdint.h>
#include <utils/KeyedVector.h>

#include <stdint.h>

namespace android {

static inline uint32_t getPackage(uint32_t attr) {
    return attr >> 24;
}
static inline uint32_t get_package(uint32_t attr) { return attr >> 24; }

/**
 * A helper class to search linearly for the requested
@@ -58,58 +57,59 @@ class BackTrackingAttributeFinder {
 public:
  BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end);

    Iterator find(uint32_t attr);
  Iterator Find(uint32_t attr);

 private:
    void jumpToClosestAttribute(uint32_t packageId);
    void markCurrentPackageId(uint32_t packageId);
  void JumpToClosestAttribute(uint32_t package_id);
  void MarkCurrentPackageId(uint32_t package_id);

    bool mFirstTime;
    Iterator mBegin;
    Iterator mEnd;
    Iterator mCurrent;
    Iterator mLargest;
    uint32_t mLastPackageId;
    uint32_t mCurrentAttr;
  bool first_time_;
  Iterator begin_;
  Iterator end_;
  Iterator current_;
  Iterator largest_;
  uint32_t last_package_id_;
  uint32_t current_attr_;

    // Package Offsets (best-case, fast look-up).
    Iterator mFrameworkStart;
    Iterator mAppStart;
  // Package offsets (best-case, fast look-up).
  Iterator framework_start_;
  Iterator app_start_;

  // Worst case, we have shared-library resources.
    KeyedVector<uint32_t, Iterator> mPackageOffsets;
  KeyedVector<uint32_t, Iterator> package_offsets_;
};

template <typename Derived, typename Iterator> inline
BackTrackingAttributeFinder<Derived, Iterator>::BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end)
    : mFirstTime(true)
    , mBegin(begin)
    , mEnd(end)
    , mCurrent(begin)
    , mLargest(begin)
    , mLastPackageId(0)
    , mCurrentAttr(0)
    , mFrameworkStart(end)
    , mAppStart(end) {
}
template <typename Derived, typename Iterator>
inline BackTrackingAttributeFinder<Derived, Iterator>::BackTrackingAttributeFinder(
    const Iterator& begin, const Iterator& end)
    : first_time_(true),
      begin_(begin),
      end_(end),
      current_(begin),
      largest_(begin),
      last_package_id_(0),
      current_attr_(0),
      framework_start_(end),
      app_start_(end) {}

template <typename Derived, typename Iterator>
void BackTrackingAttributeFinder<Derived, Iterator>::jumpToClosestAttribute(const uint32_t packageId) {
    switch (packageId) {
        case 0x01:
            mCurrent = mFrameworkStart;
void BackTrackingAttributeFinder<Derived, Iterator>::JumpToClosestAttribute(
    const uint32_t package_id) {
  switch (package_id) {
    case 0x01u:
      current_ = framework_start_;
      break;
        case 0x7f:
            mCurrent = mAppStart;
    case 0x7fu:
      current_ = app_start_;
      break;
    default: {
            ssize_t idx = mPackageOffsets.indexOfKey(packageId);
      ssize_t idx = package_offsets_.indexOfKey(package_id);
      if (idx >= 0) {
        // We have seen this package ID before, so jump to the first
        // attribute with this package ID.
                mCurrent = mPackageOffsets[idx];
        current_ = package_offsets_[idx];
      } else {
                mCurrent = mEnd;
        current_ = end_;
      }
      break;
    }
@@ -117,90 +117,90 @@ void BackTrackingAttributeFinder<Derived, Iterator>::jumpToClosestAttribute(cons

  // We have never seen this package ID yet, so jump to the
  // latest/largest index we have processed so far.
    if (mCurrent == mEnd) {
        mCurrent = mLargest;
  if (current_ == end_) {
    current_ = largest_;
  }

    if (mCurrent != mEnd) {
        mCurrentAttr = static_cast<const Derived*>(this)->getAttribute(mCurrent);
  if (current_ != end_) {
    current_attr_ = static_cast<const Derived*>(this)->GetAttribute(current_);
  }
}

template <typename Derived, typename Iterator>
void BackTrackingAttributeFinder<Derived, Iterator>::markCurrentPackageId(const uint32_t packageId) {
    switch (packageId) {
        case 0x01:
            mFrameworkStart = mCurrent;
void BackTrackingAttributeFinder<Derived, Iterator>::MarkCurrentPackageId(
    const uint32_t package_id) {
  switch (package_id) {
    case 0x01u:
      framework_start_ = current_;
      break;
        case 0x7f:
            mAppStart = mCurrent;
    case 0x7fu:
      app_start_ = current_;
      break;
    default:
            mPackageOffsets.add(packageId, mCurrent);
      package_offsets_.add(package_id, current_);
      break;
  }
}

template <typename Derived, typename Iterator>
Iterator BackTrackingAttributeFinder<Derived, Iterator>::find(uint32_t attr) {
    if (!(mBegin < mEnd)) {
        return mEnd;
Iterator BackTrackingAttributeFinder<Derived, Iterator>::Find(uint32_t attr) {
  if (!(begin_ < end_)) {
    return end_;
  }

    if (mFirstTime) {
  if (first_time_) {
    // One-time initialization. We do this here instead of the constructor
    // because the derived class we access in getAttribute() may not be
    // fully constructed.
        mFirstTime = false;
        mCurrentAttr = static_cast<const Derived*>(this)->getAttribute(mBegin);
        mLastPackageId = getPackage(mCurrentAttr);
        markCurrentPackageId(mLastPackageId);
    first_time_ = false;
    current_attr_ = static_cast<const Derived*>(this)->GetAttribute(begin_);
    last_package_id_ = get_package(current_attr_);
    MarkCurrentPackageId(last_package_id_);
  }

  // Looking for the needle (attribute we're looking for)
  // in the haystack (the attributes we're searching through)
    const uint32_t needlePackageId = getPackage(attr);
    if (mLastPackageId != needlePackageId) {
        jumpToClosestAttribute(needlePackageId);
        mLastPackageId = needlePackageId;
  const uint32_t needle_package_id = get_package(attr);
  if (last_package_id_ != needle_package_id) {
    JumpToClosestAttribute(needle_package_id);
    last_package_id_ = needle_package_id;
  }

  // Walk through the xml attributes looking for the requested attribute.
    while (mCurrent != mEnd) {
        const uint32_t haystackPackageId = getPackage(mCurrentAttr);
        if (needlePackageId == haystackPackageId && attr < mCurrentAttr) {
  while (current_ != end_) {
    const uint32_t haystack_package_id = get_package(current_attr_);
    if (needle_package_id == haystack_package_id && attr < current_attr_) {
      // The attribute we are looking was not found.
      break;
    }
        const uint32_t prevAttr = mCurrentAttr;
    const uint32_t prev_attr = current_attr_;

    // Move to the next attribute in the XML.
        ++mCurrent;
        if (mCurrent != mEnd) {
            mCurrentAttr = static_cast<const Derived*>(this)->getAttribute(mCurrent);
            const uint32_t newHaystackPackageId = getPackage(mCurrentAttr);
            if (haystackPackageId != newHaystackPackageId) {
    ++current_;
    if (current_ != end_) {
      current_attr_ = static_cast<const Derived*>(this)->GetAttribute(current_);
      const uint32_t new_haystack_package_id = get_package(current_attr_);
      if (haystack_package_id != new_haystack_package_id) {
        // We've moved to the next group of attributes
        // with a new package ID, so we should record
        // the offset of this new package ID.
                markCurrentPackageId(newHaystackPackageId);
        MarkCurrentPackageId(new_haystack_package_id);
      }
    }

        if (mCurrent > mLargest) {
            // We've moved past the latest attribute we've
            // seen.
            mLargest = mCurrent;
    if (current_ > largest_) {
      // We've moved past the latest attribute we've seen.
      largest_ = current_;
    }

        if (attr == prevAttr) {
    if (attr == prev_attr) {
      // We found the attribute we were looking for.
            return mCurrent - 1;
      return current_ - 1;
    }
  }
    return mEnd;
  return end_;
}

}  // namespace android

#endif // H_ATTRIBUTE_FINDER
#endif  // ANDROIDFW_ATTRIBUTE_FINDER_H
+378 −401

File changed.

Preview size limit exceeded, changes collapsed.

Loading