1cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/* 2cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 4cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * you may not use this file except in compliance with the License. 6cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * You may obtain a copy of the License at 7cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 8cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 10cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Unless required by applicable law or agreed to in writing, software 11cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * See the License for the specific language governing permissions and 14cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * limitations under the License. 15cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 16cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 17cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpackage com.android.internal.util; 18cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 190b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onukiimport android.annotation.Nullable; 20fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport android.app.AppOpsManager; 210b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onukiimport android.content.ComponentName; 22fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport android.content.Context; 23fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport android.content.pm.PackageManager; 24fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport android.os.Binder; 25cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 260b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onukiimport android.text.TextUtils; 27fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport android.util.Slog; 28cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 29cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 30cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.StringWriter; 310b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onukiimport java.util.Objects; 320b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onukiimport java.util.function.Predicate; 33cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Helper functions for dumping the state of system services. 360b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Test: 370b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpublic final class DumpUtils { 40fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey private static final String TAG = "DumpUtils"; 4182ba91ddb4fe9d9ff8245e27f70dea64cc20553dJoe Onorato private static final boolean DEBUG = false; 42fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DumpUtils() { 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Helper for dumping state owned by a handler thread. 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Because the caller might be holding an important lock that the handler is 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * trying to acquire, we use a short timeout to avoid deadlocks. The process 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * is inelegant but this function is only used for debugging purposes. 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 53ae6688b09649447e57468b3e7935691bc09ec9b9Dianne Hackborn public static void dumpAsync(Handler handler, final Dump dump, PrintWriter pw, 54ae6688b09649447e57468b3e7935691bc09ec9b9Dianne Hackborn final String prefix, long timeout) { 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final StringWriter sw = new StringWriter(); 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (handler.runWithScissors(new Runnable() { 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 598c84109b9fbbf473b225707a38261ff5f99d95fbDianne Hackborn PrintWriter lpw = new FastPrintWriter(sw); 60ae6688b09649447e57468b3e7935691bc09ec9b9Dianne Hackborn dump.dump(lpw, prefix); 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown lpw.close(); 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }, timeout)) { 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.print(sw.toString()); 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("... timed out"); 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public interface Dump { 71ae6688b09649447e57468b3e7935691bc09ec9b9Dianne Hackborn void dump(PrintWriter pw, String prefix); 72cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 73fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 74fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey private static void logMessage(PrintWriter pw, String msg) { 75fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (DEBUG) Slog.v(TAG, msg); 76fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey pw.println(msg); 77fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 78fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 79fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey /** 80fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * Verify that caller holds {@link android.Manifest.permission#DUMP}. 81fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * 82fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * @return true if access should be granted. 83fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * @hide 84fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey */ 85fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { 86fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 87fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey != PackageManager.PERMISSION_GRANTED) { 88fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid=" 89fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 90fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey + " due to missing android.permission.DUMP permission"); 91fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey return false; 92fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } else { 93fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey return true; 94fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 95fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 96fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 97fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey /** 98fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * Verify that caller holds 99fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * {@link android.Manifest.permission#PACKAGE_USAGE_STATS} and that they 100fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * have {@link AppOpsManager#OP_GET_USAGE_STATS} access. 101fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * 102fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * @return true if access should be granted. 103fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * @hide 104fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey */ 105fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey public static boolean checkUsageStatsPermission(Context context, String tag, PrintWriter pw) { 106fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey // System internals always get access 107fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey final int uid = Binder.getCallingUid(); 108fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey switch (uid) { 109fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey case android.os.Process.ROOT_UID: 110fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey case android.os.Process.SYSTEM_UID: 111fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey case android.os.Process.SHELL_UID: 1124bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin case android.os.Process.INCIDENTD_UID: 113fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey return true; 114fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 115fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 116fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey // Caller always needs to hold permission 117fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) 118fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey != PackageManager.PERMISSION_GRANTED) { 119fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid=" 120fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 121fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey + " due to missing android.permission.PACKAGE_USAGE_STATS permission"); 122fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey return false; 123fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 124fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 125fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey // And finally, caller needs to have appops access; this is totally 126fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey // hacky, but it's the easiest way to wire this up without retrofitting 127fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey // Binder.dump() to pass through package names. 128fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey final AppOpsManager appOps = context.getSystemService(AppOpsManager.class); 129fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey final String[] pkgs = context.getPackageManager().getPackagesForUid(uid); 130fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (pkgs != null) { 131fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey for (String pkg : pkgs) { 132d9311198e18f19ad06ef2ed5e4a400c0fc30e83eJeff Sharkey switch (appOps.noteOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg)) { 133e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey case AppOpsManager.MODE_ALLOWED: 134e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with " 135e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey + "android:get_usage_stats allowed"); 136e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey return true; 137e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey case AppOpsManager.MODE_DEFAULT: 138e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with " 139e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey + "android:get_usage_stats default"); 140e5e2569a1f0af3dd8cc245aada168f7969c3a5d9Jeff Sharkey return true; 141fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 142fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 143fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 144fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 145fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid=" 146fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 147fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey + " due to android:get_usage_stats app-op not allowed"); 148fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey return false; 149fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 150fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 151fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey /** 152fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * Verify that caller holds both {@link android.Manifest.permission#DUMP} 153fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * and {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, and that 154fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * they have {@link AppOpsManager#OP_GET_USAGE_STATS} access. 155fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * 156fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * @return true if access should be granted. 157fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey * @hide 158fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey */ 159fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey public static boolean checkDumpAndUsageStatsPermission(Context context, String tag, 160fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey PrintWriter pw) { 161fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey return checkDumpPermission(context, tag, pw) && checkUsageStatsPermission(context, tag, pw); 162fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey } 1630b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 1640b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 1650b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Return whether a package name is considered to be part of the platform. 1660b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 1670b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 1680b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static boolean isPlatformPackage(@Nullable String packageName) { 1690b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return (packageName != null) 1700b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki && (packageName.equals("android") 1710b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki || packageName.startsWith("android.") 1720b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki || packageName.startsWith("com.android.")); 1730b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 1740b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 1750b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 1760b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Return whether a package name is considered to be part of the platform. 1770b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 1780b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 1790b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static boolean isPlatformPackage(@Nullable ComponentName cname) { 1800b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return (cname != null) && isPlatformPackage(cname.getPackageName()); 1810b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 1820b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 1830b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 1840b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Return whether a package name is considered to be part of the platform. 1850b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 1860b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 1870b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static boolean isPlatformPackage(@Nullable ComponentName.WithComponentName wcn) { 1880b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return (wcn != null) && isPlatformPackage(wcn.getComponentName()); 1890b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 1900b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 1910b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 1920b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Return whether a package name is NOT considered to be part of the platform. 1930b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 1940b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 1950b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static boolean isNonPlatformPackage(@Nullable String packageName) { 1960b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return (packageName != null) && !isPlatformPackage(packageName); 1970b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 1980b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 1990b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 2000b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Return whether a package name is NOT considered to be part of the platform. 2010b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 2020b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 2030b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static boolean isNonPlatformPackage(@Nullable ComponentName cname) { 2040b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return (cname != null) && isNonPlatformPackage(cname.getPackageName()); 2050b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2060b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2070b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 2080b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Return whether a package name is NOT considered to be part of the platform. 2090b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 2100b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 2110b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static boolean isNonPlatformPackage(@Nullable ComponentName.WithComponentName wcn) { 2120b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return (wcn != null) && !isPlatformPackage(wcn.getComponentName()); 2130b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2140b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2150b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki /** 2160b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * Used for dumping providers and services. Return a predicate for a given filter string. 2170b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki * @hide 2180b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki */ 2190b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki public static <TRec extends ComponentName.WithComponentName> Predicate<TRec> filterRecord( 2200b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki @Nullable String filterString) { 2210b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2220b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki if (TextUtils.isEmpty(filterString)) { 2230b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return rec -> false; 2240b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2250b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2260b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Dump all? 2270b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki if ("all".equals(filterString)) { 2280b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return Objects::nonNull; 2290b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2300b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2310b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Dump all platform? 2320b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki if ("all-platform".equals(filterString)) { 2330b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return DumpUtils::isPlatformPackage; 2340b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2350b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2360b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Dump all non-platform? 2370b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki if ("all-non-platform".equals(filterString)) { 2380b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return DumpUtils::isNonPlatformPackage; 2390b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2400b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2410b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Is the filter a component name? If so, do an exact match. 2420b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki final ComponentName filterCname = ComponentName.unflattenFromString(filterString); 2430b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki if (filterCname != null) { 2440b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Do exact component name check. 2450b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return rec -> (rec != null) && filterCname.equals(rec.getComponentName()); 2460b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 2470b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 2480b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Otherwise, do a partial match against the component name. 2490b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki // Also if the filter is a hex-decimal string, do the object ID match too. 2500b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki final int id = ParseUtils.parseIntWithBase(filterString, 16, -1); 2510b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return rec -> { 2520b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki final ComponentName cn = rec.getComponentName(); 2530b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki return ((id != -1) && (System.identityHashCode(rec) == id)) 2540b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki || cn.flattenToString().toLowerCase().contains(filterString.toLowerCase()); 2550b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki }; 2560b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki } 257cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 2580b575a3cdfce8cd5394044c4c6a7092487ba93cbMakoto Onuki 259