Fix Android system memory requirements
authorIlkka Saarelainen <ilkka.saarelainen@siru.fi>
Tue, 27 Jul 2021 11:31:06 +0000 (14:31 +0300)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Fri, 13 Aug 2021 08:15:54 +0000 (08:15 +0000)
This CL changes how the available system memory is defined in Android.
The actual available system memory size is now used instead of
determining the available system memory by the CDD.

Affects:

dEQP-VK.api.buffer.suballocation.*
dEQP-VK.api.buffer.dedicated_alloc.*
dEQP-VK.api.object_management.*
dEQP-VK.memory.allocation.*
dEQP-VK.memory.device_group_allocation.*
dEQP-VK.pipeline.render_to_image.*.small.*
dEQP-VK.pipeline.render_to_image.*.huge.*

Components: Framework, Vulkan

VK-GL-CTS issue: 2621

Change-Id: I92fd157ec3928313ac92c29e6cbb3413c64a5096

framework/platform/android/tcuAndroidPlatform.cpp
framework/platform/android/tcuAndroidUtil.cpp
framework/platform/android/tcuAndroidUtil.hpp

index b9a4c71..f671854 100644 (file)
@@ -286,11 +286,9 @@ static size_t getTotalSystemMemory (ANativeActivity* activity)
 
        try
        {
-               const size_t    cddRequiredSize = getCDDRequiredSystemMemory(activity);
-
-               print("Device has at least %.2f MiB total system memory per Android CDD\n", double(cddRequiredSize) / double(MiB));
-
-               return cddRequiredSize;
+               const size_t totalMemory = getTotalAndroidSystemMemory(activity);
+               print("Device has %.2f MiB of system memory\n", static_cast<double>(totalMemory) / static_cast<double>(MiB));
+               return totalMemory;
        }
        catch (const std::exception& e)
        {
index c62ee05..75d9309 100644 (file)
@@ -201,9 +201,9 @@ const char* getJNITypeStr<int> (void)
 }
 
 template<>
-const char* getJNITypeStr<float> (void)
+const char* getJNITypeStr<deInt64> (void)
 {
-       return "F";
+       return "J";
 }
 
 template<>
@@ -283,17 +283,10 @@ template<typename FieldType>
 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>
@@ -355,202 +348,6 @@ void describePlatform (JNIEnv* env, std::ostream& dst)
        }
 }
 
-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)
@@ -589,75 +386,37 @@ void describePlatform (ANativeActivity* activity, std::ostream& dst)
        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
index 78601a6..f3339ba 100644 (file)
@@ -52,39 +52,7 @@ ScreenOrientation    mapScreenRotation                       (ScreenRotation rotation);
 
 void                           describePlatform                        (ANativeActivity* activity, std::ostream& dst);
 
-bool                           hasSystemFeature                        (ANativeActivity* activity, const char* name);
-
-//! android.util.DisplayMetrics
-struct DisplayMetrics
-{
-       float           density;
-       float           scaledDensity;
-       int                     densityDpi;
-
-       int                     widthPixels;
-       int                     heightPixels;
-
-       float           xdpi;
-       float           ydpi;
-
-       DisplayMetrics (void)
-               : density               (0.0f)
-               , scaledDensity (0.0f)
-               , densityDpi    (0)
-               , widthPixels   (0)
-               , heightPixels  (0)
-               , xdpi                  (0.0f)
-               , ydpi                  (0.0f)
-       {
-       }
-};
-
-DisplayMetrics         getDisplayMetrics                       (ANativeActivity* activity);
-
-//! Get minimum required system memory that must be available to kernel and
-//! userspace according to Android CDD.
-size_t                         getCDDRequiredSystemMemory      (ANativeActivity* activity);
-
+size_t                         getTotalAndroidSystemMemory     (ANativeActivity* activity);
 } // Android
 } // tcu