diff options
20 files changed, 410 insertions, 179 deletions
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml index f27e8c82a303..48899410c07c 100644 --- a/apct-tests/perftests/core/AndroidManifest.xml +++ b/apct-tests/perftests/core/AndroidManifest.xml @@ -2,6 +2,9 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.perftests.core"> + <uses-permission + android:name="android.permission.GET_ACCOUNTS" /> + <application> <uses-library android:name="android.test.runner" /> <activity android:name="android.perftests.utils.StubActivity" /> diff --git a/apct-tests/perftests/core/src/android/accounts/AccountManagerPerfTest.java b/apct-tests/perftests/core/src/android/accounts/AccountManagerPerfTest.java new file mode 100644 index 000000000000..b9411fa463d5 --- /dev/null +++ b/apct-tests/perftests/core/src/android/accounts/AccountManagerPerfTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.accounts; + +import static junit.framework.Assert.fail; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; +import android.util.Log; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class AccountManagerPerfTest { + + @Rule + public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void testGetAccounts() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final Context context = InstrumentationRegistry.getTargetContext(); + if (context.checkSelfPermission(Manifest.permission.GET_ACCOUNTS) + != PackageManager.PERMISSION_GRANTED) { + fail("Missing required GET_ACCOUNTS permission"); + } + AccountManager accountManager = AccountManager.get(context); + while (state.keepRunning()) { + accountManager.getAccounts(); + } + } +} diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 68f48a4f4c37..56d4e4d940c2 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -35,7 +35,7 @@ namespace statsd { StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap, const std::function<void(const vector<uint8_t>&)>& pushLog) - : m_dropbox_writer("all-logs"), mUidMap(uidMap), mPushLog(pushLog) { + : mUidMap(uidMap), mPushLog(pushLog) { } StatsLogProcessor::~StatsLogProcessor() { @@ -43,12 +43,6 @@ StatsLogProcessor::~StatsLogProcessor() { // TODO: what if statsd service restarts? How do we know what logs are already processed before? void StatsLogProcessor::OnLogEvent(const LogEvent& msg) { - // TODO: Use EventMetric to filter the events we want to log. - /* TODO: Convert this when we have the generic protobuf writing library in. - EventMetricData eventMetricData = parse(msg); - m_dropbox_writer.addEventMetricData(eventMetricData); - */ - // pass the event to metrics managers. for (auto& pair : mMetricsManagers) { pair.second->onLogEvent(msg); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 08090c11f724..9cd74caf095e 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -20,7 +20,6 @@ #include "logd/LogReader.h" #include "metrics/MetricsManager.h" #include "packages/UidMap.h" -#include "storage/DropboxWriter.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" @@ -49,9 +48,6 @@ public: void flush(); private: - // TODO: use EventMetrics to log the events. - DropboxWriter m_dropbox_writer; - std::unordered_map<ConfigKey, std::unique_ptr<MetricsManager>> mMetricsManagers; sp<UidMap> mUidMap; // Reference to the UidMap to lookup app name and version for each uid. @@ -75,7 +71,7 @@ private: size_t mBufferSize = 0; /* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush - the logs to dropbox if true. */ + the logs to callback clients if true. */ void flushIfNecessary(const EventMetricData& eventMetricData); /* Append event metric data to StatsLogReport. */ diff --git a/core/java/android/os/IServiceManager.java b/core/java/android/os/IServiceManager.java index 87c65ecc540b..2176a785e0a2 100644 --- a/core/java/android/os/IServiceManager.java +++ b/core/java/android/os/IServiceManager.java @@ -45,13 +45,13 @@ public interface IServiceManager extends IInterface * Place a new @a service called @a name into the service * manager. */ - void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) - throws RemoteException; + void addService(String name, IBinder service, boolean allowIsolated, int dumpFlags) + throws RemoteException; /** * Return a list of all currently running services. */ - String[] listServices(int dumpPriority) throws RemoteException; + String[] listServices(int dumpFlags) throws RemoteException; /** * Assign a permission controller to the service manager. After set, this @@ -72,9 +72,13 @@ public interface IServiceManager extends IInterface /* * Must update values in IServiceManager.h */ - int DUMP_PRIORITY_CRITICAL = 1 << 0; - int DUMP_PRIORITY_HIGH = 1 << 1; - int DUMP_PRIORITY_NORMAL = 1 << 2; - int DUMP_PRIORITY_ALL = DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_HIGH - | DUMP_PRIORITY_NORMAL; + /* Allows services to dump sections according to priorities. */ + int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0; + int DUMP_FLAG_PRIORITY_HIGH = 1 << 1; + int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2; + int DUMP_FLAG_PRIORITY_ALL = DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH + | DUMP_FLAG_PRIORITY_NORMAL; + /* Allows services to dump sections in protobuf format. */ + int DUMP_FLAG_PROTO = 1 << 3; + } diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index f41848fad74a..42ec315c10e0 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -83,7 +83,7 @@ public final class ServiceManager { * @param service the service object */ public static void addService(String name, IBinder service) { - addService(name, service, false, IServiceManager.DUMP_PRIORITY_NORMAL); + addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_NORMAL); } /** @@ -96,7 +96,7 @@ public final class ServiceManager { * to access this service */ public static void addService(String name, IBinder service, boolean allowIsolated) { - addService(name, service, allowIsolated, IServiceManager.DUMP_PRIORITY_NORMAL); + addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_NORMAL); } /** @@ -143,7 +143,7 @@ public final class ServiceManager { */ public static String[] listServices() { try { - return getIServiceManager().listServices(IServiceManager.DUMP_PRIORITY_ALL); + return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL); } catch (RemoteException e) { Log.e(TAG, "error in listServices", e); return null; diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index f716ffee53af..50e811d79845 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -20,24 +20,24 @@ option java_outer_classname = "IncidentProtoMetadata"; import "frameworks/base/libs/incident/proto/android/privacy.proto"; import "frameworks/base/libs/incident/proto/android/section.proto"; +import "frameworks/base/core/proto/android/providers/settings.proto"; +import "frameworks/base/core/proto/android/os/incidentheader.proto"; +import "frameworks/base/core/proto/android/os/kernelwake.proto"; +import "frameworks/base/core/proto/android/os/pagetypeinfo.proto"; +import "frameworks/base/core/proto/android/os/procrank.proto"; +import "frameworks/base/core/proto/android/server/activitymanagerservice.proto"; +import "frameworks/base/core/proto/android/server/alarmmanagerservice.proto"; +import "frameworks/base/core/proto/android/server/fingerprint.proto"; import "frameworks/base/core/proto/android/server/powermanagerservice.proto"; import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/battery.proto"; import "frameworks/base/core/proto/android/service/batterystats.proto"; -import "frameworks/base/core/proto/android/service/fingerprint.proto"; import "frameworks/base/core/proto/android/service/diskstats.proto"; import "frameworks/base/core/proto/android/service/netstats.proto"; import "frameworks/base/core/proto/android/service/notification.proto"; import "frameworks/base/core/proto/android/service/package.proto"; import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/service/procstats.proto"; -import "frameworks/base/core/proto/android/server/activitymanagerservice.proto"; -import "frameworks/base/core/proto/android/server/alarmmanagerservice.proto"; -import "frameworks/base/core/proto/android/providers/settings.proto"; -import "frameworks/base/core/proto/android/os/incidentheader.proto"; -import "frameworks/base/core/proto/android/os/kernelwake.proto"; -import "frameworks/base/core/proto/android/os/pagetypeinfo.proto"; -import "frameworks/base/core/proto/android/os/procrank.proto"; package android.os; @@ -69,7 +69,7 @@ message IncidentProto { // System Services - optional android.service.fingerprint.FingerprintServiceDumpProto fingerprint = 3000 [ + optional com.android.server.fingerprint.FingerprintServiceDumpProto fingerprint = 3000 [ (section).type = SECTION_DUMPSYS, (section).args = "fingerprint --proto --incident" ]; diff --git a/core/proto/android/service/fingerprint.proto b/core/proto/android/server/fingerprint.proto index 0826ad5cb31e..ec4ffe0ae4e1 100644 --- a/core/proto/android/service/fingerprint.proto +++ b/core/proto/android/server/fingerprint.proto @@ -15,7 +15,7 @@ */ syntax = "proto2"; -package android.service.fingerprint; +package com.android.server.fingerprint; option java_multiple_files = true; option java_outer_classname = "FingerprintServiceProto"; @@ -33,14 +33,15 @@ message FingerprintUserStatsProto { optional int32 num_fingerprints = 2; // Normal fingerprint authentications (e.g. lockscreen). - optional FingerprintActionStatsProto normal = 3; + optional PerformanceStatsProto normal = 3; // Crypto authentications (e.g. to unlock password storage, make secure // purchases, etc). - optional FingerprintActionStatsProto crypto = 4; + optional PerformanceStatsProto crypto = 4; } -message FingerprintActionStatsProto { +// A com.android.server.fingerprint.FingerpintService.PerformanceStats object. +message PerformanceStatsProto { // Number of accepted fingerprints. optional int32 accept = 1; @@ -55,5 +56,5 @@ message FingerprintActionStatsProto { optional int32 lockout = 4; // Total number of permanent lockouts. - optional int32 lockout_permanent = 5; + optional int32 permanent_lockout = 5; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e5f3aafd00d0..49d251aaaac5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2073,6 +2073,9 @@ <!-- Maximum number of supported users --> <integer name="config_multiuserMaximumUsers">1</integer> + <!-- Maximum number of users we allow to be running at a time --> + <integer name="config_multiuserMaxRunningUsers">3</integer> + <!-- Whether UI for multi user should be shown --> <bool name="config_enableMultiUserUI">false</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 3dff9d789a17..467d61e24d7c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -445,6 +445,7 @@ <java-symbol type="integer" name="config_soundEffectVolumeDb" /> <java-symbol type="integer" name="config_lockSoundVolumeDb" /> <java-symbol type="integer" name="config_multiuserMaximumUsers" /> + <java-symbol type="integer" name="config_multiuserMaxRunningUsers" /> <java-symbol type="integer" name="config_safe_media_volume_index" /> <java-symbol type="integer" name="config_mobile_mtu" /> <java-symbol type="array" name="config_mobile_tcp_buffers" /> diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index 35ba6ae975d8..038dcf8469cf 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -65,7 +65,7 @@ public class TileUtils { * * <p>A summary my be defined by meta-data named {@link #META_DATA_PREFERENCE_SUMMARY} */ - private static final String EXTRA_SETTINGS_ACTION = + public static final String EXTRA_SETTINGS_ACTION = "com.android.settings.action.EXTRA_SETTINGS"; /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d819a33d9207..7e65d36024e3 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -143,6 +143,7 @@ import com.android.server.connectivity.tethering.TetheringDependencies; import com.android.server.net.BaseNetworkObserver; import com.android.server.net.LockdownVpnTracker; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.utils.PriorityDump; import com.google.android.collect.Lists; @@ -682,6 +683,28 @@ public class ConnectivityService extends IConnectivityManager.Stub } private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(); + /** + * Helper class which parses out priority arguments and dumps sections according to their + * priority. If priority arguments are omitted, function calls the legacy dump command. + */ + private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { + @Override + public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + doDump(fd, pw, new String[] {DIAG_ARG}, asProto); + doDump(fd, pw, new String[] {SHORT_ARG}, asProto); + } + + @Override + public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + doDump(fd, pw, args, asProto); + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + doDump(fd, pw, args, asProto); + } + }; + public ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager) { this(context, netManager, statsService, policyManager, new IpConnectivityLog()); @@ -1862,8 +1885,13 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + PriorityDump.dump(mPriorityDumper, fd, writer, args); + } + + private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + if (asProto) return; if (argsContain(args, DIAG_ARG)) { dumpNetworkDiagnostics(pw); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 93c0a395de7a..5b51b854aac2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -53,9 +53,10 @@ import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground; import static android.os.Build.VERSION_CODES.N; -import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL; -import static android.os.IServiceManager.DUMP_PRIORITY_HIGH; -import static android.os.IServiceManager.DUMP_PRIORITY_NORMAL; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; +import static android.os.IServiceManager.DUMP_FLAG_PROTO; import static android.os.Process.BLUETOOTH_UID; import static android.os.Process.FIRST_APPLICATION_UID; import static android.os.Process.FIRST_ISOLATED_UID; @@ -722,30 +723,36 @@ public class ActivityManagerService extends IActivityManager.Stub */ private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { @Override - public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { - doDump(fd, pw, new String[] {"activities"}); + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, + boolean asProto) { + if (asProto) return; + doDump(fd, pw, new String[]{"activities"}, asProto); } @Override - public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { - doDump(fd, pw, new String[] {"settings"}); - doDump(fd, pw, new String[] {"intents"}); - doDump(fd, pw, new String[] {"broadcasts"}); - doDump(fd, pw, new String[] {"providers"}); - doDump(fd, pw, new String[] {"permissions"}); - doDump(fd, pw, new String[] {"services"}); - doDump(fd, pw, new String[] {"recents"}); - doDump(fd, pw, new String[] {"lastanr"}); - doDump(fd, pw, new String[] {"starter"}); - if (mAssociations.size() > 0) { - doDump(fd, pw, new String[] {"associations"}); - } - doDump(fd, pw, new String[] {"processes"}); + public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + if (asProto) { + doDump(fd, pw, new String[0], asProto); + } else { + doDump(fd, pw, new String[]{"settings"}, asProto); + doDump(fd, pw, new String[]{"intents"}, asProto); + doDump(fd, pw, new String[]{"broadcasts"}, asProto); + doDump(fd, pw, new String[]{"providers"}, asProto); + doDump(fd, pw, new String[]{"permissions"}, asProto); + doDump(fd, pw, new String[]{"services"}, asProto); + doDump(fd, pw, new String[]{"recents"}, asProto); + doDump(fd, pw, new String[]{"lastanr"}, asProto); + doDump(fd, pw, new String[]{"starter"}, asProto); + if (mAssociations.size() > 0) { + doDump(fd, pw, new String[]{"associations"}, asProto); + } + doDump(fd, pw, new String[]{"processes"}, asProto); + } } @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - doDump(fd, pw, args); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + doDump(fd, pw, args, asProto); } }; @@ -2493,15 +2500,15 @@ public class ActivityManagerService extends IActivityManager.Stub public void setSystemProcess() { try { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true, - DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_NORMAL); + DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats); ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false, - DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL); + DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); ServiceManager.addService("gfxinfo", new GraphicsBinder(this)); ServiceManager.addService("dbinfo", new DbBinder(this)); if (MONITOR_CPU_USAGE) { ServiceManager.addService("cpuinfo", new CpuBinder(this), - /* allowIsolated= */ false, DUMP_PRIORITY_CRITICAL); + /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); } ServiceManager.addService("permission", new PermissionController(this)); ServiceManager.addService("processinfo", new ProcessInfoService(this)); @@ -2554,7 +2561,9 @@ public class ActivityManagerService extends IActivityManager.Stub private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { @Override - public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, + boolean asProto) { + if (asProto) return; mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null); } }; @@ -2604,7 +2613,9 @@ public class ActivityManagerService extends IActivityManager.Stub private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { @Override - public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, + boolean asProto) { + if (asProto) return; if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext, "cpuinfo", pw)) return; synchronized (mActivityManagerService.mProcessCpuTracker) { @@ -13933,6 +13944,9 @@ public class ActivityManagerService extends IActivityManager.Stub com.android.internal.R.string.config_appsNotReportingCrashes)); mUserController.mUserSwitchUiEnabled = !res.getBoolean( com.android.internal.R.bool.config_customUserSwitchUi); + mUserController.mMaxRunningUsers = res.getInteger( + com.android.internal.R.integer.config_multiuserMaxRunningUsers); + if ((globalConfig.uiMode & UI_MODE_TYPE_TELEVISION) == UI_MODE_TYPE_TELEVISION) { mFullscreenThumbnailScale = (float) res .getInteger(com.android.internal.R.integer.thumbnail_width_tv) / @@ -14847,7 +14861,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Wrapper function to print out debug data filtered by specified arguments. */ - private void doDump(FileDescriptor fd, PrintWriter pw, String[] args) { + private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; boolean dumpAll = false; @@ -14856,7 +14870,6 @@ public class ActivityManagerService extends IActivityManager.Stub boolean dumpCheckinFormat = false; boolean dumpVisibleStacksOnly = false; boolean dumpFocusedStackOnly = false; - boolean useProto = false; String dumpPackage = null; int opti = 0; @@ -14890,8 +14903,6 @@ public class ActivityManagerService extends IActivityManager.Stub } else if ("-h".equals(opt)) { ActivityManagerShellCommand.dumpHelp(pw, true); return; - } else if ("--proto".equals(opt)) { - useProto = true; } else { pw.println("Unknown argument: " + opt + "; use -h for help"); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 1b42818a14ad..44f83b0e08fb 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -117,20 +117,6 @@ import java.util.concurrent.atomic.AtomicInteger; class UserController implements Handler.Callback { private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; - /** - * Maximum number of users we allow to be running at a time, including the system user and - * its profiles. - * Note changing this to 2 is not recommended, since that would mean, if the user uses - * work profile and then switch to a secondary user, then the work profile user would be killed, - * which should work fine, but aggressively killing the work profile user that has just been - * running could cause data loss. (Even without work profile, witching from secondary user A - * to secondary user B would cause similar issues on user B.) - * - * TODO: Consider adding or replacing with "MAX_RUNNING_*SECONDARY*_USERS", which is the max - * number of running *secondary, switchable* users. - */ - static final int MAX_RUNNING_USERS = 3; - // Amount of time we wait for observers to handle a user switch before // giving up on them and unfreezing the screen. static final int USER_SWITCH_TIMEOUT_MS = 3 * 1000; @@ -157,6 +143,17 @@ class UserController implements Handler.Callback { // when it never calls back. private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000; + /** + * Maximum number of users we allow to be running at a time, including system user. + * + * <p>This parameter only affects how many background users will be stopped when switching to a + * new user. It has no impact on {@link #startUser(int, boolean)} behavior. + * + * <p>Note: Current and system user (and their related profiles) are never stopped when + * switching users. Due to that, the actual number of running users can exceed mMaxRunningUsers + */ + int mMaxRunningUsers; + // Lock for internal state. private final Object mLock = new Object(); @@ -245,7 +242,7 @@ class UserController implements Handler.Callback { finishUserBoot(uss); startProfiles(); synchronized (mLock) { - stopRunningUsersLU(MAX_RUNNING_USERS); + stopRunningUsersLU(mMaxRunningUsers); } } @@ -813,7 +810,7 @@ class UserController implements Handler.Callback { } final int profilesToStartSize = profilesToStart.size(); int i = 0; - for (; i < profilesToStartSize && i < (MAX_RUNNING_USERS - 1); ++i) { + for (; i < profilesToStartSize && i < (mMaxRunningUsers - 1); ++i) { startUser(profilesToStart.get(i).id, /* foreground= */ false); } if (i < profilesToStartSize) { diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 1df9c861a666..d0d951b85b40 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -59,9 +59,6 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.security.KeyStore; -import android.service.fingerprint.FingerprintActionStatsProto; -import android.service.fingerprint.FingerprintServiceDumpProto; -import android.service.fingerprint.FingerprintUserStatsProto; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; @@ -1374,11 +1371,11 @@ public class FingerprintService extends SystemService implements IHwBinder.Death final PerformanceStats normal = mPerformanceMap.get(userId); if (normal != null) { final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL); - proto.write(FingerprintActionStatsProto.ACCEPT, normal.accept); - proto.write(FingerprintActionStatsProto.REJECT, normal.reject); - proto.write(FingerprintActionStatsProto.ACQUIRE, normal.acquire); - proto.write(FingerprintActionStatsProto.LOCKOUT, normal.lockout); - proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.permanentLockout); + proto.write(PerformanceStatsProto.ACCEPT, normal.accept); + proto.write(PerformanceStatsProto.REJECT, normal.reject); + proto.write(PerformanceStatsProto.ACQUIRE, normal.acquire); + proto.write(PerformanceStatsProto.LOCKOUT, normal.lockout); + proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, normal.permanentLockout); proto.end(countsToken); } @@ -1387,11 +1384,11 @@ public class FingerprintService extends SystemService implements IHwBinder.Death final PerformanceStats crypto = mCryptoPerformanceMap.get(userId); if (crypto != null) { final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO); - proto.write(FingerprintActionStatsProto.ACCEPT, crypto.accept); - proto.write(FingerprintActionStatsProto.REJECT, crypto.reject); - proto.write(FingerprintActionStatsProto.ACQUIRE, crypto.acquire); - proto.write(FingerprintActionStatsProto.LOCKOUT, crypto.lockout); - proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.permanentLockout); + proto.write(PerformanceStatsProto.ACCEPT, crypto.accept); + proto.write(PerformanceStatsProto.REJECT, crypto.reject); + proto.write(PerformanceStatsProto.ACQUIRE, crypto.acquire); + proto.write(PerformanceStatsProto.LOCKOUT, crypto.lockout); + proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, crypto.permanentLockout); proto.end(countsToken); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 9e4940908bda..76805ce3a9ff 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -288,19 +288,16 @@ public class PermissionManagerService { final String[] packages = mContext.getPackageManager().getPackagesForUid(uid); if (packages != null && packages.length > 0) { -Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages)); PackageParser.Package pkg = null; for (String packageName : packages) { pkg = mPackageManagerInt.getPackage(packageName); if (pkg != null) { -Slog.e(TAG, "TODD: Using packge: " + packageName); break; - } else { -Slog.e(TAG, "TODD: Missing packge: " + packageName); } } if (pkg == null) { Slog.e(TAG, "TODD: No package not found; UID: " + uid); +Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages)); return PackageManager.PERMISSION_DENIED; } if (pkg.mSharedUserId != null) { @@ -1010,8 +1007,6 @@ Slog.e(TAG, "TODD: No package not found; UID: " + uid); if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged() && !platformPackage && platformPermission) { if (!hasPrivappWhitelistEntry(perm, pkg)) { - Slog.w(TAG, "Privileged permission " + perm + " for package " - + pkg.packageName + " - not in privapp-permissions whitelist"); // Only report violations for apps on system image if (!mSystemReady && !pkg.isUpdatedSystemApp()) { // it's only a reportable violation if the permission isn't explicitly denied @@ -1019,12 +1014,16 @@ Slog.e(TAG, "TODD: No package not found; UID: " + uid); .getPrivAppDenyPermissions(pkg.packageName); final boolean permissionViolation = deniedPermissions == null || !deniedPermissions.contains(perm); - if (permissionViolation - && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { - if (mPrivappPermissionsViolations == null) { - mPrivappPermissionsViolations = new ArraySet<>(); + if (permissionViolation) { + Slog.w(TAG, "Privileged permission " + perm + " for package " + + pkg.packageName + " - not in privapp-permissions whitelist"); + + if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { + if (mPrivappPermissionsViolations == null) { + mPrivappPermissionsViolations = new ArraySet<>(); + } + mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); } - mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); } else { return false; } diff --git a/services/core/java/com/android/server/utils/PriorityDump.java b/services/core/java/com/android/server/utils/PriorityDump.java index 054f1564730e..fb92c2b8dd2f 100644 --- a/services/core/java/com/android/server/utils/PriorityDump.java +++ b/services/core/java/com/android/server/utils/PriorityDump.java @@ -16,12 +16,19 @@ package com.android.server.utils; +import android.annotation.IntDef; + import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; /** * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the - * {@link #PRIORITY_ARG} argument. + * {@link #PRIORITY_ARG} and {@link #PROTO_ARG} arguments. * <p> * Typical usage: * @@ -31,13 +38,25 @@ public class SpringfieldNuclearPowerPlant extends Binder { private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { @Override - public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Donuts in the box: 1"); + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + if (asProto) { + ProtoOutputStream proto = new ProtoOutputStream(fd); + proto.write(SpringfieldProto.DONUTS, 1); + proto.flush(); + } else { + pw.println("Donuts in the box: 1"); + } } @Override public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Nuclear reactor status: DANGER - MELTDOWN IMMINENT"); + if (asProto) { + ProtoOutputStream proto = new ProtoOutputStream(fd); + proto.write(SpringfieldProto.REACTOR_STATUS, DANGER_MELTDOWN_IMMINENT); + proto.flush(); + } else { + pw.println("Nuclear reactor status: DANGER - MELTDOWN IMMINENT"); + } } }; @@ -65,6 +84,9 @@ public class SpringfieldNuclearPowerPlant extends Binder { $ adb shell dumpsys snpp --dump-priority NORMAL Nuclear reactor status: DANGER - MELTDOWN IMMINENT + $ adb shell dumpsys snpp --dump-priority CRITICAL --proto + //binary output + * </code></pre> * * @@ -85,95 +107,146 @@ public class SpringfieldNuclearPowerPlant extends Binder { public final class PriorityDump { public static final String PRIORITY_ARG = "--dump-priority"; + public static final String PROTO_ARG = "--proto"; private PriorityDump() { throw new UnsupportedOperationException(); } + /** Enum to switch through supported priority types */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({PRIORITY_TYPE_INVALID, PRIORITY_TYPE_CRITICAL, PRIORITY_TYPE_HIGH, + PRIORITY_TYPE_NORMAL}) + private @interface PriorityType { } + private static final int PRIORITY_TYPE_INVALID = 0; + private static final int PRIORITY_TYPE_CRITICAL = 1; + private static final int PRIORITY_TYPE_HIGH = 2; + private static final int PRIORITY_TYPE_NORMAL = 3; + /** - * Parses {@code} and call the proper {@link PriorityDumper} method when the first argument is - * {@code --dump-priority}, stripping the priority and its type. + * Parses {@code args} matching {@code --dump-priority} and/or {@code --proto}. The matching + * arguments are stripped. + * <p> + * If priority args are passed as an argument, it will call the appropriate method and if proto + * args are passed then the {@code asProto} flag is set. * <p> * For example, if called as {@code --dump-priority HIGH arg1 arg2 arg3}, it will call - * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}) </code> + * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}, false) </code> * <p> * If the {@code --dump-priority} is not set, it calls - * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[])} passing the whole + * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[], boolean)} passing the whole * {@code args} instead. */ public static void dump(PriorityDumper dumper, FileDescriptor fd, PrintWriter pw, String[] args) { - if (args != null && args.length >= 2 && args[0].equals(PRIORITY_ARG)) { - final String priority = args[1]; - switch (priority) { - case "CRITICAL": { - dumper.dumpCritical(fd, pw, getStrippedArgs(args)); - return; - } - case "HIGH": { - dumper.dumpHigh(fd, pw, getStrippedArgs(args)); - return; - } - case "NORMAL": { - dumper.dumpNormal(fd, pw, getStrippedArgs(args)); - return; + boolean asProto = false; + @PriorityType int priority = PRIORITY_TYPE_INVALID; + + if (args == null) { + dumper.dump(fd, pw, args, asProto); + return; + } + + String[] strippedArgs = new String[args.length]; + int strippedCount = 0; + for (int argIndex = 0; argIndex < args.length; argIndex++) { + if (args[argIndex].equals(PROTO_ARG)) { + asProto = true; + } else if (args[argIndex].equals(PRIORITY_ARG)) { + if (argIndex + 1 < args.length) { + argIndex++; + priority = getPriorityType(args[argIndex]); } + } else { + strippedArgs[strippedCount++] = args[argIndex]; + } + } + + if (strippedCount < args.length) { + strippedArgs = Arrays.copyOf(strippedArgs, strippedCount); + } + + switch (priority) { + case PRIORITY_TYPE_CRITICAL: { + dumper.dumpCritical(fd, pw, strippedArgs, asProto); + return; + } + case PRIORITY_TYPE_HIGH: { + dumper.dumpHigh(fd, pw, strippedArgs, asProto); + return; + } + case PRIORITY_TYPE_NORMAL: { + dumper.dumpNormal(fd, pw, strippedArgs, asProto); + return; + } + default: { + dumper.dump(fd, pw, strippedArgs, asProto); + return; } } - dumper.dump(fd, pw, args); } /** - * Gets an array without the {@code --dump-priority PRIORITY} prefix. + * Converts priority argument type to enum. */ - private static String[] getStrippedArgs(String[] args) { - final String[] stripped = new String[args.length - 2]; - System.arraycopy(args, 2, stripped, 0, stripped.length); - return stripped; + private static @PriorityType int getPriorityType(String arg) { + switch (arg) { + case "CRITICAL": { + return PRIORITY_TYPE_CRITICAL; + } + case "HIGH": { + return PRIORITY_TYPE_HIGH; + } + case "NORMAL": { + return PRIORITY_TYPE_NORMAL; + } + } + return PRIORITY_TYPE_INVALID; } /** * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the - * {@link #PRIORITY_ARG} argument. + * {@link #PRIORITY_ARG} and {@link #PROTO_ARG} arguments. * * @hide */ - public static interface PriorityDumper { + public interface PriorityDumper { /** * Dumps only the critical section. */ @SuppressWarnings("unused") - default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { + default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, + boolean asProto) { } /** * Dumps only the high-priority section. */ @SuppressWarnings("unused") - default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) { + default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { } /** * Dumps only the normal section. */ @SuppressWarnings("unused") - default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { } /** * Dumps all sections. * <p> * This method is called when - * {@link PriorityDump#dump(PriorityDumper, FileDescriptor, PrintWriter, String[])} is - * called without priority arguments. By default, it calls the 3 {@code dumpTYPE} methods, - * so sub-classes just need to implement the priority types they support. + * {@link PriorityDump#dump(PriorityDumper, FileDescriptor, PrintWriter, String[], boolean)} + * is called without priority arguments. By default, it calls the 3 {@code dumpTYPE} + * methods, so sub-classes just need to implement the priority types they support. */ @SuppressWarnings("unused") - default void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - dumpCritical(fd, pw, args); - dumpHigh(fd, pw, args); - dumpNormal(fd, pw, args); + default void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + dumpCritical(fd, pw, args, asProto); + dumpHigh(fd, pw, args, asProto); + dumpNormal(fd, pw, args, asProto); } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index ad6fc39d91f8..492d6a7ed34c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -392,13 +392,14 @@ public class WindowManagerService extends IWindowManager.Stub private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { @Override - public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { - doDump(fd, pw, new String[] {"-a"}); + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, + boolean asProto) { + doDump(fd, pw, new String[] {"-a"}, asProto); } @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - doDump(fd, pw, args); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { + doDump(fd, pw, args, asProto); } }; @@ -6730,10 +6731,9 @@ public class WindowManagerService extends IWindowManager.Stub PriorityDump.dump(mPriorityDumper, fd, pw, args); } - private void doDump(FileDescriptor fd, PrintWriter pw, String[] args) { + private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; boolean dumpAll = false; - boolean useProto = false; int opti = 0; while (opti < args.length) { @@ -6744,8 +6744,6 @@ public class WindowManagerService extends IWindowManager.Stub opti++; if ("-a".equals(opt)) { dumpAll = true; - } else if ("--proto".equals(opt)) { - useProto = true; } else if ("-h".equals(opt)) { pw.println("Window manager dump options:"); pw.println(" [-a] [-h] [cmd] ..."); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index b78fcddee119..de5d879a05af 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -125,7 +125,10 @@ import java.util.Timer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; -import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; +import static android.os.IServiceManager.DUMP_FLAG_PROTO; import static android.view.Display.DEFAULT_DISPLAY; public final class SystemServer { @@ -827,7 +830,7 @@ public final class SystemServer { mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore, new PhoneWindowManager()); ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, - DUMP_PRIORITY_CRITICAL); + DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); ServiceManager.addService(Context.INPUT_SERVICE, inputManager); traceEnd(); @@ -1138,7 +1141,9 @@ public final class SystemServer { try { connectivity = new ConnectivityService( context, networkManagement, networkStats, networkPolicy); - ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); + ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity, + /* allowIsolated= */ false, + DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); networkStats.bindConnectivityManager(connectivity); networkPolicy.bindConnectivityManager(connectivity); } catch (Throwable e) { diff --git a/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java index 8a312f64a846..da45d81c6a08 100644 --- a/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java +++ b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java @@ -19,6 +19,7 @@ package com.android.server.utils; import static com.android.server.utils.PriorityDump.dump; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertArrayEquals; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; @@ -59,13 +60,13 @@ public class PriorityDumpTest { @Test public void testNullArgs() { dump(mDumper, mFd, mPw, null); - verify(mDumper).dump(same(mFd), same(mPw), eq(null)); + verify(mDumper).dump(same(mFd), same(mPw), eq(null), /* asProto= */ eq(false)); } @Test public void testNoArgs() { dump(mDumper, mFd, mPw, EMPTY_ARGS); - verify(mDumper).dump(same(mFd), same(mPw), same(EMPTY_ARGS)); + verify(mDumper).dump(same(mFd), same(mPw), eq(EMPTY_ARGS), /* asProto= */ eq(false)); } @Test @@ -74,7 +75,7 @@ public class PriorityDumpTest { "--dumb_priority" }; dump(mDumper, mFd, mPw, args); - verify(mDumper).dump(same(mFd), same(mPw), same(args)); + verify(mDumper).dump(same(mFd), same(mPw), eq(args), /* asProto= */ eq(false)); } @Test @@ -83,7 +84,7 @@ public class PriorityDumpTest { "--dump-priority" }; dump(mDumper, mFd, mPw, args); - verify(mDumper).dump(same(mFd), same(mPw), same(args)); + verify(mDumper).dump(same(mFd), same(mPw), eq(EMPTY_ARGS), /* asProto= */ eq(false)); } @Test @@ -92,7 +93,7 @@ public class PriorityDumpTest { "--dump-priority", "SUPER_HIGH" }; dump(mDumper, mFd, mPw, args); - verify(mDumper).dump(same(mFd), same(mPw), same(args)); + verify(mDumper).dump(same(mFd), same(mPw), eq(EMPTY_ARGS), /* asProto= */ eq(false)); } @Test @@ -101,7 +102,9 @@ public class PriorityDumpTest { "--dump-priority", "SUPER_HIGH", "--high", "--five" }; dump(mDumper, mFd, mPw, args); - verify(mDumper).dump(same(mFd), same(mPw), same(args)); + verify(mDumper).dump(same(mFd), same(mPw), eq(new String[] { + "--high", "--five" + }), /* asProto= */ eq(false)); } @Test @@ -117,13 +120,13 @@ public class PriorityDumpTest { assertSame(mFd, fakeDumper.criticalFd); assertSame(mPw, fakeDumper.criticalPw); - assertSame(args, fakeDumper.criticalArgs); + assertArrayEquals(args, fakeDumper.criticalArgs); assertSame(mFd, fakeDumper.highFd); assertSame(mPw, fakeDumper.highPw); - assertSame(args, fakeDumper.highArgs); + assertArrayEquals(args, fakeDumper.highArgs); assertSame(mFd, fakeDumper.normalFd); assertSame(mPw, fakeDumper.normalPw); - assertSame(args, fakeDumper.normalArgs); + assertArrayEquals(args, fakeDumper.normalArgs); } @Test @@ -131,7 +134,8 @@ public class PriorityDumpTest { dump(mDumper, mFd, mPw, new String[] { "--dump-priority", "CRITICAL" }); - verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(EMPTY_ARGS)); + verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(EMPTY_ARGS), + /* asProto= */ eq(false)); } @Test @@ -141,7 +145,27 @@ public class PriorityDumpTest { }); verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(new String[] { "--high", "--five" - })); + }), /* asProto= */ eq(false)); + } + + @Test + public void testCriticalExtraArgsInMiddle() { + dump(mDumper, mFd, mPw, new String[] { + "--high", "--dump-priority", "CRITICAL", "--five" + }); + verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(new String[] { + "--high", "--five" + }), /* asProto= */ eq(false)); + } + + @Test + public void testCriticalExtraArgsAtEnd() { + dump(mDumper, mFd, mPw, new String[] { + "--high", "--five", "--dump-priority", "CRITICAL" + }); + verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(new String[] { + "--high", "--five" + }), /* asProto= */ eq(false)); } @Test @@ -149,7 +173,7 @@ public class PriorityDumpTest { dump(mDumper, mFd, mPw, new String[] { "--dump-priority", "HIGH" }); - verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(EMPTY_ARGS)); + verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(EMPTY_ARGS), /* asProto= */ eq(false)); } @Test @@ -159,7 +183,7 @@ public class PriorityDumpTest { }); verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(new String[] { "--high", "--five" - })); + }), /* asProto= */ eq(false)); } @Test @@ -167,17 +191,58 @@ public class PriorityDumpTest { dump(mDumper, mFd, mPw, new String[] { "--dump-priority", "NORMAL" }); - verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(EMPTY_ARGS)); + verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(EMPTY_ARGS), /* asProto= */ eq(false)); } @Test public void testNormalExtraArgs() { - dump(mDumper, mFd, mPw, new String[] { + dump(mDumper, mFd, mPw, new String[]{ "--dump-priority", "NORMAL", "--high", "--five" }); - verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(new String[] { + verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(new String[]{ "--high", "--five" - })); + }), /* asProto= */ eq(false)); + } + + @Test + public void testProtoArgs() { + dump(mDumper, mFd, mPw, new String[]{"--proto"}); + verify(mDumper).dump(same(mFd), same(mPw), eq(EMPTY_ARGS), /* asProto= */ eq(true)); + } + + @Test + public void testProtoArgsWithPriorityArgs() { + dump(mDumper, mFd, mPw, new String[]{"--proto", "--dump-priority", "NORMAL", "--five"}); + verify(mDumper).dumpNormal(same(mFd), same(mPw), + eq(new String[]{"--five"}), /* asProto= */ eq(true)); + } + + @Test + public void testProtoArgsWithPriorityArgsReverseOrder() { + dump(mDumper, mFd, mPw, new String[]{"--dump-priority", "NORMAL", "--proto", "--five"}); + verify(mDumper).dumpNormal(same(mFd), same(mPw), + eq(new String[]{"--five"}), /* asProto= */ eq(true)); + } + + @Test + public void testProtoArgsInMiddle() { + dump(mDumper, mFd, mPw, new String[]{"--unknown", "--proto", "--five"}); + verify(mDumper).dump(same(mFd), same(mPw), + eq(new String[]{"--unknown", "--five"}), /* asProto= */ eq(true)); + } + + @Test + public void testProtoArgsAtEnd() { + dump(mDumper, mFd, mPw, new String[]{"args", "-left", "--behind", "--proto"}); + verify(mDumper).dump(same(mFd), same(mPw), + eq(new String[]{"args", "-left", "--behind"}), /* asProto= */ eq(true)); + } + + @Test + public void testProtoArgsWithInvalidPriorityType() { + dump(mDumper, mFd, mPw, new String[]{"--dump-priority", "HIGH?", "--proto"}); + verify(mDumper).dump(same(mFd), same(mPw), + eq(EMPTY_ARGS), /* asProto= */ eq(true)); } private final class FakeDumper implements PriorityDumper { @@ -187,21 +252,22 @@ public class PriorityDumpTest { PrintWriter criticalPw, highPw, normalPw; @Override - public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, + boolean asProto) { criticalFd = fd; criticalPw = pw; criticalArgs = args; } @Override - public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) { + public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { highFd = fd; highPw = pw; highArgs = args; } @Override - public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { normalFd = fd; normalPw = pw; normalArgs = args; |