use of org.robolectric.res.android.CppAssetManager2 in project robolectric by robolectric.
the class AttributeResolution10 method ResolveAttrs.
// 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
// predict the rest of the iterations' branch correctly.
// 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.
// `out_values` must NOT be nullptr.
// `out_indices` may be nullptr.
public static boolean ResolveAttrs(Theme theme, int def_style_attr, int def_style_res, int[] src_values, int src_values_length, int[] attrs, int attrs_length, int[] out_values, int[] out_indices) {
if (kDebugStyles) {
ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme, def_style_attr, def_style_res);
}
CppAssetManager2 assetmanager = theme.GetAssetManager();
ResTable_config config = new ResTable_config();
Res_value value;
int indicesIdx = 0;
// Load default style from attribute, if specified...
final Ref<Integer> def_style_flags = new Ref<>(0);
if (def_style_attr != 0) {
final Ref<Res_value> valueRef = new Ref<>(null);
if (theme.GetAttribute(def_style_attr, valueRef, def_style_flags).intValue() != kInvalidCookie) {
value = valueRef.get();
if (value.dataType == Res_value.TYPE_REFERENCE) {
def_style_res = value.data;
}
}
}
// Retrieve the default style bag, if requested.
ResolvedBag default_style_bag = null;
if (def_style_res != 0) {
default_style_bag = assetmanager.GetBag(def_style_res);
if (default_style_bag != null) {
def_style_flags.set(def_style_flags.get() | default_style_bag.type_spec_flags);
}
}
BagAttributeFinder def_style_attr_finder = new BagAttributeFinder(default_style_bag);
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
int destOffset = 0;
for (int ii = 0; ii < attrs_length; ii++) {
final int cur_ident = attrs[ii];
if (kDebugStyles) {
ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
}
ApkAssetsCookie cookie = K_INVALID_COOKIE;
int type_set_flags = 0;
value = Res_value.NULL_VALUE;
config.density = 0;
// Retrieve the current input value if available.
if (src_values_length > 0 && src_values[ii] != 0) {
value = new Res_value((byte) Res_value.TYPE_ATTRIBUTE, src_values[ii]);
if (kDebugStyles) {
ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
}
} else {
final Entry entry = def_style_attr_finder.Find(cur_ident);
if (entry != null) {
cookie = entry.cookie;
type_set_flags = def_style_flags.get();
value = entry.value;
if (kDebugStyles) {
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
}
}
}
int resid = 0;
final Ref<Res_value> valueRef = new Ref<>(value);
final Ref<Integer> residRef = new Ref<>(resid);
final Ref<Integer> type_set_flagsRef = new Ref<>(type_set_flags);
final Ref<ResTable_config> configRef = new Ref<>(config);
if (value.dataType != Res_value.TYPE_NULL) {
// Take care of resolving the found resource to its final value.
ApkAssetsCookie new_cookie = theme.ResolveAttributeReference(cookie, valueRef, configRef, type_set_flagsRef, residRef);
if (new_cookie.intValue() != kInvalidCookie) {
cookie = new_cookie;
}
if (kDebugStyles) {
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
}
} else if (value.data != Res_value.DATA_NULL_EMPTY) {
// If we still don't have a value for this attribute, try to find it in the theme!
ApkAssetsCookie new_cookie = theme.GetAttribute(cur_ident, valueRef, type_set_flagsRef);
if (new_cookie.intValue() != kInvalidCookie) {
if (kDebugStyles) {
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
new_cookie = assetmanager.ResolveReference(new_cookie, valueRef, configRef, type_set_flagsRef, residRef);
if (new_cookie.intValue() != kInvalidCookie) {
cookie = new_cookie;
}
if (kDebugStyles) {
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
}
}
value = valueRef.get();
resid = residRef.get();
type_set_flags = type_set_flagsRef.get();
config = configRef.get();
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value.TYPE_REFERENCE && value.data == 0) {
if (kDebugStyles) {
ALOGI("-> Setting to @null!");
}
value = Res_value.NULL_VALUE;
cookie = K_INVALID_COOKIE;
}
if (kDebugStyles) {
ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
}
// Write the final value back to Java.
out_values[destOffset + STYLE_TYPE] = value.dataType;
out_values[destOffset + STYLE_DATA] = value.data;
out_values[destOffset + STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
out_values[destOffset + STYLE_RESOURCE_ID] = resid;
out_values[destOffset + STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[destOffset + STYLE_DENSITY] = config.density;
if (out_indices != null && value.dataType != Res_value.TYPE_NULL) {
indicesIdx++;
out_indices[indicesIdx] = ii;
}
destOffset += STYLE_NUM_ENTRIES;
}
if (out_indices != null) {
out_indices[0] = indicesIdx;
}
return true;
}
use of org.robolectric.res.android.CppAssetManager2 in project robolectric by robolectric.
the class ShadowArscAssetManager9 method nativeGetResourceArray.
// static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
// jintArray out_data) {
@Implementation(minSdk = P)
protected static int nativeGetResourceArray(long ptr, @ArrayRes int resid, @NonNull int[] out_data) {
CppAssetManager2 assetmanager = AssetManagerFromLong(ptr);
ResolvedBag bag = assetmanager.GetBag(resid);
if (bag == null) {
return -1;
}
int out_data_length = out_data.length;
if ((int) (bag.entry_count) > out_data_length * STYLE_NUM_ENTRIES) {
throw new IllegalArgumentException("Input array is not large enough");
}
int[] buffer = // reinterpret_cast<int*>(env.GetPrimitiveArrayCritical(out_data, null));
out_data;
if (buffer == null) {
return -1;
}
int[] cursor = buffer;
for (int i = 0; i < bag.entry_count; i++) {
ResolvedBag.Entry entry = bag.entries[i];
final Ref<Res_value> value = new Ref<>(entry.value);
final Ref<ResTable_config> selected_config = new Ref<>(new ResTable_config());
selected_config.get().density = 0;
final Ref<Integer> flags = new Ref<>(bag.type_spec_flags);
final Ref<Integer> ref = new Ref<>(0);
ApkAssetsCookie cookie = assetmanager.ResolveReference(entry.cookie, value, selected_config, flags, ref);
if (cookie.intValue() == kInvalidCookie) {
// env.ReleasePrimitiveArrayCritical(out_data, buffer, JNI_ABORT);
return -1;
}
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.get().dataType == Res_value.TYPE_REFERENCE && value.get().data == 0) {
value.set(Res_value.NULL_VALUE);
}
int offset = i * STYLE_NUM_ENTRIES;
cursor[offset + STYLE_TYPE] = (int) (value.get().dataType);
cursor[offset + STYLE_DATA] = (int) (value.get().data);
cursor[offset + STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
cursor[offset + STYLE_RESOURCE_ID] = (int) (ref.get());
cursor[offset + STYLE_CHANGING_CONFIGURATIONS] = (int) (flags.get());
cursor[offset + STYLE_DENSITY] = (int) (selected_config.get().density);
// cursor += STYLE_NUM_ENTRIES;
}
// env.ReleasePrimitiveArrayCritical(out_data, buffer, 0);
return (int) (bag.entry_count);
}
use of org.robolectric.res.android.CppAssetManager2 in project robolectric by robolectric.
the class ShadowArscAssetManager9 method nativeOpenAsset.
// static jlong NativeOpenAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
// jint access_mode) {
@Implementation(minSdk = P)
protected static long nativeOpenAsset(long ptr, @NonNull String asset_path, int access_mode) throws FileNotFoundException {
String asset_path_utf8 = asset_path;
if (asset_path_utf8 == null) {
// This will throw NPE.
return 0;
}
ATRACE_NAME(String.format("AssetManager::OpenAsset(%s)", asset_path_utf8));
if (access_mode != Asset.AccessMode.ACCESS_UNKNOWN.mode() && access_mode != Asset.AccessMode.ACCESS_RANDOM.mode() && access_mode != Asset.AccessMode.ACCESS_STREAMING.mode() && access_mode != Asset.AccessMode.ACCESS_BUFFER.mode()) {
throw new IllegalArgumentException("Bad access mode");
}
CppAssetManager2 assetmanager = AssetManagerFromLong(ptr);
Asset asset = assetmanager.Open(asset_path_utf8, Asset.AccessMode.fromInt(access_mode));
if (!isTruthy(asset)) {
throw new FileNotFoundException(asset_path_utf8);
}
return Registries.NATIVE_ASSET_REGISTRY.register(asset);
}
use of org.robolectric.res.android.CppAssetManager2 in project robolectric by robolectric.
the class ShadowArscAssetManager9 method nativeCreate.
// static jlong NativeCreate(JNIEnv* /*env*/, jclass /*clazz*/) {
@Implementation(minSdk = P)
protected static long nativeCreate() {
// AssetManager2 needs to be protected by a lock. To avoid cache misses, we allocate the lock
// and
// AssetManager2 in a contiguous block (GuardedAssetManager).
// return reinterpret_cast<long>(new GuardedAssetManager());
long cppAssetManagerRef;
// we want to share a single instance of the system CppAssetManager2
if (inNonSystemConstructor) {
CppAssetManager2 appAssetManager = new CppAssetManager2();
cppAssetManagerRef = Registries.NATIVE_ASSET_MANAGER_REGISTRY.register(appAssetManager);
} else {
if (systemCppAssetManager2 == null) {
systemCppAssetManager2 = new CppAssetManager2();
systemCppAssetManager2Ref = Registries.NATIVE_ASSET_MANAGER_REGISTRY.register(systemCppAssetManager2);
}
cppAssetManagerRef = systemCppAssetManager2Ref;
}
return cppAssetManagerRef;
}
use of org.robolectric.res.android.CppAssetManager2 in project robolectric by robolectric.
the class ShadowFontBuilder method nGetNativeAsset.
// transliterated from frameworks/base/core/jni/android/graphics/fonts/Font.cpp
@Implementation(maxSdk = Q)
protected static long nGetNativeAsset(AssetManager assetMgr, String path, boolean isAsset, int cookie) {
// NPE_CHECK_RETURN_ZERO(env, assetMgr);
Preconditions.checkNotNull(assetMgr);
// NPE_CHECK_RETURN_ZERO(env, path);
Preconditions.checkNotNull(path);
// Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, assetMgr);
CppAssetManager2 mgr = ShadowArscAssetManager10.AssetManagerForJavaObject(assetMgr);
// if (mgr == nullptr) {
if (mgr == null) {
return 0;
}
// ScopedUtfChars str(env, path);
// if (str.c_str() == nullptr) {
// return 0;
// }
// std::unique_ptr<Asset> asset;
Asset asset;
{
// ScopedLock<AssetManager2> locked_mgr(*mgr);
if (isAsset) {
// asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
asset = mgr.Open(path, AccessMode.ACCESS_BUFFER);
} else if (cookie > 0) {
// Valid java cookies are 1-based, but AssetManager cookies are 0-based.
// asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1), Asset::ACCESS_BUFFER);
asset = mgr.OpenNonAsset(path, ApkAssetsCookie.forInt(cookie - 1), AccessMode.ACCESS_BUFFER);
} else {
// asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
asset = mgr.OpenNonAsset(path, AccessMode.ACCESS_BUFFER);
}
}
// return reinterpret_cast<jlong>(asset.release());
return Registries.NATIVE_ASSET_REGISTRY.register(asset);
}
Aggregations