/*
 * Copyright (C) 2018 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_LIBDEXFILE_DEX_HIDDEN_API_ACCESS_FLAGS_H_
#define ART_LIBDEXFILE_DEX_HIDDEN_API_ACCESS_FLAGS_H_

#include "base/bit_utils.h"
#include "base/macros.h"
#include "dex/modifiers.h"

namespace art {

/* This class is used for encoding and decoding access flags of class members
 * from the boot class path. These access flags might contain additional two bits
 * of information on whether the given class member should be hidden from apps
 * and under what circumstances.
 *
 * The encoding is different inside DexFile, where we are concerned with size,
 * and at runtime where we want to optimize for speed of access. The class
 * provides helper functions to decode/encode both of them.
 *
 * Encoding in DexFile
 * ===================
 *
 * First bit is encoded as inversion of visibility flags (public/private/protected).
 * At most one can be set for any given class member. If two or three are set,
 * this is interpreted as the first bit being set and actual visibility flags
 * being the complement of the encoded flags.
 *
 * Second bit is either encoded as bit 5 for fields and non-native methods, where
 * it carries no other meaning. If a method is native (bit 8 set), bit 9 is used.
 *
 * Bits were selected so that they never increase the length of unsigned LEB-128
 * encoding of the access flags.
 *
 * Encoding at runtime
 * ===================
 *
 * Two bits are set aside in the uint32_t access flags in the intrinsics ordinal
 * space (thus intrinsics need to be special-cased). These are two consecutive
 * bits and they are directly used to store the integer value of the ApiList
 * enum values.
 *
 */
class HiddenApiAccessFlags {
 public:
  enum ApiList {
    kWhitelist = 0,
    kLightGreylist,
    kDarkGreylist,
    kBlacklist,
    kNoList,
  };

  static ALWAYS_INLINE ApiList DecodeFromDex(uint32_t dex_access_flags) {
    DexHiddenAccessFlags flags(dex_access_flags);
    uint32_t int_value = (flags.IsFirstBitSet() ? 1 : 0) + (flags.IsSecondBitSet() ? 2 : 0);
    return static_cast<ApiList>(int_value);
  }

  static ALWAYS_INLINE uint32_t RemoveFromDex(uint32_t dex_access_flags) {
    DexHiddenAccessFlags flags(dex_access_flags);
    flags.SetFirstBit(false);
    flags.SetSecondBit(false);
    return flags.GetEncoding();
  }

  static ALWAYS_INLINE uint32_t EncodeForDex(uint32_t dex_access_flags, ApiList value) {
    DexHiddenAccessFlags flags(RemoveFromDex(dex_access_flags));
    uint32_t int_value = static_cast<uint32_t>(value);
    flags.SetFirstBit((int_value & 1) != 0);
    flags.SetSecondBit((int_value & 2) != 0);
    return flags.GetEncoding();
  }

  static ALWAYS_INLINE ApiList DecodeFromRuntime(uint32_t runtime_access_flags) {
    // This is used in the fast path, only DCHECK here.
    DCHECK_EQ(runtime_access_flags & kAccIntrinsic, 0u);
    uint32_t int_value = (runtime_access_flags & kAccHiddenApiBits) >> kAccFlagsShift;
    return static_cast<ApiList>(int_value);
  }

  static ALWAYS_INLINE uint32_t EncodeForRuntime(uint32_t runtime_access_flags, ApiList value) {
    CHECK_EQ(runtime_access_flags & kAccIntrinsic, 0u);

    uint32_t hidden_api_flags = static_cast<uint32_t>(value) << kAccFlagsShift;
    CHECK_EQ(hidden_api_flags & ~kAccHiddenApiBits, 0u);

    runtime_access_flags &= ~kAccHiddenApiBits;
    return runtime_access_flags | hidden_api_flags;
  }

 private:
  static const int kAccFlagsShift = CTZ(kAccHiddenApiBits);
  static_assert(IsPowerOfTwo((kAccHiddenApiBits >> kAccFlagsShift) + 1),
                "kAccHiddenApiBits are not continuous");

  struct DexHiddenAccessFlags {
    explicit DexHiddenAccessFlags(uint32_t access_flags) : access_flags_(access_flags) {}

    ALWAYS_INLINE uint32_t GetSecondFlag() {
      return ((access_flags_ & kAccNative) != 0) ? kAccDexHiddenBitNative : kAccDexHiddenBit;
    }

    ALWAYS_INLINE bool IsFirstBitSet() {
      static_assert(IsPowerOfTwo(0u), "Following statement checks if *at most* one bit is set");
      return !IsPowerOfTwo(access_flags_ & kAccVisibilityFlags);
    }

    ALWAYS_INLINE void SetFirstBit(bool value) {
      if (IsFirstBitSet() != value) {
        access_flags_ ^= kAccVisibilityFlags;
      }
    }

    ALWAYS_INLINE bool IsSecondBitSet() {
      return (access_flags_ & GetSecondFlag()) != 0;
    }

    ALWAYS_INLINE void SetSecondBit(bool value) {
      if (value) {
        access_flags_ |= GetSecondFlag();
      } else {
        access_flags_ &= ~GetSecondFlag();
      }
    }

    ALWAYS_INLINE uint32_t GetEncoding() const {
      return access_flags_;
    }

    uint32_t access_flags_;
  };
};

inline std::ostream& operator<<(std::ostream& os, HiddenApiAccessFlags::ApiList value) {
  switch (value) {
    case HiddenApiAccessFlags::kWhitelist:
      os << "whitelist";
      break;
    case HiddenApiAccessFlags::kLightGreylist:
      os << "light greylist";
      break;
    case HiddenApiAccessFlags::kDarkGreylist:
      os << "dark greylist";
      break;
    case HiddenApiAccessFlags::kBlacklist:
      os << "blacklist";
      break;
    case HiddenApiAccessFlags::kNoList:
      os << "no list";
      break;
  }
  return os;
}

}  // namespace art


#endif  // ART_LIBDEXFILE_DEX_HIDDEN_API_ACCESS_FLAGS_H_
