1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.launcher3.tapl; 18 19 import static androidx.test.InstrumentationRegistry.getInstrumentation; 20 import static androidx.test.InstrumentationRegistry.getTargetContext; 21 22 import android.app.Instrumentation; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.ActivityInfo; 27 import android.content.pm.ResolveInfo; 28 import android.content.res.Resources; 29 import android.os.DropBoxManager; 30 31 import org.junit.Assert; 32 33 import java.util.Date; 34 import java.util.List; 35 36 public class TestHelpers { 37 38 private static Boolean sIsInLauncherProcess; 39 isInLauncherProcess()40 public static boolean isInLauncherProcess() { 41 if (sIsInLauncherProcess == null) { 42 sIsInLauncherProcess = initIsInLauncherProcess(); 43 } 44 return sIsInLauncherProcess; 45 } 46 initIsInLauncherProcess()47 private static boolean initIsInLauncherProcess() { 48 ActivityInfo info = getLauncherInMyProcess(); 49 50 // If we are in the same process, we can instantiate the class name. 51 try { 52 Class launcherClazz = Class.forName("com.android.launcher3.Launcher"); 53 return launcherClazz.isAssignableFrom(Class.forName(info.name)); 54 } catch (Exception e) { 55 return false; 56 } 57 } 58 getHomeIntentInPackage(Context context)59 public static Intent getHomeIntentInPackage(Context context) { 60 return new Intent(Intent.ACTION_MAIN) 61 .addCategory(Intent.CATEGORY_HOME) 62 .setPackage(context.getPackageName()) 63 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 64 } 65 getLauncherInMyProcess()66 public static ActivityInfo getLauncherInMyProcess() { 67 Instrumentation instrumentation = getInstrumentation(); 68 if (instrumentation.getTargetContext() == null) { 69 return null; 70 } 71 72 List<ResolveInfo> launchers = getTargetContext().getPackageManager() 73 .queryIntentActivities(getHomeIntentInPackage(getTargetContext()), 0); 74 if (launchers.size() != 1) { 75 return null; 76 } 77 return launchers.get(0).activityInfo; 78 } 79 getOverviewPackageName()80 public static String getOverviewPackageName() { 81 Resources res = Resources.getSystem(); 82 int id = res.getIdentifier("config_recentsComponentName", "string", "android"); 83 if (id != 0) { 84 return ComponentName.unflattenFromString(res.getString(id)).getPackageName(); 85 } 86 return "com.android.systemui"; 87 } 88 truncateCrash(String text, int maxLines)89 private static String truncateCrash(String text, int maxLines) { 90 String[] lines = text.split("\\r?\\n"); 91 StringBuilder ret = new StringBuilder(); 92 for (int i = 0; i < maxLines && i < lines.length; i++) { 93 ret.append(lines[i]); 94 ret.append('\n'); 95 } 96 if (lines.length > maxLines) { 97 ret.append("... "); 98 ret.append(lines.length - maxLines); 99 ret.append(" more lines truncated ...\n"); 100 } 101 return ret.toString(); 102 } 103 checkCrash(Context context, String label, long startTime)104 private static String checkCrash(Context context, String label, long startTime) { 105 DropBoxManager dropbox = (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE); 106 Assert.assertNotNull("Unable access the DropBoxManager service", dropbox); 107 108 long timestamp = startTime; 109 DropBoxManager.Entry entry; 110 StringBuilder errorDetails = new StringBuilder(); 111 while (null != (entry = dropbox.getNextEntry(label, timestamp))) { 112 errorDetails.append("------------------------------\n"); 113 timestamp = entry.getTimeMillis(); 114 errorDetails.append(new Date(timestamp)); 115 errorDetails.append(": "); 116 errorDetails.append(entry.getTag()); 117 errorDetails.append(": "); 118 final String dropboxSnippet = entry.getText(4096); 119 if (dropboxSnippet != null) errorDetails.append(truncateCrash(dropboxSnippet, 40)); 120 errorDetails.append(" ...\n"); 121 entry.close(); 122 } 123 return errorDetails.length() != 0 ? errorDetails.toString() : null; 124 } 125 getSystemHealthMessage(Context context, long startTime)126 public static String getSystemHealthMessage(Context context, long startTime) { 127 try { 128 StringBuilder errors = new StringBuilder(); 129 130 final String[] labels = { 131 "system_app_anr", 132 "system_app_crash", 133 "system_app_native_crash", 134 "system_server_anr", 135 "system_server_crash", 136 "system_server_native_crash", 137 "system_server_watchdog", 138 }; 139 140 for (String label : labels) { 141 final String crash = checkCrash(context, label, startTime); 142 if (crash != null) errors.append(crash); 143 } 144 145 return errors.length() != 0 146 ? "Current time: " + new Date(System.currentTimeMillis()) + "\n" + errors 147 : null; 148 } catch (Exception e) { 149 return "Failed to get system health diags, maybe build your test via .bp instead of " 150 + ".mk? " + android.util.Log.getStackTraceString(e); 151 } 152 } 153 } 154