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