}
template<>
-const char* getJNITypeStr<float> (void)
+const char* getJNITypeStr<deInt64> (void)
{
- return "F";
+ return "J";
}
template<>
FieldType getFieldValue (JNIEnv* env, jobject obj, jfieldID fieldId);
template<>
-int getFieldValue<int> (JNIEnv* env, jobject obj, jfieldID fieldId)
+deInt64 getFieldValue<deInt64> (JNIEnv* env, jobject obj, jfieldID fieldId)
{
DE_ASSERT(obj && fieldId);
- return env->GetIntField(obj, fieldId);
-}
-
-template<>
-float getFieldValue<float> (JNIEnv* env, jobject obj, jfieldID fieldId)
-{
- DE_ASSERT(obj && fieldId);
- return env->GetFloatField(obj, fieldId);
+ return env->GetLongField(obj, fieldId);
}
template<typename FieldType>
}
}
-vector<string> getSupportedABIs (JNIEnv* env)
-{
- return getStaticField<vector<string> >(env, "android/os/Build", "SUPPORTED_ABIS");
-}
-
-bool supportsAny64BitABI (JNIEnv* env)
-{
- const vector<string> supportedAbis = getSupportedABIs(env);
- const char* known64BitAbis[] = { "arm64-v8a", "x86_64", "mips64" };
-
- for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(known64BitAbis); ++ndx)
- {
- if (de::contains(supportedAbis.begin(), supportedAbis.end(), string(known64BitAbis[ndx])))
- return true;
- }
-
- return false;
-}
-
-bool supportsAny64BitABI (ANativeActivity* activity)
-{
- const ScopedJNIEnv env(activity->vm);
-
- return supportsAny64BitABI(env.getEnv());
-}
-
-jobject getPackageManager (JNIEnv* env, jobject activity)
-{
- const jclass activityCls = getObjectClass(env, activity);
- const jmethodID getPMID = getMethodID(env, activityCls, "getPackageManager", "()Landroid/content/pm/PackageManager;");
- const jobject packageManager = env->CallObjectMethod(activity, getPMID);
-
- return packageManager;
-}
-
-bool hasSystemFeature (JNIEnv* env, jobject activity, const char* name)
-{
- const LocalRef packageManager (env, getPackageManager(env, activity));
- const jclass pmCls = getObjectClass(env, *packageManager);
- const jmethodID hasFeatureID = getMethodID(env, pmCls, "hasSystemFeature", "(Ljava/lang/String;)Z");
- const LocalRef nameStr (env, env->NewStringUTF(name));
- jvalue callArgs[1];
-
- callArgs[0].l = *nameStr;
-
- return env->CallBooleanMethodA(*packageManager, hasFeatureID, callArgs) == JNI_TRUE;
-}
-
-jobject getWindowManager (JNIEnv* env, jobject activity)
-{
- const jclass activityCls = getObjectClass(env, activity);
- const jmethodID getWMID = getMethodID(env, activityCls, "getWindowManager", "()Landroid/view/WindowManager;");
- const jobject windowManager = env->CallObjectMethod(activity, getWMID);
-
- return windowManager;
-}
-
-jobject getDefaultDisplay (JNIEnv* env, jobject windowManager)
-{
- const jclass wmClass = getObjectClass(env, windowManager);
- const jmethodID getDisplayID = getMethodID(env, wmClass, "getDefaultDisplay", "()Landroid/view/Display;");
- const jobject display = env->CallObjectMethod(windowManager, getDisplayID);
-
- return display;
-}
-
-jobject createDisplayMetrics (JNIEnv* env)
-{
- const jclass displayMetricsCls = findClass(env, "android/util/DisplayMetrics");
- const jmethodID ctorId = getMethodID(env, displayMetricsCls, "<init>", "()V");
-
- return env->NewObject(displayMetricsCls, ctorId);
-}
-
-DisplayMetrics getDisplayMetrics (JNIEnv* env, jobject activity)
-{
- const LocalRef windowManager (env, getWindowManager(env, activity));
- const LocalRef defaultDisplay (env, getDefaultDisplay(env, *windowManager));
- const LocalRef nativeMetrics (env, createDisplayMetrics(env));
- const jclass displayCls = getObjectClass(env, *defaultDisplay);
- const jmethodID getMetricsID = getMethodID(env, displayCls, "getMetrics", "(Landroid/util/DisplayMetrics;)V");
- DisplayMetrics metrics;
-
- {
- jvalue callArgs[1];
- callArgs[0].l = *nativeMetrics;
-
- env->CallVoidMethodA(*defaultDisplay, getMetricsID, callArgs);
- }
-
- metrics.density = getField<float> (env, *nativeMetrics, "density");
- metrics.densityDpi = getField<int> (env, *nativeMetrics, "densityDpi");
- metrics.scaledDensity = getField<float> (env, *nativeMetrics, "scaledDensity");
- metrics.widthPixels = getField<int> (env, *nativeMetrics, "widthPixels");
- metrics.heightPixels = getField<int> (env, *nativeMetrics, "heightPixels");
- metrics.xdpi = getField<float> (env, *nativeMetrics, "xdpi");
- metrics.ydpi = getField<float> (env, *nativeMetrics, "ydpi");
-
- return metrics;
-}
-
-enum ScreenClass
-{
- SCREEN_CLASS_WEAR = 0,
- SCREEN_CLASS_SMALL,
- SCREEN_CLASS_NORMAL,
- SCREEN_CLASS_LARGE,
- SCREEN_CLASS_EXTRA_LARGE,
-
- SCREEN_CLASS_LAST
-};
-
-enum DensityClass
-{
- DENSITY_CLASS_LDPI = 120,
- DENSITY_CLASS_MDPI = 160,
- DENSITY_CLASS_TVDPI = 213,
- DENSITY_CLASS_HDPI = 240,
- DENSITY_CLASS_280DPI = 280,
- DENSITY_CLASS_XHDPI = 320,
- DENSITY_CLASS_360DPI = 360,
- DENSITY_CLASS_400DPI = 400,
- DENSITY_CLASS_420DPI = 420,
- DENSITY_CLASS_XXHDPI = 480,
- DENSITY_CLASS_560DPI = 560,
- DENSITY_CLASS_XXXHDPI = 640,
-
- DENSITY_CLASS_INVALID = -1,
-};
-
-ScreenClass getScreenClass (const DisplayMetrics& displayMetrics)
-{
- static const struct
- {
- int minWidthDp;
- int minHeightDp;
- ScreenClass screenClass;
- } s_screenClasses[] =
- {
- // Must be ordered from largest to smallest
- { 960, 720, SCREEN_CLASS_EXTRA_LARGE },
- { 640, 480, SCREEN_CLASS_LARGE },
- { 480, 320, SCREEN_CLASS_NORMAL },
- { 426, 320, SCREEN_CLASS_SMALL },
- };
-
- const float dpScale = float(displayMetrics.densityDpi) / 160.f;
-
- // \note Assume landscape orientation for comparison
- const int widthP = de::max(displayMetrics.widthPixels, displayMetrics.heightPixels);
- const int heightP = de::min(displayMetrics.widthPixels, displayMetrics.heightPixels);
-
- const int widthDp = deFloorFloatToInt32(float(widthP) / dpScale);
- const int heightDp = deFloorFloatToInt32(float(heightP) / dpScale);
-
- for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_screenClasses); ++ndx)
- {
- if ((s_screenClasses[ndx].minWidthDp <= widthDp) &&
- (s_screenClasses[ndx].minHeightDp <= heightDp))
- return s_screenClasses[ndx].screenClass;
- }
-
- return SCREEN_CLASS_WEAR;
-}
-
-bool isValidDensityClass (int dpi)
-{
- switch (dpi)
- {
- case DENSITY_CLASS_LDPI:
- case DENSITY_CLASS_MDPI:
- case DENSITY_CLASS_TVDPI:
- case DENSITY_CLASS_HDPI:
- case DENSITY_CLASS_280DPI:
- case DENSITY_CLASS_XHDPI:
- case DENSITY_CLASS_360DPI:
- case DENSITY_CLASS_400DPI:
- case DENSITY_CLASS_420DPI:
- case DENSITY_CLASS_XXHDPI:
- case DENSITY_CLASS_560DPI:
- case DENSITY_CLASS_XXXHDPI:
- return true;
-
- default:
- return false;
- }
-}
-
-DensityClass getDensityClass (const DisplayMetrics& displayMetrics)
-{
- if (isValidDensityClass(displayMetrics.densityDpi))
- return (DensityClass)displayMetrics.densityDpi;
- else
- return DENSITY_CLASS_INVALID;
-}
-
} // anonymous
ScreenOrientation mapScreenRotation (ScreenRotation rotation)
describePlatform(env.getEnv(), dst);
}
-bool hasSystemFeature (ANativeActivity* activity, const char* name)
+size_t getTotalAndroidSystemMemory (ANativeActivity* activity)
{
- const ScopedJNIEnv env(activity->vm);
-
- return hasSystemFeature(env.getEnv(), activity->clazz, name);
-}
-
-DisplayMetrics getDisplayMetrics (ANativeActivity* activity)
-{
- const ScopedJNIEnv env(activity->vm);
-
- return getDisplayMetrics(env.getEnv(), activity->clazz);
-}
-
-size_t getCDDRequiredSystemMemory (ANativeActivity* activity)
-{
- const DisplayMetrics displayMetrics = getDisplayMetrics(activity);
- const ScreenClass screenClass = getScreenClass(displayMetrics);
- const bool isWearDevice = hasSystemFeature(activity, "android.hardware.type.watch");
- const bool is64BitDevice = supportsAny64BitABI(activity);
- const size_t MiB = (size_t)(1<<20);
-
- if (!is64BitDevice)
- TCU_CHECK_INTERNAL(sizeof(void*) != sizeof(deUint64));
-
- if (isWearDevice)
- {
- TCU_CHECK_INTERNAL(!is64BitDevice);
- return 416*MiB;
- }
- else
- {
- const DensityClass densityClass = getDensityClass(displayMetrics);
+ const ScopedJNIEnv scopedJniEnv (activity->vm);
+ JNIEnv* env = scopedJniEnv.getEnv();
- TCU_CHECK_INTERNAL(de::inRange(screenClass, SCREEN_CLASS_SMALL, SCREEN_CLASS_EXTRA_LARGE));
- TCU_CHECK_INTERNAL(densityClass != DENSITY_CLASS_INVALID);
-
- static const struct
- {
- DensityClass smallNormalScreenDensity;
- DensityClass largeScreenDensity;
- DensityClass extraLargeScreenDensity;
- size_t requiredMem32bit;
- size_t requiredMem64bit;
- } s_classes[] =
- {
- // Must be ordered from largest to smallest
- { DENSITY_CLASS_560DPI, DENSITY_CLASS_400DPI, DENSITY_CLASS_XHDPI, 1344*MiB, 1824*MiB },
- { DENSITY_CLASS_400DPI, DENSITY_CLASS_XHDPI, DENSITY_CLASS_TVDPI, 896*MiB, 1280*MiB },
- { DENSITY_CLASS_XHDPI, DENSITY_CLASS_HDPI, DENSITY_CLASS_MDPI, 512*MiB, 832*MiB },
+ // Get activity manager instance:
+ // ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ const jclass activityManagerClass = findClass(env, "android/app/ActivityManager");
+ const LocalRef activityString (env, env->NewStringUTF("activity")); // Context.ACTIVITY_SERVICE == "activity"
+ const jclass activityClass = getObjectClass(env, activity->clazz);
+ const jmethodID getServiceID = getMethodID(env, activityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+ LocalRef activityManager (env, env->CallObjectMethod(activity->clazz, getServiceID, *activityString));
+ checkException(env);
+ TCU_CHECK_INTERNAL(activityManager);
- // \note Last is default, and density values are maximum allowed
- { DENSITY_CLASS_280DPI, DENSITY_CLASS_MDPI, DENSITY_CLASS_LDPI, 424*MiB, 704*MiB },
- };
+ // Crete memory info instance:
+ // ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ const jclass memoryInfoClass = findClass(env, "android/app/ActivityManager$MemoryInfo");
+ const jmethodID memoryInfoCtor = getMethodID(env, memoryInfoClass, "<init>", "()V");
+ LocalRef memoryInfo (env, env->NewObject(memoryInfoClass, memoryInfoCtor));
+ checkException(env);
+ TCU_CHECK_INTERNAL(memoryInfo);
- for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_classes); ++ndx)
- {
- const DensityClass minClass = screenClass == SCREEN_CLASS_EXTRA_LARGE ? s_classes[ndx].extraLargeScreenDensity
- : screenClass == SCREEN_CLASS_LARGE ? s_classes[ndx].largeScreenDensity
- : /* small/normal */ s_classes[ndx].smallNormalScreenDensity;
- const size_t reqMem = is64BitDevice ? s_classes[ndx].requiredMem64bit : s_classes[ndx].requiredMem32bit;
- const bool isLast = ndx == DE_LENGTH_OF_ARRAY(s_classes)-1;
-
- if ((isLast && minClass >= densityClass) || (!isLast && minClass <= densityClass))
- return reqMem;
- }
+ // Get memory info from activity manager:
+ // activityManager.getMemoryInfo(memoryInfo);
+ const jmethodID getMemoryInfoID = getMethodID(env, activityManagerClass, "getMemoryInfo", "(Landroid/app/ActivityManager$MemoryInfo;)V");
+ checkException(env);
+ env->CallVoidMethod(*activityManager, getMemoryInfoID, *memoryInfo);
- TCU_THROW(InternalError, "Invalid combination of density and screen size");
- }
+ // Return 'totalMem' field from the memory info instance.
+ return static_cast<size_t>(getField<deInt64>(env, *memoryInfo, "totalMem"));
}
} // Android