• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.hardware.cts;
18 
19 import static android.content.res.Configuration.SCREENLAYOUT_SIZE_LARGE;
20 import static android.content.res.Configuration.SCREENLAYOUT_SIZE_NORMAL;
21 import static android.content.res.Configuration.SCREENLAYOUT_SIZE_SMALL;
22 import static android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE;
23 import static android.util.DisplayMetrics.DENSITY_400;
24 import static android.util.DisplayMetrics.DENSITY_560;
25 import static android.util.DisplayMetrics.DENSITY_HIGH;
26 import static android.util.DisplayMetrics.DENSITY_LOW;
27 import static android.util.DisplayMetrics.DENSITY_MEDIUM;
28 import static android.util.DisplayMetrics.DENSITY_TV;
29 import static android.util.DisplayMetrics.DENSITY_XHIGH;
30 
31 import static org.junit.Assert.assertFalse;
32 import static org.junit.Assert.assertTrue;
33 
34 import android.app.ActivityManager;
35 import android.content.Context;
36 import android.content.pm.PackageManager;
37 import android.content.res.Configuration;
38 import android.os.Build;
39 import android.os.StatFs;
40 import android.util.DisplayMetrics;
41 import android.util.Log;
42 import android.view.WindowManager;
43 
44 import androidx.test.InstrumentationRegistry;
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import com.android.compatibility.common.util.CddTest;
48 
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.junit.runner.RunWith;
52 
53 import java.io.File;
54 
55 /**
56  * Tests that devices with low RAM specify themselves as Low RAM devices
57  */
58 @RunWith(AndroidJUnit4.class)
59 public class LowRamDeviceTest {
60 
61     private static final long ONE_MEGABYTE = 1048576L;
62     private static final String TAG = "LowRamDeviceTest";
63     private static final long LOW_RAM_MAX = 1024;
64     private static final float MIN_APP_DATA_PARTITION_SIZE_GB = 4f;
65     private static final float MIN_APP_DATA_PARTITION_SIZE_LOW_RAM_GB = 1.1f;
66     private static final float MIN_SHARED_DATA_PARTITION_SIZE_GB = 1f;
67     private static final long GB_TO_BYTES_MULTIPLIER = 1024 * 1024 * 1024;
68 
69     private Context mContext;
70     private PackageManager mPackageManager;
71     private ActivityManager mActivityManager;
72     private DisplayMetrics mDisplayMetrics;
73 
74     @Before
setUp()75     public void setUp() throws Exception {
76         mContext = InstrumentationRegistry.getTargetContext();
77         mPackageManager = mContext.getPackageManager();
78         mActivityManager =
79                 (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
80 
81         mDisplayMetrics = new DisplayMetrics();
82         WindowManager windowManager =
83                 (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
84         windowManager.getDefaultDisplay().getMetrics(mDisplayMetrics);
85     }
86 
87     /**
88      * Test the devices reported memory to ensure it meets the minimum values described
89      * in CDD 7.6.1.
90      */
91     @Test
92     @CddTest(requirement="7.6.1")
testMinimumMemory()93     public void testMinimumMemory() {
94         int density = mDisplayMetrics.densityDpi;
95         Boolean supports64Bit = supportsSixtyFourBit();
96         int screenSize = getScreenSize();
97         Boolean lowRamDevice = mActivityManager.isLowRamDevice();
98         Boolean watch = mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
99 
100         Log.i(TAG, String.format("density=%d, supports64Bit=%s, screenSize=%d, watch=%s",
101                 density, supports64Bit, screenSize, watch));
102 
103         if (watch) {
104             assertFalse("Device is not expected to be 64-bit", supports64Bit);
105             assertMinMemoryMb(416);
106         } else if (lessThanDpi(density, DENSITY_HIGH, screenSize,
107                 SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
108                 lessThanDpi(density, DENSITY_MEDIUM, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
109                 lessThanDpi(density, DENSITY_LOW, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
110 
111             if (supports64Bit) {
112                 assertMinMemoryMb(816);
113             } else {
114                 assertMinMemoryMb(416);
115             }
116         } else if (greaterThanDpi(density, DENSITY_560, screenSize,
117                 SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
118                 greaterThanDpi(density, DENSITY_400, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
119                 greaterThanDpi(density, DENSITY_XHIGH, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
120 
121             if (supports64Bit) {
122                 assertMinMemoryMb(1824);
123             } else {
124                 assertMinMemoryMb(1344);
125             }
126         } else if (greaterThanDpi(density, DENSITY_400, screenSize,
127                 SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
128                 greaterThanDpi(density, DENSITY_XHIGH, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
129                 greaterThanDpi(density, DENSITY_TV, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
130 
131             if (supports64Bit) {
132                 assertMinMemoryMb(1280);
133             } else {
134                 assertMinMemoryMb(896);
135             }
136         } else if (greaterThanDpi(density, DENSITY_XHIGH, screenSize,
137                 SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
138                 greaterThanDpi(density, DENSITY_TV, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
139                 greaterThanDpi(density, DENSITY_MEDIUM, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
140 
141             if (supports64Bit) {
142                 assertMinMemoryMb(944);
143             } else {
144                 assertMinMemoryMb(592);
145             }
146         }
147     }
148 
149     @Test
150     @CddTest(requirement="7.6.2")
testMinSharedDataPartitionSize()151     public void testMinSharedDataPartitionSize() {
152         assertDataPartitionMinimumSize(
153                 "Shared data",
154                 mContext.getExternalFilesDir(null),
155                 MIN_SHARED_DATA_PARTITION_SIZE_GB);
156     }
157 
158     @Test
159     @CddTest(requirement="7.6.1/H-9-2,7.6.1/H-10-1")
testMinDataPartitionSize()160     public void testMinDataPartitionSize() {
161         long totalMemoryMb = getTotalMemory() / ONE_MEGABYTE;
162         boolean lowRam = totalMemoryMb <= LOW_RAM_MAX;
163 
164         if (lowRam) {
165             assertDataPartitionMinimumSize(
166                     "Application data",
167                     mContext.getFilesDir(),
168                     MIN_APP_DATA_PARTITION_SIZE_LOW_RAM_GB);
169         } else {
170             assertDataPartitionMinimumSize(
171                     "Application data", mContext.getFilesDir(), MIN_APP_DATA_PARTITION_SIZE_GB);
172         }
173     }
174 
175     /**
176      * @return the total memory accessible by the kernel as defined by
177      * {@code ActivityManager.MemoryInfo}.
178      */
getTotalMemory()179     private long getTotalMemory() {
180         ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
181         mActivityManager.getMemoryInfo(memoryInfo);
182         return memoryInfo.totalMem;
183     }
184 
185     /** @return the screen size as defined in {@Configuration}. */
getScreenSize()186     private int getScreenSize() {
187         Configuration config = mContext.getResources().getConfiguration();
188         return config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
189     }
190 
191     /** @return true iff this device supports 64 bit ABIs */
supportsSixtyFourBit()192     private static boolean supportsSixtyFourBit() {
193         return Build.SUPPORTED_64_BIT_ABIS.length > 0;
194     }
195 
196     /** Asserts that the given values conform to the specs in CDD 7.6.1 */
assertMinMemoryMb(long minMb)197     private void assertMinMemoryMb(long minMb) {
198 
199         long totalMemoryMb = getTotalMemory() / ONE_MEGABYTE;
200         boolean lowRam = totalMemoryMb <= LOW_RAM_MAX;
201         boolean lowRamDevice = mActivityManager.isLowRamDevice();
202 
203         Log.i(TAG, String.format("minMb=%,d", minMb));
204         Log.i(TAG, String.format("totalMemoryMb=%,d", totalMemoryMb));
205         Log.i(TAG, "lowRam=" + lowRam);
206         Log.i(TAG, "lowRamDevice=" + lowRamDevice);
207 
208         assertTrue(String.format("Does not meet minimum memory requirements (CDD 7.6.1)."
209                 + "Found = %d, Minimum = %d", totalMemoryMb, minMb), totalMemoryMb >= minMb);
210 
211         assertTrue("Device must specify low RAM property: ro.config.low_ram=true",
212                 !lowRam || (lowRam && lowRamDevice));
213     }
214 
lessThanDpi(int actualDensityDpi, int expectedDensityDpi, int actualScreenSize, int... expectedScreenSizes)215     private static boolean lessThanDpi(int actualDensityDpi, int expectedDensityDpi,
216             int actualScreenSize, int... expectedScreenSizes) {
217         return actualDensityDpi <= expectedDensityDpi &&
218                 contains(expectedScreenSizes, actualScreenSize);
219     }
220 
greaterThanDpi(int actualDensityDpi, int expectedDensityDpi, int actualScreenSize, int... expectedScreenSizes)221     private static boolean greaterThanDpi(int actualDensityDpi, int expectedDensityDpi,
222             int actualScreenSize, int... expectedScreenSizes) {
223         return actualDensityDpi >= expectedDensityDpi &&
224                 contains(expectedScreenSizes, actualScreenSize);
225     }
226 
227     /** @return true iff the {@code array} contains the {@code target} */
contains(int [] array, int target)228     private static boolean contains(int [] array, int target) {
229         for(int a : array) {
230             if (a == target) {
231                 return true;
232             }
233         }
234         return false;
235     }
236 
assertDataPartitionMinimumSize( String partitionName, File fileInPartition, float minPartitionSizeGb)237     private void assertDataPartitionMinimumSize(
238             String partitionName, File fileInPartition, float minPartitionSizeGb) {
239         StatFs statFs = new StatFs(fileInPartition.getAbsolutePath());
240         long size = statFs.getTotalBytes();
241         long minSizeBytes = (long) minPartitionSizeGb * GB_TO_BYTES_MULTIPLIER;
242 
243         assertTrue(
244                 String.format("%s partition size does not meet requirement. "
245                         + "Found = %d, Minimum = %d", partitionName, size, minSizeBytes),
246                 size > minSizeBytes);
247     }
248 }
249