/*
 * 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_RUNTIME_HIDDEN_API_ACCESS_FLAGS_H_
#define ART_RUNTIME_HIDDEN_API_ACCESS_FLAGS_H_

#include "base/bit_utils.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,
  };

  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) {
    if ((runtime_access_flags & kAccIntrinsic) != 0) {
      return kWhitelist;
    } else {
      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;
  }
  return os;
}

}  // namespace art


#endif  // ART_RUNTIME_HIDDEN_API_ACCESS_FLAGS_H_
