1 /* 2 * Copyright (C) 2009 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 package android.os.cts; 17 18 import android.content.Context; 19 import android.os.Debug; 20 import android.platform.test.annotations.AppModeFull; 21 import android.test.AndroidTestCase; 22 23 import com.android.compatibility.common.util.TestThread; 24 25 import java.io.File; 26 import java.io.FileOutputStream; 27 import java.io.IOException; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.logging.Level; 32 import java.util.logging.Logger; 33 34 public class DebugTest extends AndroidTestCase { 35 private static final Logger Log = Logger.getLogger(DebugTest.class.getName()); 36 37 // Static list here to avoid R8 optimizations in #testGetAndReset causing wrong alloc counts 38 private static final List<int[]> TEST_ALLOC = new ArrayList<>(); 39 40 @Override tearDown()41 public void tearDown() throws Exception { 42 super.tearDown(); 43 Debug.stopAllocCounting(); 44 Debug.resetAllCounts(); 45 } 46 testPrintLoadedClasses()47 public void testPrintLoadedClasses() { 48 Debug.printLoadedClasses(Debug.SHOW_FULL_DETAIL); 49 Debug.printLoadedClasses(Debug.SHOW_CLASSLOADER); 50 Debug.printLoadedClasses(Debug.SHOW_INITIALIZED); 51 } 52 testStartMethodTracing()53 public void testStartMethodTracing() throws InterruptedException { 54 final long debugTime = 3000; 55 final String traceName = getFileName(); 56 57 final int bufSize = 1024 * 1024 * 2; 58 final int debug_flag = Debug.TRACE_COUNT_ALLOCS; 59 60 Debug.startMethodTracing(traceName); 61 Thread.sleep(debugTime); 62 Debug.stopMethodTracing(); 63 64 Debug.startMethodTracing(traceName, bufSize); 65 Thread.sleep(debugTime); 66 Debug.stopMethodTracing(); 67 68 Debug.startMethodTracing(traceName, bufSize, debug_flag); 69 Thread.sleep(debugTime); 70 Debug.stopMethodTracing(); 71 } 72 73 @AppModeFull( 74 reason = "Default trace in Context#getExternalFilesDir not accessible by instant apps" 75 ) testStartMethodTracingDefaultExternalStorage()76 public void testStartMethodTracingDefaultExternalStorage() throws InterruptedException { 77 final long debugTime = 3000; 78 79 Debug.startMethodTracing(); 80 Thread.sleep(debugTime); 81 Debug.stopMethodTracing(); 82 } 83 getFileName()84 private String getFileName() { 85 File dir = getContext().getFilesDir(); 86 File file = new File(dir, "debug.trace"); 87 return file.getAbsolutePath(); 88 } 89 testStartNativeTracing()90 public void testStartNativeTracing() { 91 Debug.startNativeTracing(); 92 93 Debug.stopNativeTracing(); 94 } 95 testThreadCpuTimeNanos()96 public void testThreadCpuTimeNanos() throws Exception { 97 if (Debug.threadCpuTimeNanos() == -1) { 98 // Indicates the system does not support this operation, so we can't test it. 99 Log.log(Level.WARNING, "Skipping testThreadCpuTimeNanos() on unsupported system"); 100 return; 101 } 102 103 TestThread t = new TestThread(new Runnable() { 104 @Override 105 public void run() { 106 long startDebugTime = Debug.threadCpuTimeNanos(); 107 108 // Do some work for a second to increment CPU time 109 long startSystemTime = System.currentTimeMillis(); 110 while (System.currentTimeMillis() - startSystemTime < 1000) { 111 Math.random(); 112 } 113 114 // Verify that threadCpuTimeNanos reports that some work was done. 115 // We can't do more than this because the specification for this API call makes 116 // clear that this is only an estimate. 117 assertTrue(Debug.threadCpuTimeNanos() > startDebugTime); 118 } 119 }); 120 t.start(); 121 t.join(); 122 } 123 testWaitingForDebugger()124 public void testWaitingForDebugger() { 125 assertFalse(Debug.waitingForDebugger()); 126 } 127 testGetAndReset()128 public void testGetAndReset() throws IOException { 129 final String dumpFile = getFileName(); 130 Debug.startAllocCounting(); 131 132 final int MIN_GLOBAL_ALLOC_COUNT = 100; 133 final int ARRAY_SIZE = 100; 134 final int MIN_GLOBAL_ALLOC_SIZE = MIN_GLOBAL_ALLOC_COUNT * ARRAY_SIZE; 135 for(int i = 0; i < MIN_GLOBAL_ALLOC_COUNT; i++){ 136 // for test alloc huge memory 137 TEST_ALLOC.add(new int[ARRAY_SIZE]); 138 TEST_ALLOC.clear(); 139 } 140 141 assertTrue(Debug.getGlobalAllocCount() >= MIN_GLOBAL_ALLOC_COUNT); 142 assertTrue(Debug.getGlobalAllocSize() >= MIN_GLOBAL_ALLOC_SIZE); 143 assertTrue(Debug.getGlobalFreedCount() >= 0); 144 assertTrue(Debug.getGlobalFreedSize() >= 0); 145 assertTrue(Debug.getNativeHeapSize() >= 0); 146 assertTrue(Debug.getGlobalExternalAllocCount() >= 0); 147 assertTrue(Debug.getGlobalExternalAllocSize() >= 0); 148 assertTrue(Debug.getGlobalExternalFreedCount() >= 0); 149 assertTrue(Debug.getGlobalExternalFreedSize() >= 0); 150 assertTrue(Debug.getLoadedClassCount() >= 0); 151 assertTrue(Debug.getNativeHeapAllocatedSize() >= 0); 152 assertTrue(Debug.getNativeHeapFreeSize() >= 0); 153 assertTrue(Debug.getNativeHeapSize() >= 0); 154 assertTrue(Debug.getThreadAllocCount() >= 0); 155 assertTrue(Debug.getThreadAllocSize() >= 0); 156 assertTrue(Debug.getThreadExternalAllocCount() >=0); 157 assertTrue(Debug.getThreadExternalAllocSize() >= 0); 158 assertTrue(Debug.getThreadGcInvocationCount() >= 0); 159 assertTrue(Debug.getBinderDeathObjectCount() >= 0); 160 assertTrue(Debug.getBinderLocalObjectCount() >= 0); 161 assertTrue(Debug.getBinderProxyObjectCount() >= 0); 162 Debug.getBinderReceivedTransactions(); 163 Debug.getBinderSentTransactions(); 164 165 Debug.stopAllocCounting(); 166 167 Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); 168 Debug.getMemoryInfo(memoryInfo); 169 170 Debug.resetGlobalAllocCount(); 171 assertEquals(0, Debug.getGlobalAllocCount()); 172 173 Debug.resetGlobalAllocSize(); 174 assertEquals(0, Debug.getGlobalAllocSize()); 175 176 Debug.resetGlobalExternalAllocCount(); 177 assertEquals(0, Debug.getGlobalExternalAllocCount()); 178 179 Debug.resetGlobalExternalAllocSize(); 180 assertEquals(0, Debug.getGlobalExternalAllocSize()); 181 182 Debug.resetGlobalExternalFreedCount(); 183 assertEquals(0, Debug.getGlobalExternalFreedCount()); 184 185 Debug.resetGlobalExternalFreedSize(); 186 assertEquals(0, Debug.getGlobalExternalFreedSize()); 187 188 Debug.resetGlobalFreedCount(); 189 assertEquals(0, Debug.getGlobalFreedCount()); 190 191 Debug.resetGlobalFreedSize(); 192 assertEquals(0, Debug.getGlobalFreedSize()); 193 194 Debug.resetGlobalGcInvocationCount(); 195 assertEquals(0, Debug.getGlobalGcInvocationCount()); 196 197 Debug.resetThreadAllocCount(); 198 assertEquals(0, Debug.getThreadAllocCount()); 199 200 Debug.resetThreadAllocSize(); 201 assertEquals(0, Debug.getThreadAllocSize()); 202 203 Debug.resetThreadExternalAllocCount(); 204 assertEquals(0, Debug.getThreadExternalAllocCount()); 205 206 Debug.resetThreadExternalAllocSize(); 207 assertEquals(0, Debug.getThreadExternalAllocSize()); 208 209 Debug.resetThreadGcInvocationCount(); 210 assertEquals(0, Debug.getThreadGcInvocationCount()); 211 212 Debug.resetAllCounts(); 213 Debug.dumpHprofData(dumpFile); 214 } 215 testDumpService()216 public void testDumpService() throws Exception { 217 File file = getContext().getFileStreamPath("dump.out"); 218 file.delete(); 219 assertFalse(file.exists()); 220 221 FileOutputStream out = getContext().openFileOutput("dump.out", Context.MODE_PRIVATE); 222 assertFalse(Debug.dumpService("xyzzy -- not a valid service name", out.getFD(), null)); 223 out.close(); 224 225 // File was opened, but nothing was written 226 assertTrue(file.exists()); 227 assertEquals(0, file.length()); 228 229 out = getContext().openFileOutput("dump.out", Context.MODE_PRIVATE); 230 assertTrue(Debug.dumpService(Context.POWER_SERVICE, out.getFD(), null)); 231 out.close(); 232 233 // Don't require any specific content, just that something was written 234 assertTrue(file.exists()); 235 assertTrue(file.length() > 0); 236 } 237 checkNumber(String s)238 private static void checkNumber(String s) throws Exception { 239 assertTrue(s != null); 240 long n = Long.valueOf(s); 241 assertTrue(n >= 0); 242 } 243 checkHistogram(String s)244 private static void checkHistogram(String s) throws Exception { 245 assertTrue(s != null); 246 assertTrue(s.length() > 0); 247 String[] buckets = s.split(","); 248 long last_key = 0; 249 for (int i = 0; i < buckets.length; ++i) { 250 String bucket = buckets[i]; 251 assertTrue(bucket.length() > 0); 252 String[] kv = bucket.split(":"); 253 assertTrue(kv.length == 2); 254 assertTrue(kv[0].length() > 0); 255 assertTrue(kv[1].length() > 0); 256 long key = Long.valueOf(kv[0]); 257 long value = Long.valueOf(kv[1]); 258 assertTrue(key >= 0); 259 assertTrue(value >= 0); 260 assertTrue(key >= last_key); 261 last_key = key; 262 } 263 } 264 testGetRuntimeStat()265 public void testGetRuntimeStat() throws Exception { 266 // Invoke at least one GC and wait for 20 seconds or so so we get at 267 // least one bucket in the histograms. 268 for (int i = 0; i < 20; ++i) { 269 Runtime.getRuntime().gc(); 270 Thread.sleep(1000L); 271 } 272 String gc_count = Debug.getRuntimeStat("art.gc.gc-count"); 273 String gc_time = Debug.getRuntimeStat("art.gc.gc-time"); 274 String bytes_allocated = Debug.getRuntimeStat("art.gc.bytes-allocated"); 275 String bytes_freed = Debug.getRuntimeStat("art.gc.bytes-freed"); 276 String blocking_gc_count = Debug.getRuntimeStat("art.gc.blocking-gc-count"); 277 String blocking_gc_time = Debug.getRuntimeStat("art.gc.blocking-gc-time"); 278 String gc_count_rate_histogram = Debug.getRuntimeStat("art.gc.gc-count-rate-histogram"); 279 String blocking_gc_count_rate_histogram = 280 Debug.getRuntimeStat("art.gc.blocking-gc-count-rate-histogram"); 281 checkNumber(gc_count); 282 checkNumber(gc_time); 283 checkNumber(bytes_allocated); 284 checkNumber(bytes_freed); 285 checkNumber(blocking_gc_count); 286 checkNumber(blocking_gc_time); 287 checkHistogram(gc_count_rate_histogram); 288 checkHistogram(blocking_gc_count_rate_histogram); 289 } 290 testGetRuntimeStats()291 public void testGetRuntimeStats() throws Exception { 292 // Invoke at least one GC and wait for 20 seconds or so so we get at 293 // least one bucket in the histograms. 294 for (int i = 0; i < 20; ++i) { 295 Runtime.getRuntime().gc(); 296 Thread.sleep(1000L); 297 } 298 Map<String, String> map = Debug.getRuntimeStats(); 299 String gc_count = map.get("art.gc.gc-count"); 300 String gc_time = map.get("art.gc.gc-time"); 301 String bytes_allocated = map.get("art.gc.bytes-allocated"); 302 String bytes_freed = map.get("art.gc.bytes-freed"); 303 String blocking_gc_count = map.get("art.gc.blocking-gc-count"); 304 String blocking_gc_time = map.get("art.gc.blocking-gc-time"); 305 String gc_count_rate_histogram = map.get("art.gc.gc-count-rate-histogram"); 306 String blocking_gc_count_rate_histogram = 307 map.get("art.gc.blocking-gc-count-rate-histogram"); 308 checkNumber(gc_count); 309 checkNumber(gc_time); 310 checkNumber(bytes_allocated); 311 checkNumber(bytes_freed); 312 checkNumber(blocking_gc_count); 313 checkNumber(blocking_gc_time); 314 checkHistogram(gc_count_rate_histogram); 315 checkHistogram(blocking_gc_count_rate_histogram); 316 } 317 testGetMemoryStat()318 public void testGetMemoryStat() throws Exception { 319 Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); 320 Debug.getMemoryInfo(memoryInfo); 321 322 String summary_java_heap = memoryInfo.getMemoryStat("summary.java-heap"); 323 String summary_native_heap = memoryInfo.getMemoryStat("summary.native-heap"); 324 String summary_code = memoryInfo.getMemoryStat("summary.code"); 325 String summary_stack = memoryInfo.getMemoryStat("summary.stack"); 326 String summary_graphics = memoryInfo.getMemoryStat("summary.graphics"); 327 String summary_private_other = memoryInfo.getMemoryStat("summary.private-other"); 328 String summary_system = memoryInfo.getMemoryStat("summary.system"); 329 String summary_total_pss = memoryInfo.getMemoryStat("summary.total-pss"); 330 String summary_total_swap = memoryInfo.getMemoryStat("summary.total-swap"); 331 checkNumber(summary_java_heap); 332 checkNumber(summary_native_heap); 333 checkNumber(summary_code); 334 checkNumber(summary_stack); 335 checkNumber(summary_graphics); 336 checkNumber(summary_private_other); 337 checkNumber(summary_system); 338 checkNumber(summary_total_pss); 339 checkNumber(summary_total_swap); 340 } 341 testGetMemoryStats()342 public void testGetMemoryStats() throws Exception { 343 Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); 344 Debug.getMemoryInfo(memoryInfo); 345 346 Map<String, String> map = memoryInfo.getMemoryStats(); 347 String summary_java_heap = map.get("summary.java-heap"); 348 String summary_native_heap = map.get("summary.native-heap"); 349 String summary_code = map.get("summary.code"); 350 String summary_stack = map.get("summary.stack"); 351 String summary_graphics = map.get("summary.graphics"); 352 String summary_private_other = map.get("summary.private-other"); 353 String summary_system = map.get("summary.system"); 354 String summary_total_pss = map.get("summary.total-pss"); 355 String summary_total_swap = map.get("summary.total-swap"); 356 checkNumber(summary_java_heap); 357 checkNumber(summary_native_heap); 358 checkNumber(summary_code); 359 checkNumber(summary_stack); 360 checkNumber(summary_graphics); 361 checkNumber(summary_private_other); 362 checkNumber(summary_system); 363 checkNumber(summary_total_pss); 364 checkNumber(summary_total_swap); 365 } 366 } 367