diff options
author | Baligh Uddin <baligh@google.com> | 2020-12-09 22:51:28 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-12-09 22:51:28 +0000 |
commit | 8f2e0ec9509512dbc55d3316355298bd782ee74b (patch) | |
tree | 06edde13f85a0df313ee2053b4cbd0244a58ba1b | |
parent | f06c01f4938da7a8fcb669b9d2d48af44803bf63 (diff) | |
parent | 71725afa9a85ba5a37bc943a624a164024e69428 (diff) | |
download | base-8f2e0ec9509512dbc55d3316355298bd782ee74b.tar.gz |
Merge "Migrate apex/statsd -> packages/modules/StatsD/apex" into stage-aosp-master
50 files changed, 0 insertions, 6714 deletions
diff --git a/apex/statsd/.clang-format b/apex/statsd/.clang-format deleted file mode 100644 index cead3a079435..000000000000 --- a/apex/statsd/.clang-format +++ /dev/null @@ -1,17 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: true -AllowShortFunctionsOnASingleLine: false -AllowShortLoopsOnASingleLine: true -BinPackArguments: true -BinPackParameters: true -ColumnLimit: 100 -CommentPragmas: NOLINT:.* -ContinuationIndentWidth: 8 -DerivePointerAlignment: false -IndentWidth: 4 -PointerAlignment: Left -TabWidth: 4 -AccessModifierOffset: -4 -IncludeCategories: - - Regex: '^"Log\.h"' - Priority: -1 diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp deleted file mode 100644 index f13861e7ee85..000000000000 --- a/apex/statsd/Android.bp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2019 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. - -apex { - name: "com.android.os.statsd", - defaults: ["com.android.os.statsd-defaults"], - manifest: "apex_manifest.json", -} - -apex_defaults { - jni_libs: [ - "libstats_jni", - ], - native_shared_libs: [ - "libstatspull", - "libstatssocket", - ], - binaries: ["statsd"], - java_libs: [ - "framework-statsd", - "service-statsd", - ], - compile_multilib: "both", - prebuilts: ["com.android.os.statsd.init.rc"], - name: "com.android.os.statsd-defaults", - updatable: true, - min_sdk_version: "30", - key: "com.android.os.statsd.key", - certificate: ":com.android.os.statsd.certificate", -} - -apex_key { - name: "com.android.os.statsd.key", - public_key: "com.android.os.statsd.avbpubkey", - private_key: "com.android.os.statsd.pem", -} - -android_app_certificate { - name: "com.android.os.statsd.certificate", - // This will use com.android.os.statsd.x509.pem (the cert) and - // com.android.os.statsd.pk8 (the private key) - certificate: "com.android.os.statsd", -} - -prebuilt_etc { - name: "com.android.os.statsd.init.rc", - src: "statsd.rc", - filename: "init.rc", - installable: false, -} - -// JNI library for StatsLog.write -cc_library_shared { - name: "libstats_jni", - srcs: ["jni/**/*.cpp"], - header_libs: ["libnativehelper_header_only"], - shared_libs: [ - "liblog", // Has a stable abi - should not be copied into apex. - "libstatssocket", - ], - stl: "libc++_static", - cflags: [ - "-Wall", - "-Werror", - "-Wextra", - "-Wno-unused-parameter", - ], - apex_available: [ - "com.android.os.statsd", - "test_com.android.os.statsd", - ], -} diff --git a/apex/statsd/OWNERS b/apex/statsd/OWNERS deleted file mode 100644 index bed9600bc955..000000000000 --- a/apex/statsd/OWNERS +++ /dev/null @@ -1,9 +0,0 @@ -jeffreyhuang@google.com -joeo@google.com -jtnguyen@google.com -muhammadq@google.com -ruchirr@google.com -singhtejinder@google.com -tsaichristine@google.com -yaochen@google.com -yro@google.com
\ No newline at end of file diff --git a/apex/statsd/TEST_MAPPING b/apex/statsd/TEST_MAPPING deleted file mode 100644 index 93f108707d9e..000000000000 --- a/apex/statsd/TEST_MAPPING +++ /dev/null @@ -1,10 +0,0 @@ -{ - "presubmit" : [ - { - "name" : "FrameworkStatsdTest" - }, - { - "name" : "LibStatsPullTests" - } - ] -} diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp deleted file mode 100644 index 04339e67d799..000000000000 --- a/apex/statsd/aidl/Android.bp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (C) 2019 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. -// -filegroup { - name: "framework-statsd-aidl-sources", - srcs: ["**/*.aidl"], -} - -aidl_interface { - name: "statsd-aidl", - unstable: true, - srcs: [ - "android/os/IPendingIntentRef.aidl", - "android/os/IPullAtomCallback.aidl", - "android/os/IPullAtomResultReceiver.aidl", - "android/os/IStatsCompanionService.aidl", - "android/os/IStatsd.aidl", - "android/os/StatsDimensionsValueParcel.aidl", - "android/util/StatsEventParcel.aidl", - ], - backend: { - java: { - enabled: false, // framework-statsd and service-statsd use framework-statsd-aidl-sources - }, - cpp: { - enabled: false, - }, - ndk: { - enabled: true, - apex_available: [ - // TODO(b/145923087): Remove this once statsd binary is in apex - "//apex_available:platform", - - "com.android.os.statsd", - "test_com.android.os.statsd", - ], - }, - } -} diff --git a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl deleted file mode 100644 index 000a69992a49..000000000000 --- a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2019 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.os; - -import android.os.StatsDimensionsValueParcel; - -/** - * Binder interface to hold a PendingIntent for StatsCompanionService. - * {@hide} - */ -interface IPendingIntentRef { - - /** - * Sends a broadcast to the specified PendingIntent that it should getData now. - * This should be only called from StatsCompanionService. - */ - oneway void sendDataBroadcast(long lastReportTimeNs); - - /** - * Send a broadcast to the specified PendingIntent notifying it that the list of active configs - * has changed. This should be only called from StatsCompanionService. - */ - oneway void sendActiveConfigsChangedBroadcast(in long[] configIds); - - /** - * Send a broadcast to the specified PendingIntent, along with the other information - * specified. This should only be called from StatsCompanionService. - */ - oneway void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId, - long subscriptionRuleId, in String[] cookies, - in StatsDimensionsValueParcel dimensionsValueParcel); -} diff --git a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl deleted file mode 100644 index ff0b97bb5b84..000000000000 --- a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2019 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.os; - -import android.os.IPullAtomResultReceiver; - -/** - * Binder interface to pull atoms for the stats service. - * {@hide} - */ -interface IPullAtomCallback { - /** - * Initiate a request for a pull for an atom. - */ - oneway void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver); - -} diff --git a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl b/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl deleted file mode 100644 index 00d026e25df3..000000000000 --- a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2019 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.os; - -import android.util.StatsEventParcel; - -/** - * Binder interface to pull atoms for the stats service. - * {@hide} - */ -interface IPullAtomResultReceiver { - - /** - * Indicate that a pull request for an atom is complete. - */ - oneway void pullFinished(int atomTag, boolean success, in StatsEventParcel[] output); - -} diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl deleted file mode 100644 index d56a4bd0a8e5..000000000000 --- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2017 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.os; - -/** - * Binder interface to communicate with the Java-based statistics service helper. - * {@hide} - */ -interface IStatsCompanionService { - /** - * Tell statscompanion that stastd is up and running. - */ - oneway void statsdReady(); - - /** - * Register a repeating alarm for pulling to fire at the given timestamp and every - * intervalMs thereafter (in ms since epoch). - * If polling alarm had already been registered, it will be replaced by new one. - * Uses AlarmManager.setRepeating API, so if the timestamp is in past, alarm fires immediately, - * and alarm is inexact. - */ - oneway void setPullingAlarm(long nextPullTimeMs); - - /** Cancel any repeating pulling alarm. */ - oneway void cancelPullingAlarm(); - - /** - * Register an alarm when we want to trigger subscribers at the given - * timestamp (in ms since epoch). - * If an alarm had already been registered, it will be replaced by new one. - */ - oneway void setAlarmForSubscriberTriggering(long timestampMs); - - /** Cancel any alarm for the purpose of subscriber triggering. */ - oneway void cancelAlarmForSubscriberTriggering(); - - /** - * Ask StatsCompanionService if the given permission is allowed for a particular process - * and user ID. statsd is incapable of doing this check itself because checkCallingPermission - * is not currently supported by libbinder_ndk. - */ - boolean checkPermission(String permission, int pid, int uid); -} diff --git a/apex/statsd/aidl/android/os/IStatsManagerService.aidl b/apex/statsd/aidl/android/os/IStatsManagerService.aidl deleted file mode 100644 index b59a97e25bd0..000000000000 --- a/apex/statsd/aidl/android/os/IStatsManagerService.aidl +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (c) 2019, 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.os; - -import android.app.PendingIntent; -import android.os.IPullAtomCallback; - -/** - * Binder interface to communicate with the Java-based statistics service helper. - * Contains parcelable objects available only in Java. - * {@hide} - */ -interface IStatsManagerService { - - /** - * Registers the given pending intent for this config key. This intent is invoked when the - * memory consumed by the metrics for this configuration approach the pre-defined limits. There - * can be at most one listener per config key. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void setDataFetchOperation(long configId, in PendingIntent pendingIntent, - in String packageName); - - /** - * Removes the data fetch operation for the specified configuration. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeDataFetchOperation(long configId, in String packageName); - - /** - * Registers the given pending intent for this packagename. This intent is invoked when the - * active status of any of the configs sent by this package changes and will contain a list of - * config ids that are currently active. It also returns the list of configs that are currently - * active. There can be at most one active configs changed listener per package. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - long[] setActiveConfigsChangedOperation(in PendingIntent pendingIntent, in String packageName); - - /** - * Removes the active configs changed operation for the specified package name. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeActiveConfigsChangedOperation(in String packageName); - - /** - * Set the PendingIntent to be used when broadcasting subscriber - * information to the given subscriberId within the given config. - * - * Suppose that the calling uid has added a config with key configKey, and that in this config - * it is specified that when a particular anomaly is detected, a broadcast should be sent to - * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with - * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast - * when the anomaly is detected. - * - * This function can only be called by the owner (uid) of the config. It must be called each - * time statsd starts. Later calls overwrite previous calls; only one PendingIntent is stored. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent, - in String packageName); - - /** - * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair. - * Any broadcasts associated with subscriberId will henceforth not be sent. - * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntent. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName); - - /** - * Returns the most recently registered experiment IDs. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - long[] getRegisteredExperimentIds(); - - /** - * Fetches metadata across statsd. Returns byte array representing wire-encoded proto. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - byte[] getMetadata(in String packageName); - - /** - * Fetches data for the specified configuration key. Returns a byte array representing proto - * wire-encoded of ConfigMetricsReportList. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - byte[] getData(in long key, in String packageName); - - /** - * Sets a configuration with the specified config id and subscribes to updates for this - * configuration id. Broadcasts will be sent if this configuration needs to be collected. - * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is - * registered in a separate function. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void addConfiguration(in long configId, in byte[] config, in String packageName); - - /** - * Removes the configuration with the matching config id. No-op if this config id does not - * exist. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeConfiguration(in long configId, in String packageName); - - /** Tell StatsManagerService to register a puller for the given atom tag with statsd. */ - oneway void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis, - in int[] additiveFields, IPullAtomCallback pullerCallback); - - /** Tell StatsManagerService to unregister the pulller for the given atom tag from statsd. */ - oneway void unregisterPullAtomCallback(int atomTag); -} diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl deleted file mode 100644 index 066412a9f157..000000000000 --- a/apex/statsd/aidl/android/os/IStatsd.aidl +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Copyright (c) 2017, 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.os; - -import android.os.IPendingIntentRef; -import android.os.IPullAtomCallback; -import android.os.ParcelFileDescriptor; - -/** - * Binder interface to communicate with the statistics management service. - * {@hide} - */ -interface IStatsd { - /** - * Tell the stats daemon that the android system server is up and running. - */ - oneway void systemRunning(); - - /** - * Tell the stats daemon that the android system has finished booting. - */ - oneway void bootCompleted(); - - /** - * Tell the stats daemon that the StatsCompanionService is up and running. - * Two-way binder call so that caller knows message received. - */ - void statsCompanionReady(); - - /** - * Tells statsd that it is time to poll some stats. Statsd will be responsible for determing - * what stats to poll and initiating the polling. - * Two-way binder call so that caller's method (and corresponding wakelocks) will linger. - */ - void informPollAlarmFired(); - - /** - * Tells statsd that it is time to handle periodic alarms. Statsd will be responsible for - * determing what alarm subscriber to trigger. - * Two-way binder call so that caller's method (and corresponding wakelocks) will linger. - */ - void informAlarmForSubscriberTriggeringFired(); - - /** - * Tells statsd that the device is about to shutdown. - */ - void informDeviceShutdown(); - - /** - * Inform statsd about a file descriptor for a pipe through which we will pipe version - * and package information for each uid. - * Versions and package information are supplied via UidData proto where info for each app - * is captured in its own element of a repeated ApplicationInfo message. - */ - oneway void informAllUidData(in ParcelFileDescriptor fd); - - /** - * Inform statsd what the uid, version, version_string, and installer are for one app that was - * updated. - */ - oneway void informOnePackage(in String app, in int uid, in long version, - in String version_string, in String installer); - - /** - * Inform stats that an app was removed. - */ - oneway void informOnePackageRemoved(in String app, in int uid); - - /** - * Fetches data for the specified configuration key. Returns a byte array representing proto - * wire-encoded of ConfigMetricsReportList. - * - * Requires Manifest.permission.DUMP. - */ - byte[] getData(in long key, int callingUid); - - /** - * Fetches metadata across statsd. Returns byte array representing wire-encoded proto. - * - * Requires Manifest.permission.DUMP. - */ - byte[] getMetadata(); - - /** - * Sets a configuration with the specified config id and subscribes to updates for this - * configuration key. Broadcasts will be sent if this configuration needs to be collected. - * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is - * registered in a separate function. - * - * Requires Manifest.permission.DUMP. - */ - void addConfiguration(in long configId, in byte[] config, in int callingUid); - - /** - * Registers the given pending intent for this config key. This intent is invoked when the - * memory consumed by the metrics for this configuration approach the pre-defined limits. There - * can be at most one listener per config key. - * - * Requires Manifest.permission.DUMP. - */ - void setDataFetchOperation(long configId, in IPendingIntentRef pendingIntentRef, - int callingUid); - - /** - * Removes the data fetch operation for the specified configuration. - * - * Requires Manifest.permission.DUMP. - */ - void removeDataFetchOperation(long configId, int callingUid); - - /** - * Registers the given pending intent for this packagename. This intent is invoked when the - * active status of any of the configs sent by this package changes and will contain a list of - * config ids that are currently active. It also returns the list of configs that are currently - * active. There can be at most one active configs changed listener per package. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - long[] setActiveConfigsChangedOperation(in IPendingIntentRef pendingIntentRef, int callingUid); - - /** - * Removes the active configs changed operation for the specified package name. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS. - */ - void removeActiveConfigsChangedOperation(int callingUid); - - /** - * Removes the configuration with the matching config id. No-op if this config id does not - * exist. - * - * Requires Manifest.permission.DUMP. - */ - void removeConfiguration(in long configId, in int callingUid); - - /** - * Set the PendingIntentRef to be used when broadcasting subscriber - * information to the given subscriberId within the given config. - * - * Suppose that the calling uid has added a config with key configId, and that in this config - * it is specified that when a particular anomaly is detected, a broadcast should be sent to - * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with - * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast - * when the anomaly is detected. - * - * This function can only be called by the owner (uid) of the config. It must be called each - * time statsd starts. Later calls overwrite previous calls; only one pendingIntent is stored. - * - * Requires Manifest.permission.DUMP. - */ - void setBroadcastSubscriber(long configId, long subscriberId, in IPendingIntentRef pir, - int callingUid); - - /** - * Undoes setBroadcastSubscriber() for the (configId, subscriberId) pair. - * Any broadcasts associated with subscriberId will henceforth not be sent. - * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntentRef. - * - * Requires Manifest.permission.DUMP. - */ - void unsetBroadcastSubscriber(long configId, long subscriberId, int callingUid); - - /** - * Tell the stats daemon that all the pullers registered during boot have been sent. - */ - oneway void allPullersFromBootRegistered(); - - /** - * Registers a puller callback function that, when invoked, pulls the data - * for the specified atom tag. - */ - oneway void registerPullAtomCallback(int uid, int atomTag, long coolDownMillis, - long timeoutMillis,in int[] additiveFields, - IPullAtomCallback pullerCallback); - - /** - * Registers a puller callback function that, when invoked, pulls the data - * for the specified atom tag. - * - * Enforces the REGISTER_STATS_PULL_ATOM permission. - */ - oneway void registerNativePullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis, - in int[] additiveFields, IPullAtomCallback pullerCallback); - - /** - * Unregisters any pullAtomCallback for the given uid/atom. - */ - oneway void unregisterPullAtomCallback(int uid, int atomTag); - - /** - * Unregisters any pullAtomCallback for the given atom + caller. - * - * Enforces the REGISTER_STATS_PULL_ATOM permission. - */ - oneway void unregisterNativePullAtomCallback(int atomTag); - - /** - * The install requires staging. - */ - const int FLAG_REQUIRE_STAGING = 0x01; - - /** - * Rollback is enabled with this install. - */ - const int FLAG_ROLLBACK_ENABLED = 0x02; - - /** - * Requires low latency monitoring. - */ - const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04; - - /** - * Returns the most recently registered experiment IDs. - */ - long[] getRegisteredExperimentIds(); -} diff --git a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl b/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl deleted file mode 100644 index 05f78d00348e..000000000000 --- a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl +++ /dev/null @@ -1,21 +0,0 @@ -package android.os; - -/** - * @hide - */ -parcelable StatsDimensionsValueParcel { - // Field equals atomTag for top level StatsDimensionsValueParcels or - // positions in depth (1-indexed) for lower level parcels. - int field; - - // Indicator for which type of value is stored. Should be set to one - // of the constants in StatsDimensionsValue.java. - int valueType; - - String stringValue; - int intValue; - long longValue; - boolean boolValue; - float floatValue; - StatsDimensionsValueParcel[] tupleValue; -} diff --git a/apex/statsd/aidl/android/util/StatsEventParcel.aidl b/apex/statsd/aidl/android/util/StatsEventParcel.aidl deleted file mode 100644 index add8bfb47b1a..000000000000 --- a/apex/statsd/aidl/android/util/StatsEventParcel.aidl +++ /dev/null @@ -1,8 +0,0 @@ -package android.util; - -/** - * @hide - */ -parcelable StatsEventParcel { - byte[] buffer; -} diff --git a/apex/statsd/apex_manifest.json b/apex/statsd/apex_manifest.json deleted file mode 100644 index e2972e700880..000000000000 --- a/apex/statsd/apex_manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "com.android.os.statsd", - "version": 300000000 -} - diff --git a/apex/statsd/com.android.os.statsd.avbpubkey b/apex/statsd/com.android.os.statsd.avbpubkey Binary files differdeleted file mode 100644 index d78af8b8bef2..000000000000 --- a/apex/statsd/com.android.os.statsd.avbpubkey +++ /dev/null diff --git a/apex/statsd/com.android.os.statsd.pem b/apex/statsd/com.android.os.statsd.pem deleted file mode 100644 index 558e17fd6864..000000000000 --- a/apex/statsd/com.android.os.statsd.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKgIBAAKCAgEA893bbpkivKEiNgfknYBSlzC0csaKU/ddBm5Pb4ZFuab+LQSR -9DDc5JrsmxyrsrvuwL/zAtMbkyYWzEiUxJtx/w0bw8rC90GoPRSCmxyI0ZK8FuPy -IAQ7UeNfTWZ485mAUaTSasGIfQ3DY4F0P+aUSijeG3NUY02nALHDMqJX7lXR+mL1 -DUYDg05KB0jxQwlYqBeujTPPiAzEqm3PlBoHuan8/qgK2wdQMTVg/fieUD3lupmV -Wj2dRZgqfBPA16ZbV4Uo0j0bZSf+fQLiXlU2VJGb5i/FQfjLqMKGABDI0MgK7Sc2 -m4ySpV4g4XKDv/vw6Dw4kwWC7mATEVAkH+q6V7uiZeN6a7w30UMtPI8fPaUvAP3L -VBjCBIv/3m+CKkWcNxOZ3sQBQl5bS05dxcfiVsBvBLYbvQgC+Wy0Sc3b+1pXFT/E -uAsbZ4CyVsi1+PAdx3h5e2QAyNCXgZDOcvTUyxY6JLTE0LOVHmI4fJEujBex//Oz -PCRHvC8K+KiljyQWf/NYrLSD3QGYAjVMtQh7yu2yhzWzgBUxyhuv3rY4ATXsN3bJ -wW4w7/L/RSLSW5+lp/NoJOD9utbsKTyGMHOY6K8JLOmhv3ORoAEmLYlFTI+FqBi9 -AH1HQEKCyh8Z/bYHLUzGWl6FqAMtcnuintv40BbKyt0/D1ItdbSNKmOZ5rkCAwEA -AQKCAgAY7ll8mRNADYkd1Pi+UVwgMM6B3WJO6z8LZUOhtyxxqmzZ1VnGiShMBrqh -sPCsuSHTeswxQbvT81TpVZI/91RUKtbn0VbVSFUWyX4AtY4XPtUT0gHy2/vkh0Y6 -93ruDIdd0Wfhmh+GCV4sUhO8ZKpMWpk6XTQHYuzr2UCHcKlkqElrO6qpzLqXNe3D -iOWBYPc7WBB0RxO0aPnCIq/SCEc55/MBZdSWR80e+sILtNsagPl3djQaoanub3wI -a0yPv2YfMHHX7H9cfBY8WYsi8bs4MhqqEcAs2m6XtitU3mJpVcooLJYcmOZ1GYZr -BfYKLouWcnGmNi4IiLHqVzMaQDkEhAZsRaAXCkoVVrFBedLlmLPpiUIQlINF4vxe -3IcekTKWyMzkU6h+K8T15MU5mLSqeL2Gji1JIwKJno51FZ9uc++pUJVtfYQmNny8 -8RKvQ1hv/S5yLQKgN+VkNbaWlUoMP73dtUe3m/At71/2Dj7xB0KtcgT1lEMrM1GR -oynJAJLz/d0n5RUUREwkZZMcA4fQVC7Db6vpK69jPiQMShpZ3JKCEjfYLUuN0slt -FPhjiR175E0vTRuLoIj4kXNwLLswH0c9zqrKM2S92SCxAV3E4JJGKhUZalvT9s1g -LrPhMCl6CsOES98T87d3RyAIK0iVRCnRUG3bc+8rzyRd4fzkAQKCAQEA/UjmCSm3 -H46t/1w7YBZPew7SFQOAJe81iDzbonc3fNPD2R8lxtD3MwdvrQ5f9fhT4+uveWNr -dyBX7ppnissyM3LZRN+7BdeIVVeIPVen6Ou9W2i7q18ZoQx9IpRcZEw5tGJFZaGx -EmyPN4i1K0ccUkGbBvbXXQ/tcG3wElRpBAc5/TQ8vrpUgHll2/MbYhowx6P9uHv5 -thoyG98X+7Fbg8ikzw5GtyuedXfyX1CpJ7yUQVS2PEaOMXOkZdx2bbWRAYYCpsqB -dMmjs2PsFhZHu6CpLhlocHbfUiRztCUCaMZJPQXFSVmy8QDMvZEdVLvad9Poi8ny -lmHVRgxaNbAtIQKCAQEA9nscqRaaO7hIX9bOUxcDbI0486Ws4H0hAFApIN+6/LP4 -hkxey3xWArTYWrvSG1d5GkJAdn99ayWzo2PevmJlrhIJiO1QqYBAk+87cnhwSCmB -kb0sGkNWcc/xNRy7eqdhyCmVhaUnIbORee+cD6qiu/l2BAclTf2ZARFOGXjhQkvt -cDbc/9ZR467ceXbiTIU34Be4xnNAY1mo59jvwl9eqxgpefYTqPhcZ7OmlDli77Hd -XuRfuxLZCscv7A9M5Enc2zwOEP5VwRNwYzYtMm2Yh9CQZxNWC7JVh1Gw5MPFzsGl -sgEdb4WGneN6PPLQHK7NF0f7wYSNnF0i3XSME9MumQKCAQEA0qMbWydr+TyJC0LC -xigHtUkgAQXGPsXuePxTk4sdhBwAVcKHgg4qZi+a+gpoV4BLE9LfPU4nAwzM08to -rI5Lk2nBsnt1Z2hVItQGoy0QoK3b7fbti5ktETf3oRhMtcSGgLLxD5ImVjId8Isq -T3F15hpVOLdzZxtl1Qg4jKXSJ91yplYY5mzC9Yz/3qkQbsdlJcIFsLS5eG3UmkUw -Bsr6VmA4X1F6Eb6eqwYzdHz6D+fOS36NhxcODaYkY+myO46xptixv8/NVTiTgQ5q -OfwRb8Iur/3FUzIoioFyD7Bvjn7ITY1NArEsFS0bF9Nk1yDakKiUThyGN/Xojbac -FuYKwQKCAQEAxOWJ+qU8phJLdowBHC0ZJiEWasRhep9auoZOpJ01IWOfV6EwZLs5 -dkYDQ1Agwoi5DDn6hu7HQM3IV/CS4mF2OnzcMw7ozc7PR53nTkVZ5LuLbuHAlmZO -avKjDDucpJmLqjtV34IT5X8t6kt3zqgQAbuBBCy1Jz07ebfaPMzsnWpMDcU1/AW4 -OvrX0wweMOSGwzQP/i/ZMsRQAo2w0gQfeuv9Thk+kU99ebXwjx3co//hCEnFE4s1 -6L8/0AJU+VTr4hJyZi7WUDt4HzkLF+qm22/Hux+eMA/Q9R1UAxtFLCpTdAQiAJGY -/Q3X+1I434DgAwYU3f1Gpq9cB65vq/KamQKCAQEAjIub5wde/ttHlLALvnOXrbqe -nUIfWHExMzhul/rkr8fFEJwij2nZUuN2EWUGzBWQQoNXw5QKHLZyPsyFUOa/P2BS -osnffAa+sumL4k36E71xFdTVV5ExyTXZVB49sPmUpivP9gEucFFqDHKjGsF45dBF -+DZdykLUIv+/jQUzXGkZ5Wv/r52YUNho4EZdwnlJ2so7cxnsYnjW+c1nlp17tkq5 -DfwktkeD9iFzlaZ66vLoO44luaBm+lC3xM2sHinOTwbk0gvhJAIoLfkOYhpmGc8A -4W/E1OHfVz6xqVDsMBFhRbQpHNkf8XZNqkIoqHVMTaMOJJlM+lb0+A9B8Bm/XA== ------END RSA PRIVATE KEY----- diff --git a/apex/statsd/com.android.os.statsd.pk8 b/apex/statsd/com.android.os.statsd.pk8 Binary files differdeleted file mode 100644 index 49910f80a05c..000000000000 --- a/apex/statsd/com.android.os.statsd.pk8 +++ /dev/null diff --git a/apex/statsd/com.android.os.statsd.x509.pem b/apex/statsd/com.android.os.statsd.x509.pem deleted file mode 100644 index e7b16b2048cb..000000000000 --- a/apex/statsd/com.android.os.statsd.x509.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFDTCCAvWgAwIBAgIUCnta1LAl5fMMLLQx//4zWz9A2A8wDQYJKoZIhvcNAQEL -BQAwFTETMBEGA1UECgwKR29vZ2xlIExMQzAgFw0xOTA4MTIyMjM5MzBaGA80NzU3 -MDcwODIyMzkzMFowFTETMBEGA1UECgwKR29vZ2xlIExMQzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAOranWZ19jkXCF9WIlXv01tUUvLKMHWKV7X9Earw -cL7/aax0pFbNJutgyBUiOszbR+0T7quZxz6jACu+6y7iaMJnvMluZsfTi+p2UvQt -y6Ql7ZUOQ7bVluCFIW5hZ+8d9RrLmZdvX1r4YfF6HufDBkAbj+os+y6407OezJAV -8EATpemc9gsCC4RJZpwzTs1RUXMD4UoNrLZAE8+7iaJZeBxmz0MAPj92pYc9M7/d -xInzYvOR08/uEpHt8jlMdVgSQS/FaRlIOIqcGBk3cjkjDlpVATQ4Hyjy+IPQPjTD -bJUmDJiYeBCyY/pYZQvTQjl8s+fvykTsF9Lfb+E+PhZ0+N8pRi7sUSpisZHSiqaN -W3oxYWc0YQSuzygHHog8HH/azHX5L805g/+Rwfb/cUF9eJgjq0vrkFnsz4UKgKNV -hHL90mfqpbc2UvJ8VY8BvIjbsHQ77LrBKlqI9VMPorttpTOuwHHJPKsyN972F0Ul -lRB6CwFE8csVGWXoNaDZWBv7xTDdbdirmlKDNueg9pw6ksYV2Is9Dv8PxmsZvb+4 -oftC/hb4X1Pudn01PPs9Tx44CwHuVLENUwlDEVzG5zNetsv9kAuCYt3VRVF+NYqj -NAfLbxCKLe25wGzJrZUEJ1YrYIjpUbfwnttEad/9Pu13DAS7HZwn5vwqEKB/1LlT -NSUXAgMBAAGjUzBRMB0GA1UdDgQWBBSKElkhJSbzgh8+iysye8SrkmJ62DAfBgNV -HSMEGDAWgBSKElkhJSbzgh8+iysye8SrkmJ62DAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBCwUAA4ICAQANFGnc2wJBrFbh2nzhl06g4TjPKGRCw365vZ1A3T9O -jXP0lToHDxB33TpKk6d7zszR1uPphQQxgzhSVZB/jx8q4kWSSoKoF9Dlx7h8rAt+ -2TM5DaBvxrwu5mqOALwQuF81wap1Pl2L2fFHvygCm8b+Ci4iS5vcr0axNnp1rK1b -vUtRWY4mfxTjJYcgeCVUGskqTb+cCxQZ6Icno6VTKajT1FybRmD3KZJaUuLbNEN+ -IE4nGTMG2WZ5Hl2vR8JJp1sYYn8T3ElMAb0MSNFkqsfI+tToEwGsuJDgYEdtEnzf -lTycQvn5NhrIZRRN3pqSyWpAU7p9mmyTK0PHMz2D/Rtfb7lE692vXzxCmZND51mc -YXCCoanV6eZZ7Sbqzh60+5QV38hgFBst5l8CcFaWWSFK9nBWdzS5lhs9lmQ4aiYd -IE0qsNZgMob+TTP1VW39hu4EDjNmOrKfimM9J2tcPZ5QP01DgETPvAsB7vn2Xz9J -HGt5ntiSV4W2izDP8viQ1M5NvfdBaUhcnNsE6/sxfU0USRs2hrEp1oiqrv4p6V0P -qOt7C2/YtJzkrxfsHZAxBUSRHa7LwtzgeiJDUivHn94VnAzSAH8MLx6CzDPQ8HWN -NiZFxTKfMVyjEmbQ2PalHWB8pWtpdEh7X4rzaqhnLBTis3pGssASgo3ArLIYleAU -+g== ------END CERTIFICATE----- diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp deleted file mode 100644 index e4299f52ff7d..000000000000 --- a/apex/statsd/framework/Android.bp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2019 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 { - default_visibility: [ ":__pkg__" ] -} - -genrule { - name: "statslog-statsd-java-gen", - tools: ["stats-log-api-gen"], - cmd: "$(location stats-log-api-gen) --java $(out) --module statsd" + - " --javaPackage com.android.internal.statsd --javaClass StatsdStatsLog", - out: ["com/android/internal/statsd/StatsdStatsLog.java"], -} - -java_library_static { - name: "statslog-statsd", - srcs: [ - ":statslog-statsd-java-gen", - ], - visibility: [ - "//cts/hostsidetests/statsd/apps:__subpackages__", - "//vendor:__subpackages__", - ], -} - -filegroup { - name: "framework-statsd-sources", - srcs: [ - "java/**/*.java", - ":framework-statsd-aidl-sources", - ":statslog-statsd-java-gen", - ], - visibility: [ - "//frameworks/base", // For the "global" stubs. - "//frameworks/base/apex/statsd:__subpackages__", - "//packages/modules/StatsD/apex:__subpackages__", - ], -} -java_sdk_library { - name: "framework-statsd", - defaults: ["framework-module-defaults"], - installable: true, - - srcs: [ - ":framework-statsd-sources", - ], - - permitted_packages: [ - "android.app", - "android.os", - "android.util", - // From :statslog-statsd-java-gen - "com.android.internal.statsd", - ], - - api_packages: [ - "android.app", - "android.os", - "android.util", - ], - - hostdex: true, // for hiddenapi check - - impl_library_visibility: [ - "//frameworks/base/apex/statsd/framework/test:__subpackages__", - "//packages/modules/StatsD/apex/framework/test:__subpackages__", - ], - - apex_available: [ - "com.android.os.statsd", - "test_com.android.os.statsd", - ], -} diff --git a/apex/statsd/framework/api/current.txt b/apex/statsd/framework/api/current.txt deleted file mode 100644 index a65569347e7d..000000000000 --- a/apex/statsd/framework/api/current.txt +++ /dev/null @@ -1,12 +0,0 @@ -// Signature format: 2.0 -package android.util { - - public final class StatsLog { - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public static boolean logBinaryPushStateChanged(@NonNull String, long, int, int, @NonNull long[]); - method public static boolean logEvent(int); - method public static boolean logStart(int); - method public static boolean logStop(int); - } - -} - diff --git a/apex/statsd/framework/api/module-lib-current.txt b/apex/statsd/framework/api/module-lib-current.txt deleted file mode 100644 index 8b6e2170002e..000000000000 --- a/apex/statsd/framework/api/module-lib-current.txt +++ /dev/null @@ -1,10 +0,0 @@ -// Signature format: 2.0 -package android.os { - - public class StatsFrameworkInitializer { - method public static void registerServiceWrappers(); - method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager); - } - -} - diff --git a/apex/statsd/framework/api/module-lib-removed.txt b/apex/statsd/framework/api/module-lib-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/statsd/framework/api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/statsd/framework/api/removed.txt b/apex/statsd/framework/api/removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/statsd/framework/api/removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/statsd/framework/api/system-current.txt b/apex/statsd/framework/api/system-current.txt deleted file mode 100644 index 3ea572450c1c..000000000000 --- a/apex/statsd/framework/api/system-current.txt +++ /dev/null @@ -1,111 +0,0 @@ -// Signature format: 2.0 -package android.app { - - public final class StatsManager { - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException; - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]); - method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void clearPullAtomCallback(int); - method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getData(long); - method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getMetadata(); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] getRegisteredExperimentIds() throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException; - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException; - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent); - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException; - method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void setPullAtomCallback(int, @Nullable android.app.StatsManager.PullAtomMetadata, @NonNull java.util.concurrent.Executor, @NonNull android.app.StatsManager.StatsPullAtomCallback); - field public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED"; - field public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = "android.app.extra.STATS_ACTIVE_CONFIG_KEYS"; - field public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES"; - field public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY"; - field public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID"; - field public static final String EXTRA_STATS_DIMENSIONS_VALUE = "android.app.extra.STATS_DIMENSIONS_VALUE"; - field public static final String EXTRA_STATS_SUBSCRIPTION_ID = "android.app.extra.STATS_SUBSCRIPTION_ID"; - field public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = "android.app.extra.STATS_SUBSCRIPTION_RULE_ID"; - field public static final int PULL_SKIP = 1; // 0x1 - field public static final int PULL_SUCCESS = 0; // 0x0 - } - - public static class StatsManager.PullAtomMetadata { - method @Nullable public int[] getAdditiveFields(); - method public long getCoolDownMillis(); - method public long getTimeoutMillis(); - } - - public static class StatsManager.PullAtomMetadata.Builder { - ctor public StatsManager.PullAtomMetadata.Builder(); - method @NonNull public android.app.StatsManager.PullAtomMetadata build(); - method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setAdditiveFields(@NonNull int[]); - method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setCoolDownMillis(long); - method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setTimeoutMillis(long); - } - - public static interface StatsManager.StatsPullAtomCallback { - method public int onPullAtom(int, @NonNull java.util.List<android.util.StatsEvent>); - } - - public static class StatsManager.StatsUnavailableException extends android.util.AndroidException { - ctor public StatsManager.StatsUnavailableException(String); - ctor public StatsManager.StatsUnavailableException(String, Throwable); - } - -} - -package android.os { - - public final class StatsDimensionsValue implements android.os.Parcelable { - method public int describeContents(); - method public boolean getBooleanValue(); - method public int getField(); - method public float getFloatValue(); - method public int getIntValue(); - method public long getLongValue(); - method public String getStringValue(); - method public java.util.List<android.os.StatsDimensionsValue> getTupleValueList(); - method public int getValueType(); - method public boolean isValueType(int); - method public void writeToParcel(android.os.Parcel, int); - field public static final int BOOLEAN_VALUE_TYPE = 5; // 0x5 - field @NonNull public static final android.os.Parcelable.Creator<android.os.StatsDimensionsValue> CREATOR; - field public static final int FLOAT_VALUE_TYPE = 6; // 0x6 - field public static final int INT_VALUE_TYPE = 3; // 0x3 - field public static final int LONG_VALUE_TYPE = 4; // 0x4 - field public static final int STRING_VALUE_TYPE = 2; // 0x2 - field public static final int TUPLE_VALUE_TYPE = 7; // 0x7 - } - -} - -package android.util { - - public final class StatsEvent { - method @NonNull public static android.util.StatsEvent.Builder newBuilder(); - } - - public static final class StatsEvent.Builder { - method @NonNull public android.util.StatsEvent.Builder addBooleanAnnotation(byte, boolean); - method @NonNull public android.util.StatsEvent.Builder addIntAnnotation(byte, int); - method @NonNull public android.util.StatsEvent build(); - method @NonNull public android.util.StatsEvent.Builder setAtomId(int); - method @NonNull public android.util.StatsEvent.Builder usePooledBuffer(); - method @NonNull public android.util.StatsEvent.Builder writeAttributionChain(@NonNull int[], @NonNull String[]); - method @NonNull public android.util.StatsEvent.Builder writeBoolean(boolean); - method @NonNull public android.util.StatsEvent.Builder writeByteArray(@NonNull byte[]); - method @NonNull public android.util.StatsEvent.Builder writeFloat(float); - method @NonNull public android.util.StatsEvent.Builder writeInt(int); - method @NonNull public android.util.StatsEvent.Builder writeKeyValuePairs(@Nullable android.util.SparseIntArray, @Nullable android.util.SparseLongArray, @Nullable android.util.SparseArray<java.lang.String>, @Nullable android.util.SparseArray<java.lang.Float>); - method @NonNull public android.util.StatsEvent.Builder writeLong(long); - method @NonNull public android.util.StatsEvent.Builder writeString(@NonNull String); - } - - public final class StatsLog { - method public static void write(@NonNull android.util.StatsEvent); - method public static void writeRaw(@NonNull byte[], int); - } - -} - diff --git a/apex/statsd/framework/api/system-removed.txt b/apex/statsd/framework/api/system-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/apex/statsd/framework/api/system-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java deleted file mode 100644 index a7d20572ca96..000000000000 --- a/apex/statsd/framework/java/android/app/StatsManager.java +++ /dev/null @@ -1,725 +0,0 @@ -/* - * Copyright 2017 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.app; - -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.PACKAGE_USAGE_STATS; - -import android.annotation.CallbackExecutor; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.content.Context; -import android.os.Binder; -import android.os.IPullAtomCallback; -import android.os.IPullAtomResultReceiver; -import android.os.IStatsManagerService; -import android.os.RemoteException; -import android.os.StatsFrameworkInitializer; -import android.util.AndroidException; -import android.util.Log; -import android.util.StatsEvent; -import android.util.StatsEventParcel; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; - -/** - * API for statsd clients to send configurations and retrieve data. - * - * @hide - */ -@SystemApi -public final class StatsManager { - private static final String TAG = "StatsManager"; - private static final boolean DEBUG = false; - - private static final Object sLock = new Object(); - private final Context mContext; - - @GuardedBy("sLock") - private IStatsManagerService mStatsManagerService; - - /** - * Long extra of uid that added the relevant stats config. - */ - public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID"; - /** - * Long extra of the relevant stats config's configKey. - */ - public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY"; - /** - * Long extra of the relevant statsd_config.proto's Subscription.id. - */ - public static final String EXTRA_STATS_SUBSCRIPTION_ID = - "android.app.extra.STATS_SUBSCRIPTION_ID"; - /** - * Long extra of the relevant statsd_config.proto's Subscription.rule_id. - */ - public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = - "android.app.extra.STATS_SUBSCRIPTION_RULE_ID"; - /** - * List<String> of the relevant statsd_config.proto's BroadcastSubscriberDetails.cookie. - * Obtain using {@link android.content.Intent#getStringArrayListExtra(String)}. - */ - public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = - "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES"; - /** - * Extra of a {@link android.os.StatsDimensionsValue} representing sliced dimension value - * information. - */ - public static final String EXTRA_STATS_DIMENSIONS_VALUE = - "android.app.extra.STATS_DIMENSIONS_VALUE"; - /** - * Long array extra of the active configs for the uid that added those configs. - */ - public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = - "android.app.extra.STATS_ACTIVE_CONFIG_KEYS"; - - /** - * Broadcast Action: Statsd has started. - * Configurations and PendingIntents can now be sent to it. - */ - public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED"; - - // Pull atom callback return codes. - /** - * Value indicating that this pull was successful and that the result should be used. - * - **/ - public static final int PULL_SUCCESS = 0; - - /** - * Value indicating that this pull was unsuccessful and that the result should not be used. - **/ - public static final int PULL_SKIP = 1; - - /** - * @hide - **/ - @VisibleForTesting public static final long DEFAULT_COOL_DOWN_MILLIS = 1_000L; // 1 second. - - /** - * @hide - **/ - @VisibleForTesting public static final long DEFAULT_TIMEOUT_MILLIS = 2_000L; // 2 seconds. - - /** - * Constructor for StatsManagerClient. - * - * @hide - */ - public StatsManager(Context context) { - mContext = context; - } - - /** - * Adds the given configuration and associates it with the given configKey. If a config with the - * given configKey already exists for the caller's uid, it is replaced with the new one. - * - * @param configKey An arbitrary integer that allows clients to track the configuration. - * @param config Wire-encoded StatsdConfig proto that specifies metrics (and all - * dependencies eg, conditions and matchers). - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - * @throws IllegalArgumentException if config is not a wire-encoded StatsdConfig proto - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void addConfig(long configKey, byte[] config) throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - // can throw IllegalArgumentException - service.addConfiguration(configKey, config, mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when adding configuration"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to addConfig in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #addConfig(long, byte[])} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean addConfiguration(long configKey, byte[] config) { - try { - addConfig(configKey, config); - return true; - } catch (StatsUnavailableException | IllegalArgumentException e) { - return false; - } - } - - /** - * Remove a configuration from logging. - * - * @param configKey Configuration key to remove. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void removeConfig(long configKey) throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - service.removeConfiguration(configKey, mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when removing configuration"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to removeConfig in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #removeConfig(long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean removeConfiguration(long configKey) { - try { - removeConfig(configKey); - return true; - } catch (StatsUnavailableException e) { - return false; - } - } - - /** - * Set the PendingIntent to be used when broadcasting subscriber information to the given - * subscriberId within the given config. - * <p> - * Suppose that the calling uid has added a config with key configKey, and that in this config - * it is specified that when a particular anomaly is detected, a broadcast should be sent to - * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with - * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast - * when the anomaly is detected. - * <p> - * When statsd sends the broadcast, the PendingIntent will used to send an intent with - * information of - * {@link #EXTRA_STATS_CONFIG_UID}, - * {@link #EXTRA_STATS_CONFIG_KEY}, - * {@link #EXTRA_STATS_SUBSCRIPTION_ID}, - * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID}, - * {@link #EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES}, and - * {@link #EXTRA_STATS_DIMENSIONS_VALUE}. - * <p> - * This function can only be called by the owner (uid) of the config. It must be called each - * time statsd starts. The config must have been added first (via {@link #addConfig}). - * - * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber - * associated with the given subscriberId. May be null, in which case - * it undoes any previous setting of this subscriberId. - * @param configKey The integer naming the config to which this subscriber is attached. - * @param subscriberId ID of the subscriber, as used in the config. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void setBroadcastSubscriber( - PendingIntent pendingIntent, long configKey, long subscriberId) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - if (pendingIntent != null) { - service.setBroadcastSubscriber(configKey, subscriberId, pendingIntent, - mContext.getOpPackageName()); - } else { - service.unsetBroadcastSubscriber(configKey, subscriberId, - mContext.getOpPackageName()); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when adding broadcast subscriber", - e); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #setBroadcastSubscriber(PendingIntent, long, long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean setBroadcastSubscriber( - long configKey, long subscriberId, PendingIntent pendingIntent) { - try { - setBroadcastSubscriber(pendingIntent, configKey, subscriberId); - return true; - } catch (StatsUnavailableException e) { - return false; - } - } - - /** - * Registers the operation that is called to retrieve the metrics data. This must be called - * each time statsd starts. The config must have been added first (via {@link #addConfig}, - * although addConfig could have been called on a previous boot). This operation allows - * statsd to send metrics data whenever statsd determines that the metrics in memory are - * approaching the memory limits. The fetch operation should call {@link #getReports} to fetch - * the data, which also deletes the retrieved metrics from statsd's memory. - * - * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber - * associated with the given subscriberId. May be null, in which case - * it removes any associated pending intent with this configKey. - * @param configKey The integer naming the config to which this operation is attached. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void setFetchReportsOperation(PendingIntent pendingIntent, long configKey) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - if (pendingIntent == null) { - service.removeDataFetchOperation(configKey, mContext.getOpPackageName()); - } else { - service.setDataFetchOperation(configKey, pendingIntent, - mContext.getOpPackageName()); - } - - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when registering data listener."); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - /** - * Registers the operation that is called whenever there is a change in which configs are - * active. This must be called each time statsd starts. This operation allows - * statsd to inform clients that they should pull data of the configs that are currently - * active. The activeConfigsChangedOperation should set periodic alarms to pull data of configs - * that are active and stop pulling data of configs that are no longer active. - * - * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber - * associated with the given subscriberId. May be null, in which case - * it removes any associated pending intent for this client. - * @return A list of configs that are currently active for this client. If the pendingIntent is - * null, this will be an empty list. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public @NonNull long[] setActiveConfigsChangedOperation(@Nullable PendingIntent pendingIntent) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - if (pendingIntent == null) { - service.removeActiveConfigsChangedOperation(mContext.getOpPackageName()); - return new long[0]; - } else { - return service.setActiveConfigsChangedOperation(pendingIntent, - mContext.getOpPackageName()); - } - - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager " - + "when registering active configs listener."); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #setFetchReportsOperation(PendingIntent, long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) { - try { - setFetchReportsOperation(pendingIntent, configKey); - return true; - } catch (StatsUnavailableException e) { - return false; - } - } - - /** - * Request the data collected for the given configKey. - * This getter is destructive - it also clears the retrieved metrics from statsd's memory. - * - * @param configKey Configuration key to retrieve data from. - * @return Serialized ConfigMetricsReportList proto. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public byte[] getReports(long configKey) throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - return service.getData(configKey, mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when getting data"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to getReports in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #getReports(long)} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public @Nullable byte[] getData(long configKey) { - try { - return getReports(configKey); - } catch (StatsUnavailableException e) { - return null; - } - } - - /** - * Clients can request metadata for statsd. Will contain stats across all configurations but not - * the actual metrics themselves (metrics must be collected via {@link #getReports(long)}. - * This getter is not destructive and will not reset any metrics/counters. - * - * @return Serialized StatsdStatsReport proto. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public byte[] getStatsMetadata() throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - return service.getMetadata(mContext.getOpPackageName()); - } catch (RemoteException e) { - Log.e(TAG, "Failed to connect to statsmanager when getting metadata"); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to getStatsMetadata in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - // TODO: Temporary for backwards compatibility. Remove. - /** - * @deprecated Use {@link #getStatsMetadata()} - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public @Nullable byte[] getMetadata() { - try { - return getStatsMetadata(); - } catch (StatsUnavailableException e) { - return null; - } - } - - /** - * Returns the experiments IDs registered with statsd, or an empty array if there aren't any. - * - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - */ - @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS}) - public long[] getRegisteredExperimentIds() - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - return service.getRegisteredExperimentIds(); - } catch (RemoteException e) { - if (DEBUG) { - Log.d(TAG, - "Failed to connect to StatsManagerService when getting " - + "registered experiment IDs"); - } - throw new StatsUnavailableException("could not connect", e); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to getRegisteredExperimentIds in statsmanager"); - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - /** - * Sets a callback for an atom when that atom is to be pulled. The stats service will - * invoke pullData in the callback when the stats service determines that this atom needs to be - * pulled. This method should not be called by third-party apps. - * - * @param atomTag The tag of the atom for this puller callback. - * @param metadata Optional metadata specifying the timeout, cool down time, and - * additive fields for mapping isolated to host uids. - * @param executor The executor in which to run the callback. - * @param callback The callback to be invoked when the stats service pulls the atom. - * - */ - @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) - public void setPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata, - @NonNull @CallbackExecutor Executor executor, - @NonNull StatsPullAtomCallback callback) { - long coolDownMillis = - metadata == null ? DEFAULT_COOL_DOWN_MILLIS : metadata.mCoolDownMillis; - long timeoutMillis = metadata == null ? DEFAULT_TIMEOUT_MILLIS : metadata.mTimeoutMillis; - int[] additiveFields = metadata == null ? new int[0] : metadata.mAdditiveFields; - if (additiveFields == null) { - additiveFields = new int[0]; - } - - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - PullAtomCallbackInternal rec = - new PullAtomCallbackInternal(atomTag, callback, executor); - service.registerPullAtomCallback( - atomTag, coolDownMillis, timeoutMillis, additiveFields, rec); - } catch (RemoteException e) { - throw new RuntimeException("Unable to register pull callback", e); - } - } - } - - /** - * Clears a callback for an atom when that atom is to be pulled. Note that any ongoing - * pulls will still occur. This method should not be called by third-party apps. - * - * @param atomTag The tag of the atom of which to unregister - * - */ - @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) - public void clearPullAtomCallback(int atomTag) { - synchronized (sLock) { - try { - IStatsManagerService service = getIStatsManagerServiceLocked(); - service.unregisterPullAtomCallback(atomTag); - } catch (RemoteException e) { - throw new RuntimeException("Unable to unregister pull atom callback"); - } - } - } - - private static class PullAtomCallbackInternal extends IPullAtomCallback.Stub { - public final int mAtomId; - public final StatsPullAtomCallback mCallback; - public final Executor mExecutor; - - PullAtomCallbackInternal(int atomId, StatsPullAtomCallback callback, Executor executor) { - mAtomId = atomId; - mCallback = callback; - mExecutor = executor; - } - - @Override - public void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver) { - long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - List<StatsEvent> data = new ArrayList<>(); - int successInt = mCallback.onPullAtom(atomTag, data); - boolean success = successInt == PULL_SUCCESS; - StatsEventParcel[] parcels = new StatsEventParcel[data.size()]; - for (int i = 0; i < data.size(); i++) { - parcels[i] = new StatsEventParcel(); - parcels[i].buffer = data.get(i).getBytes(); - } - try { - resultReceiver.pullFinished(atomTag, success, parcels); - } catch (RemoteException e) { - Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId - + " due to TransactionTooLarge. Calling pullFinish with no data"); - StatsEventParcel[] emptyData = new StatsEventParcel[0]; - try { - resultReceiver.pullFinished(atomTag, /*success=*/false, emptyData); - } catch (RemoteException nestedException) { - Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId - + " with empty payload"); - } - } - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - } - - /** - * Metadata required for registering a StatsPullAtomCallback. - * All fields are optional, and defaults will be used for fields that are unspecified. - * - */ - public static class PullAtomMetadata { - private final long mCoolDownMillis; - private final long mTimeoutMillis; - private final int[] mAdditiveFields; - - // Private Constructor for builder - private PullAtomMetadata(long coolDownMillis, long timeoutMillis, int[] additiveFields) { - mCoolDownMillis = coolDownMillis; - mTimeoutMillis = timeoutMillis; - mAdditiveFields = additiveFields; - } - - /** - * Builder for PullAtomMetadata. - */ - public static class Builder { - private long mCoolDownMillis; - private long mTimeoutMillis; - private int[] mAdditiveFields; - - /** - * Returns a new PullAtomMetadata.Builder object for constructing PullAtomMetadata for - * StatsManager#registerPullAtomCallback - */ - public Builder() { - mCoolDownMillis = DEFAULT_COOL_DOWN_MILLIS; - mTimeoutMillis = DEFAULT_TIMEOUT_MILLIS; - mAdditiveFields = null; - } - - /** - * Set the cool down time of the pull in milliseconds. If two successive pulls are - * issued within the cool down, a cached version of the first pull will be used for the - * second pull. The minimum allowed cool down is 1 second. - */ - @NonNull - public Builder setCoolDownMillis(long coolDownMillis) { - mCoolDownMillis = coolDownMillis; - return this; - } - - /** - * Set the maximum time the pull can take in milliseconds. The maximum allowed timeout - * is 10 seconds. - */ - @NonNull - public Builder setTimeoutMillis(long timeoutMillis) { - mTimeoutMillis = timeoutMillis; - return this; - } - - /** - * Set the additive fields of this pulled atom. - * - * This is only applicable for atoms which have a uid field. When tasks are run in - * isolated processes, the data will be attributed to the host uid. Additive fields - * will be combined when the non-additive fields are the same. - */ - @NonNull - public Builder setAdditiveFields(@NonNull int[] additiveFields) { - mAdditiveFields = additiveFields; - return this; - } - - /** - * Builds and returns a PullAtomMetadata object with the values set in the builder and - * defaults for unset fields. - */ - @NonNull - public PullAtomMetadata build() { - return new PullAtomMetadata(mCoolDownMillis, mTimeoutMillis, mAdditiveFields); - } - } - - /** - * Return the cool down time of this pull in milliseconds. - */ - public long getCoolDownMillis() { - return mCoolDownMillis; - } - - /** - * Return the maximum amount of time this pull can take in milliseconds. - */ - public long getTimeoutMillis() { - return mTimeoutMillis; - } - - /** - * Return the additive fields of this pulled atom. - * - * This is only applicable for atoms that have a uid field. When tasks are run in - * isolated processes, the data will be attributed to the host uid. Additive fields - * will be combined when the non-additive fields are the same. - */ - @Nullable - public int[] getAdditiveFields() { - return mAdditiveFields; - } - } - - /** - * Callback interface for pulling atoms requested by the stats service. - * - */ - public interface StatsPullAtomCallback { - /** - * Pull data for the specified atom tag, filling in the provided list of StatsEvent data. - * @return {@link #PULL_SUCCESS} if the pull was successful, or {@link #PULL_SKIP} if not. - */ - int onPullAtom(int atomTag, @NonNull List<StatsEvent> data); - } - - @GuardedBy("sLock") - private IStatsManagerService getIStatsManagerServiceLocked() { - if (mStatsManagerService != null) { - return mStatsManagerService; - } - mStatsManagerService = IStatsManagerService.Stub.asInterface( - StatsFrameworkInitializer - .getStatsServiceManager() - .getStatsManagerServiceRegisterer() - .get()); - return mStatsManagerService; - } - - /** - * Exception thrown when communication with the stats service fails (eg if it is not available). - * This might be thrown early during boot before the stats service has started or if it crashed. - */ - public static class StatsUnavailableException extends AndroidException { - public StatsUnavailableException(String reason) { - super("Failed to connect to statsd: " + reason); - } - - public StatsUnavailableException(String reason, Throwable e) { - super("Failed to connect to statsd: " + reason, e); - } - } -} diff --git a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java b/apex/statsd/framework/java/android/os/StatsDimensionsValue.java deleted file mode 100644 index 7d9349cefa48..000000000000 --- a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2018 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.os; - -import android.annotation.SystemApi; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; - -/** - * Container for statsd dimension value information, corresponding to a - * stats_log.proto's DimensionValue. - * - * This consists of a field (an int representing a statsd atom field) - * and a value (which may be one of a number of types). - * - * <p> - * Only a single value is held, and it is necessarily one of the following types: - * {@link String}, int, long, boolean, float, - * or tuple (i.e. {@link List} of {@code StatsDimensionsValue}). - * - * The type of value held can be retrieved using {@link #getValueType()}, which returns one of the - * following ints, depending on the type of value: - * <ul> - * <li>{@link #STRING_VALUE_TYPE}</li> - * <li>{@link #INT_VALUE_TYPE}</li> - * <li>{@link #LONG_VALUE_TYPE}</li> - * <li>{@link #BOOLEAN_VALUE_TYPE}</li> - * <li>{@link #FLOAT_VALUE_TYPE}</li> - * <li>{@link #TUPLE_VALUE_TYPE}</li> - * </ul> - * Alternatively, this can be determined using {@link #isValueType(int)} with one of these constants - * as a parameter. - * The value itself can be retrieved using the correct get...Value() function for its type. - * - * <p> - * The field is always an int, and always exists; it can be obtained using {@link #getField()}. - * - * - * @hide - */ -@SystemApi -public final class StatsDimensionsValue implements Parcelable { - private static final String TAG = "StatsDimensionsValue"; - - // Values of the value type correspond to stats_log.proto's DimensionValue fields. - // Keep constants in sync with frameworks/base/cmds/statsd/src/HashableDimensionKey.cpp. - /** Indicates that this holds a String. */ - public static final int STRING_VALUE_TYPE = 2; - /** Indicates that this holds an int. */ - public static final int INT_VALUE_TYPE = 3; - /** Indicates that this holds a long. */ - public static final int LONG_VALUE_TYPE = 4; - /** Indicates that this holds a boolean. */ - public static final int BOOLEAN_VALUE_TYPE = 5; - /** Indicates that this holds a float. */ - public static final int FLOAT_VALUE_TYPE = 6; - /** Indicates that this holds a List of StatsDimensionsValues. */ - public static final int TUPLE_VALUE_TYPE = 7; - - private final StatsDimensionsValueParcel mInner; - - /** - * Creates a {@code StatsDimensionValue} from a parcel. - * - * @hide - */ - public StatsDimensionsValue(Parcel in) { - mInner = StatsDimensionsValueParcel.CREATOR.createFromParcel(in); - } - - /** - * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel - * - * @hide - */ - public StatsDimensionsValue(StatsDimensionsValueParcel parcel) { - mInner = parcel; - } - - /** - * Return the field, i.e. the tag of a statsd atom. - * - * @return the field - */ - public int getField() { - return mInner.field; - } - - /** - * Retrieve the String held, if any. - * - * @return the {@link String} held if {@link #getValueType()} == {@link #STRING_VALUE_TYPE}, - * null otherwise - */ - public String getStringValue() { - if (mInner.valueType == STRING_VALUE_TYPE) { - return mInner.stringValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not string."); - return null; - } - } - - /** - * Retrieve the int held, if any. - * - * @return the int held if {@link #getValueType()} == {@link #INT_VALUE_TYPE}, 0 otherwise - */ - public int getIntValue() { - if (mInner.valueType == INT_VALUE_TYPE) { - return mInner.intValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not int."); - return 0; - } - } - - /** - * Retrieve the long held, if any. - * - * @return the long held if {@link #getValueType()} == {@link #LONG_VALUE_TYPE}, 0 otherwise - */ - public long getLongValue() { - if (mInner.valueType == LONG_VALUE_TYPE) { - return mInner.longValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not long."); - return 0; - } - } - - /** - * Retrieve the boolean held, if any. - * - * @return the boolean held if {@link #getValueType()} == {@link #BOOLEAN_VALUE_TYPE}, - * false otherwise - */ - public boolean getBooleanValue() { - if (mInner.valueType == BOOLEAN_VALUE_TYPE) { - return mInner.boolValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not boolean."); - return false; - } - } - - /** - * Retrieve the float held, if any. - * - * @return the float held if {@link #getValueType()} == {@link #FLOAT_VALUE_TYPE}, 0 otherwise - */ - public float getFloatValue() { - if (mInner.valueType == FLOAT_VALUE_TYPE) { - return mInner.floatValue; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not float."); - return 0; - } - } - - /** - * Retrieve the tuple, in the form of a {@link List} of {@link StatsDimensionsValue}, held, - * if any. - * - * @return the {@link List} of {@link StatsDimensionsValue} held - * if {@link #getValueType()} == {@link #TUPLE_VALUE_TYPE}, - * null otherwise - */ - public List<StatsDimensionsValue> getTupleValueList() { - if (mInner.valueType == TUPLE_VALUE_TYPE) { - int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; - List<StatsDimensionsValue> tupleValues = new ArrayList<>(length); - for (int i = 0; i < length; i++) { - tupleValues.add(new StatsDimensionsValue(mInner.tupleValue[i])); - } - return tupleValues; - } else { - Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not tuple."); - return null; - } - } - - /** - * Returns the constant representing the type of value stored, namely one of - * <ul> - * <li>{@link #STRING_VALUE_TYPE}</li> - * <li>{@link #INT_VALUE_TYPE}</li> - * <li>{@link #LONG_VALUE_TYPE}</li> - * <li>{@link #BOOLEAN_VALUE_TYPE}</li> - * <li>{@link #FLOAT_VALUE_TYPE}</li> - * <li>{@link #TUPLE_VALUE_TYPE}</li> - * </ul> - * - * @return the constant representing the type of value stored - */ - public int getValueType() { - return mInner.valueType; - } - - /** - * Returns whether the type of value stored is equal to the given type. - * - * @param valueType int representing the type of value stored, as used in {@link #getValueType} - * @return true if {@link #getValueType()} is equal to {@code valueType}. - */ - public boolean isValueType(int valueType) { - return mInner.valueType == valueType; - } - - /** - * Returns a String representing the information in this StatsDimensionValue. - * No guarantees are made about the format of this String. - * - * @return String representation - * - * @hide - */ - // Follows the format of statsd's dimension.h toString. - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(mInner.field); - sb.append(":"); - switch (mInner.valueType) { - case STRING_VALUE_TYPE: - sb.append(mInner.stringValue); - break; - case INT_VALUE_TYPE: - sb.append(String.valueOf(mInner.intValue)); - break; - case LONG_VALUE_TYPE: - sb.append(String.valueOf(mInner.longValue)); - break; - case BOOLEAN_VALUE_TYPE: - sb.append(String.valueOf(mInner.boolValue)); - break; - case FLOAT_VALUE_TYPE: - sb.append(String.valueOf(mInner.floatValue)); - break; - case TUPLE_VALUE_TYPE: - sb.append("{"); - int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; - for (int i = 0; i < length; i++) { - StatsDimensionsValue child = new StatsDimensionsValue(mInner.tupleValue[i]); - sb.append(child.toString()); - sb.append("|"); - } - sb.append("}"); - break; - default: - Log.w(TAG, "Incorrect value type"); - break; - } - return sb.toString(); - } - - /** - * Parcelable Creator for StatsDimensionsValue. - */ - public static final @android.annotation.NonNull - Parcelable.Creator<StatsDimensionsValue> CREATOR = new - Parcelable.Creator<StatsDimensionsValue>() { - public StatsDimensionsValue createFromParcel(Parcel in) { - return new StatsDimensionsValue(in); - } - - public StatsDimensionsValue[] newArray(int size) { - return new StatsDimensionsValue[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - mInner.writeToParcel(out, flags); - } - - /** - * Returns a string representation of the type of value stored. - */ - private String getValueTypeAsString() { - switch (mInner.valueType) { - case STRING_VALUE_TYPE: - return "string"; - case INT_VALUE_TYPE: - return "int"; - case LONG_VALUE_TYPE: - return "long"; - case BOOLEAN_VALUE_TYPE: - return "boolean"; - case FLOAT_VALUE_TYPE: - return "float"; - case TUPLE_VALUE_TYPE: - return "tuple"; - default: - return "unknown"; - } - } -} diff --git a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java b/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java deleted file mode 100644 index 8dc91239c2e0..000000000000 --- a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2020 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.os; - -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.annotation.SystemApi.Client; -import android.app.StatsManager; -import android.app.SystemServiceRegistry; -import android.content.Context; - -/** - * Class for performing registration for all stats services - * - * @hide - */ -@SystemApi(client = Client.MODULE_LIBRARIES) -public class StatsFrameworkInitializer { - private StatsFrameworkInitializer() { - } - - private static volatile StatsServiceManager sStatsServiceManager; - - /** - * Sets an instance of {@link StatsServiceManager} that allows - * the statsd mainline module to register/obtain stats binder services. This is called - * by the platform during the system initialization. - * - * @param statsServiceManager instance of {@link StatsServiceManager} that allows - * the statsd mainline module to register/obtain statsd binder services. - */ - public static void setStatsServiceManager( - @NonNull StatsServiceManager statsServiceManager) { - if (sStatsServiceManager != null) { - throw new IllegalStateException("setStatsServiceManager called twice!"); - } - - if (statsServiceManager == null) { - throw new NullPointerException("statsServiceManager is null"); - } - - sStatsServiceManager = statsServiceManager; - } - - /** @hide */ - public static StatsServiceManager getStatsServiceManager() { - return sStatsServiceManager; - } - - /** - * Called by {@link SystemServiceRegistry}'s static initializer and registers all statsd - * services to {@link Context}, so that {@link Context#getSystemService} can return them. - * - * @throws IllegalStateException if this is called from anywhere besides - * {@link SystemServiceRegistry} - */ - public static void registerServiceWrappers() { - SystemServiceRegistry.registerContextAwareService( - Context.STATS_MANAGER, - StatsManager.class, - context -> new StatsManager(context) - ); - } -} diff --git a/apex/statsd/framework/java/android/util/StatsEvent.java b/apex/statsd/framework/java/android/util/StatsEvent.java deleted file mode 100644 index 8be5c63f31e3..000000000000 --- a/apex/statsd/framework/java/android/util/StatsEvent.java +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Copyright (C) 2019 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.util; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.SystemClock; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Arrays; - -/** - * StatsEvent builds and stores the buffer sent over the statsd socket. - * This class defines and encapsulates the socket protocol. - * - * <p>Usage:</p> - * <pre> - * // Pushed event - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeBoolean(false) - * .writeString("annotated String field") - * .addBooleanAnnotation(annotationId, true) - * .usePooledBuffer() - * .build(); - * StatsLog.write(statsEvent); - * - * // Pulled event - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeBoolean(false) - * .writeString("annotated String field") - * .addBooleanAnnotation(annotationId, true) - * .build(); - * </pre> - * @hide - **/ -@SystemApi -public final class StatsEvent { - // Type Ids. - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_INT = 0x00; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_LONG = 0x01; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_STRING = 0x02; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_LIST = 0x03; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_FLOAT = 0x04; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_BOOLEAN = 0x05; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_BYTE_ARRAY = 0x06; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_OBJECT = 0x07; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_KEY_VALUE_PAIRS = 0x08; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_ERRORS = 0x0F; - - // Error flags. - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_NO_TIMESTAMP = 0x1; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_NO_ATOM_ID = 0x2; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_OVERFLOW = 0x4; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_INVALID_ANNOTATION_ID = 0x40; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_FIELDS = 0x200; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000; - - // Size limits. - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_ANNOTATION_COUNT = 15; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_ATTRIBUTION_NODES = 127; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_NUM_ELEMENTS = 127; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_KEY_VALUE_PAIRS = 127; - - private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068; - - // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag. - // See android_util_StatsLog.cpp. - private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4; - - private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB - - private final int mAtomId; - private final byte[] mPayload; - private Buffer mBuffer; - private final int mNumBytes; - - private StatsEvent(final int atomId, @Nullable final Buffer buffer, - @NonNull final byte[] payload, final int numBytes) { - mAtomId = atomId; - mBuffer = buffer; - mPayload = payload; - mNumBytes = numBytes; - } - - /** - * Returns a new StatsEvent.Builder for building StatsEvent object. - **/ - @NonNull - public static StatsEvent.Builder newBuilder() { - return new StatsEvent.Builder(Buffer.obtain()); - } - - /** - * Get the atom Id of the atom encoded in this StatsEvent object. - * - * @hide - **/ - public int getAtomId() { - return mAtomId; - } - - /** - * Get the byte array that contains the encoded payload that can be sent to statsd. - * - * @hide - **/ - @NonNull - public byte[] getBytes() { - return mPayload; - } - - /** - * Get the number of bytes used to encode the StatsEvent payload. - * - * @hide - **/ - public int getNumBytes() { - return mNumBytes; - } - - /** - * Recycle resources used by this StatsEvent object. - * No actions should be taken on this StatsEvent after release() is called. - * - * @hide - **/ - public void release() { - if (mBuffer != null) { - mBuffer.release(); - mBuffer = null; - } - } - - /** - * Builder for constructing a StatsEvent object. - * - * <p>This class defines and encapsulates the socket encoding for the buffer. - * The write methods must be called in the same order as the order of fields in the - * atom definition.</p> - * - * <p>setAtomId() can be called anytime before build().</p> - * - * <p>Example:</p> - * <pre> - * // Atom definition. - * message MyAtom { - * optional int32 field1 = 1; - * optional int64 field2 = 2; - * optional string field3 = 3 [(annotation1) = true]; - * } - * - * // StatsEvent construction for pushed event. - * StatsEvent.newBuilder() - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeInt(3) // field1 - * .writeLong(8L) // field2 - * .writeString("foo") // field 3 - * .addBooleanAnnotation(annotation1Id, true) - * .usePooledBuffer() - * .build(); - * - * // StatsEvent construction for pulled event. - * StatsEvent.newBuilder() - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeInt(3) // field1 - * .writeLong(8L) // field2 - * .writeString("foo") // field 3 - * .addBooleanAnnotation(annotation1Id, true) - * .build(); - * </pre> - **/ - public static final class Builder { - // Fixed positions. - private static final int POS_NUM_ELEMENTS = 1; - private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES; - private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES; - - private final Buffer mBuffer; - private long mTimestampNs; - private int mAtomId; - private byte mCurrentAnnotationCount; - private int mPos; - private int mPosLastField; - private byte mLastType; - private int mNumElements; - private int mErrorMask; - private boolean mUsePooledBuffer = false; - - private Builder(final Buffer buffer) { - mBuffer = buffer; - mCurrentAnnotationCount = 0; - mAtomId = 0; - mTimestampNs = SystemClock.elapsedRealtimeNanos(); - mNumElements = 0; - - // Set mPos to 0 for writing TYPE_OBJECT at 0th position. - mPos = 0; - writeTypeId(TYPE_OBJECT); - - // Write timestamp. - mPos = POS_TIMESTAMP_NS; - writeLong(mTimestampNs); - } - - /** - * Sets the atom id for this StatsEvent. - * - * This should be called immediately after StatsEvent.newBuilder() - * and should only be called once. - * Not calling setAtomId will result in ERROR_NO_ATOM_ID. - * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION. - **/ - @NonNull - public Builder setAtomId(final int atomId) { - if (0 == mAtomId) { - mAtomId = atomId; - - if (1 == mNumElements) { // Only timestamp is written so far. - writeInt(atomId); - } else { - // setAtomId called out of order. - mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION; - } - } - - return this; - } - - /** - * Write a boolean field to this StatsEvent. - **/ - @NonNull - public Builder writeBoolean(final boolean value) { - // Write boolean typeId byte followed by boolean byte representation. - writeTypeId(TYPE_BOOLEAN); - mPos += mBuffer.putBoolean(mPos, value); - mNumElements++; - return this; - } - - /** - * Write an integer field to this StatsEvent. - **/ - @NonNull - public Builder writeInt(final int value) { - // Write integer typeId byte followed by 4-byte representation of value. - writeTypeId(TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a long field to this StatsEvent. - **/ - @NonNull - public Builder writeLong(final long value) { - // Write long typeId byte followed by 8-byte representation of value. - writeTypeId(TYPE_LONG); - mPos += mBuffer.putLong(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a float field to this StatsEvent. - **/ - @NonNull - public Builder writeFloat(final float value) { - // Write float typeId byte followed by 4-byte representation of value. - writeTypeId(TYPE_FLOAT); - mPos += mBuffer.putFloat(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a String field to this StatsEvent. - **/ - @NonNull - public Builder writeString(@NonNull final String value) { - // Write String typeId byte, followed by 4-byte representation of number of bytes - // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value. - final byte[] valueBytes = stringToBytes(value); - writeByteArray(valueBytes, TYPE_STRING); - return this; - } - - /** - * Write a byte array field to this StatsEvent. - **/ - @NonNull - public Builder writeByteArray(@NonNull final byte[] value) { - // Write byte array typeId byte, followed by 4-byte representation of number of bytes - // in value, followed by the actual byte array. - writeByteArray(value, TYPE_BYTE_ARRAY); - return this; - } - - private void writeByteArray(@NonNull final byte[] value, final byte typeId) { - writeTypeId(typeId); - final int numBytes = value.length; - mPos += mBuffer.putInt(mPos, numBytes); - mPos += mBuffer.putByteArray(mPos, value); - mNumElements++; - } - - /** - * Write an attribution chain field to this StatsEvent. - * - * The sizes of uids and tags must be equal. The AttributionNode at position i is - * made up of uids[i] and tags[i]. - * - * @param uids array of uids in the attribution nodes. - * @param tags array of tags in the attribution nodes. - **/ - @NonNull - public Builder writeAttributionChain( - @NonNull final int[] uids, @NonNull final String[] tags) { - final byte numUids = (byte) uids.length; - final byte numTags = (byte) tags.length; - - if (numUids != numTags) { - mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL; - } else if (numUids > MAX_ATTRIBUTION_NODES) { - mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG; - } else { - // Write attribution chain typeId byte, followed by 1-byte representation of - // number of attribution nodes, followed by encoding of each attribution node. - writeTypeId(TYPE_ATTRIBUTION_CHAIN); - mPos += mBuffer.putByte(mPos, numUids); - for (int i = 0; i < numUids; i++) { - // Each uid is encoded as 4-byte representation of its int value. - mPos += mBuffer.putInt(mPos, uids[i]); - - // Each tag is encoded as 4-byte representation of number of bytes in its - // UTF-8 encoding, followed by the actual UTF-8 bytes. - final byte[] tagBytes = stringToBytes(tags[i]); - mPos += mBuffer.putInt(mPos, tagBytes.length); - mPos += mBuffer.putByteArray(mPos, tagBytes); - } - mNumElements++; - } - return this; - } - - /** - * Write KeyValuePairsAtom entries to this StatsEvent. - * - * @param intMap Integer key-value pairs. - * @param longMap Long key-value pairs. - * @param stringMap String key-value pairs. - * @param floatMap Float key-value pairs. - **/ - @NonNull - public Builder writeKeyValuePairs( - @Nullable final SparseIntArray intMap, - @Nullable final SparseLongArray longMap, - @Nullable final SparseArray<String> stringMap, - @Nullable final SparseArray<Float> floatMap) { - final int intMapSize = null == intMap ? 0 : intMap.size(); - final int longMapSize = null == longMap ? 0 : longMap.size(); - final int stringMapSize = null == stringMap ? 0 : stringMap.size(); - final int floatMapSize = null == floatMap ? 0 : floatMap.size(); - final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize; - - if (totalCount > MAX_KEY_VALUE_PAIRS) { - mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS; - } else { - writeTypeId(TYPE_KEY_VALUE_PAIRS); - mPos += mBuffer.putByte(mPos, (byte) totalCount); - - for (int i = 0; i < intMapSize; i++) { - final int key = intMap.keyAt(i); - final int value = intMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - } - - for (int i = 0; i < longMapSize; i++) { - final int key = longMap.keyAt(i); - final long value = longMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_LONG); - mPos += mBuffer.putLong(mPos, value); - } - - for (int i = 0; i < stringMapSize; i++) { - final int key = stringMap.keyAt(i); - final String value = stringMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_STRING); - final byte[] valueBytes = stringToBytes(value); - mPos += mBuffer.putInt(mPos, valueBytes.length); - mPos += mBuffer.putByteArray(mPos, valueBytes); - } - - for (int i = 0; i < floatMapSize; i++) { - final int key = floatMap.keyAt(i); - final float value = floatMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_FLOAT); - mPos += mBuffer.putFloat(mPos, value); - } - - mNumElements++; - } - - return this; - } - - /** - * Write a boolean annotation for the last field written. - **/ - @NonNull - public Builder addBooleanAnnotation( - final byte annotationId, final boolean value) { - // Ensure there's a field written to annotate. - if (mNumElements < 2) { - mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { - mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; - } else { - mPos += mBuffer.putByte(mPos, annotationId); - mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN); - mPos += mBuffer.putBoolean(mPos, value); - mCurrentAnnotationCount++; - writeAnnotationCount(); - } - - return this; - } - - /** - * Write an integer annotation for the last field written. - **/ - @NonNull - public Builder addIntAnnotation(final byte annotationId, final int value) { - if (mNumElements < 2) { - mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { - mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; - } else { - mPos += mBuffer.putByte(mPos, annotationId); - mPos += mBuffer.putByte(mPos, TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - mCurrentAnnotationCount++; - writeAnnotationCount(); - } - - return this; - } - - /** - * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent. - * This should be called for pushed events to reduce memory allocations and garbage - * collections. - **/ - @NonNull - public Builder usePooledBuffer() { - mUsePooledBuffer = true; - mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos); - return this; - } - - /** - * Builds a StatsEvent object with values entered in this Builder. - **/ - @NonNull - public StatsEvent build() { - if (0L == mTimestampNs) { - mErrorMask |= ERROR_NO_TIMESTAMP; - } - if (0 == mAtomId) { - mErrorMask |= ERROR_NO_ATOM_ID; - } - if (mBuffer.hasOverflowed()) { - mErrorMask |= ERROR_OVERFLOW; - } - if (mNumElements > MAX_NUM_ELEMENTS) { - mErrorMask |= ERROR_TOO_MANY_FIELDS; - } - - if (0 == mErrorMask) { - mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements); - } else { - // Write atom id and error mask. Overwrite any annotations for atom Id. - mPos = POS_ATOM_ID; - mPos += mBuffer.putByte(mPos, TYPE_INT); - mPos += mBuffer.putInt(mPos, mAtomId); - mPos += mBuffer.putByte(mPos, TYPE_ERRORS); - mPos += mBuffer.putInt(mPos, mErrorMask); - mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3); - } - - final int size = mPos; - - if (mUsePooledBuffer) { - return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size); - } else { - // Create a copy of the buffer with the required number of bytes. - final byte[] payload = new byte[size]; - System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size); - - // Return Buffer instance to the pool. - mBuffer.release(); - - return new StatsEvent(mAtomId, null, payload, size); - } - } - - private void writeTypeId(final byte typeId) { - mPosLastField = mPos; - mLastType = typeId; - mCurrentAnnotationCount = 0; - final byte encodedId = (byte) (typeId & 0x0F); - mPos += mBuffer.putByte(mPos, encodedId); - } - - private void writeAnnotationCount() { - // Use first 4 bits for annotation count and last 4 bits for typeId. - final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F)); - mBuffer.putByte(mPosLastField, encodedId); - } - - @NonNull - private static byte[] stringToBytes(@Nullable final String value) { - return (null == value ? "" : value).getBytes(UTF_8); - } - } - - private static final class Buffer { - private static Object sLock = new Object(); - - @GuardedBy("sLock") - private static Buffer sPool; - - private byte[] mBytes = new byte[MAX_PUSH_PAYLOAD_SIZE]; - private boolean mOverflow = false; - private int mMaxSize = MAX_PULL_PAYLOAD_SIZE; - - @NonNull - private static Buffer obtain() { - final Buffer buffer; - synchronized (sLock) { - buffer = null == sPool ? new Buffer() : sPool; - sPool = null; - } - buffer.reset(); - return buffer; - } - - private Buffer() { - } - - @NonNull - private byte[] getBytes() { - return mBytes; - } - - private void release() { - // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under. - if (mBytes.length <= MAX_PUSH_PAYLOAD_SIZE) { - synchronized (sLock) { - if (null == sPool) { - sPool = this; - } - } - } - } - - private void reset() { - mOverflow = false; - mMaxSize = MAX_PULL_PAYLOAD_SIZE; - } - - private void setMaxSize(final int maxSize, final int numBytesWritten) { - mMaxSize = maxSize; - if (numBytesWritten > maxSize) { - mOverflow = true; - } - } - - private boolean hasOverflowed() { - return mOverflow; - } - - /** - * Checks for available space in the byte array. - * - * @param index starting position in the buffer to start the check. - * @param numBytes number of bytes to check from index. - * @return true if space is available, false otherwise. - **/ - private boolean hasEnoughSpace(final int index, final int numBytes) { - final int totalBytesNeeded = index + numBytes; - - if (totalBytesNeeded > mMaxSize) { - mOverflow = true; - return false; - } - - // Expand buffer if needed. - if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) { - int newSize = mBytes.length; - do { - newSize *= 2; - } while (newSize <= totalBytesNeeded); - - if (newSize > mMaxSize) { - newSize = mMaxSize; - } - - mBytes = Arrays.copyOf(mBytes, newSize); - } - - return true; - } - - /** - * Writes a byte into the buffer. - * - * @param index position in the buffer where the byte is written. - * @param value the byte to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putByte(final int index, final byte value) { - if (hasEnoughSpace(index, Byte.BYTES)) { - mBytes[index] = (byte) (value); - return Byte.BYTES; - } - return 0; - } - - /** - * Writes a boolean into the buffer. - * - * @param index position in the buffer where the boolean is written. - * @param value the boolean to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putBoolean(final int index, final boolean value) { - return putByte(index, (byte) (value ? 1 : 0)); - } - - /** - * Writes an integer into the buffer. - * - * @param index position in the buffer where the integer is written. - * @param value the integer to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putInt(final int index, final int value) { - if (hasEnoughSpace(index, Integer.BYTES)) { - // Use little endian byte order. - mBytes[index] = (byte) (value); - mBytes[index + 1] = (byte) (value >> 8); - mBytes[index + 2] = (byte) (value >> 16); - mBytes[index + 3] = (byte) (value >> 24); - return Integer.BYTES; - } - return 0; - } - - /** - * Writes a long into the buffer. - * - * @param index position in the buffer where the long is written. - * @param value the long to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putLong(final int index, final long value) { - if (hasEnoughSpace(index, Long.BYTES)) { - // Use little endian byte order. - mBytes[index] = (byte) (value); - mBytes[index + 1] = (byte) (value >> 8); - mBytes[index + 2] = (byte) (value >> 16); - mBytes[index + 3] = (byte) (value >> 24); - mBytes[index + 4] = (byte) (value >> 32); - mBytes[index + 5] = (byte) (value >> 40); - mBytes[index + 6] = (byte) (value >> 48); - mBytes[index + 7] = (byte) (value >> 56); - return Long.BYTES; - } - return 0; - } - - /** - * Writes a float into the buffer. - * - * @param index position in the buffer where the float is written. - * @param value the float to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putFloat(final int index, final float value) { - return putInt(index, Float.floatToIntBits(value)); - } - - /** - * Copies a byte array into the buffer. - * - * @param index position in the buffer where the byte array is copied. - * @param value the byte array to copy. - * @return number of bytes written to buffer from this write operation. - **/ - private int putByteArray(final int index, @NonNull final byte[] value) { - final int numBytes = value.length; - if (hasEnoughSpace(index, numBytes)) { - System.arraycopy(value, 0, mBytes, index, numBytes); - return numBytes; - } - return 0; - } - } -} diff --git a/apex/statsd/framework/java/android/util/StatsLog.java b/apex/statsd/framework/java/android/util/StatsLog.java deleted file mode 100644 index 0a9f4ebabdf0..000000000000 --- a/apex/statsd/framework/java/android/util/StatsLog.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2017 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.util; - -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.PACKAGE_USAGE_STATS; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.content.Context; -import android.os.IStatsd; -import android.os.Process; -import android.util.proto.ProtoOutputStream; - -import com.android.internal.statsd.StatsdStatsLog; - -/** - * StatsLog provides an API for developers to send events to statsd. The events can be used to - * define custom metrics inside statsd. - */ -public final class StatsLog { - - // Load JNI library - static { - System.loadLibrary("stats_jni"); - } - private static final String TAG = "StatsLog"; - private static final boolean DEBUG = false; - private static final int EXPERIMENT_IDS_FIELD_ID = 1; - - private StatsLog() { - } - - /** - * Logs a start event. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logStart(int label) { - int callingUid = Process.myUid(); - StatsdStatsLog.write( - StatsdStatsLog.APP_BREADCRUMB_REPORTED, - callingUid, - label, - StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START); - return true; - } - - /** - * Logs a stop event. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logStop(int label) { - int callingUid = Process.myUid(); - StatsdStatsLog.write( - StatsdStatsLog.APP_BREADCRUMB_REPORTED, - callingUid, - label, - StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP); - return true; - } - - /** - * Logs an event that does not represent a start or stop boundary. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logEvent(int label) { - int callingUid = Process.myUid(); - StatsdStatsLog.write( - StatsdStatsLog.APP_BREADCRUMB_REPORTED, - callingUid, - label, - StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED); - return true; - } - - /** - * Logs an event for binary push for module updates. - * - * @param trainName name of install train. - * @param trainVersionCode version code of the train. - * @param options optional flags about this install. - * The last 3 bits indicate options: - * 0x01: FLAG_REQUIRE_STAGING - * 0x02: FLAG_ROLLBACK_ENABLED - * 0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR - * @param state current install state. Defined as State enums in - * BinaryPushStateChanged atom in - * frameworks/base/cmds/statsd/src/atoms.proto - * @param experimentIds experiment ids. - * @return True if the log request was sent to statsd. - */ - @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS}) - public static boolean logBinaryPushStateChanged(@NonNull String trainName, - long trainVersionCode, int options, int state, - @NonNull long[] experimentIds) { - ProtoOutputStream proto = new ProtoOutputStream(); - for (long id : experimentIds) { - proto.write( - ProtoOutputStream.FIELD_TYPE_INT64 - | ProtoOutputStream.FIELD_COUNT_REPEATED - | EXPERIMENT_IDS_FIELD_ID, - id); - } - StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED, - trainName, - trainVersionCode, - (options & IStatsd.FLAG_REQUIRE_STAGING) > 0, - (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0, - (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0, - state, - proto.getBytes(), - 0, - 0, - false); - return true; - } - - /** - * Write an event to stats log using the raw format. - * - * @param buffer The encoded buffer of data to write. - * @param size The number of bytes from the buffer to write. - * @hide - */ - // TODO(b/144935988): Mark deprecated. - @SystemApi - public static void writeRaw(@NonNull byte[] buffer, int size) { - // TODO(b/144935988): make this no-op once clients have migrated to StatsEvent. - writeImpl(buffer, size, 0); - } - - /** - * Write an event to stats log using the raw format. - * - * @param buffer The encoded buffer of data to write. - * @param size The number of bytes from the buffer to write. - * @param atomId The id of the atom to which the event belongs. - */ - private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId); - - /** - * Write an event to stats log using the raw format encapsulated in StatsEvent. - * After writing to stats log, release() is called on the StatsEvent object. - * No further action should be taken on the StatsEvent object following this call. - * - * @param statsEvent The StatsEvent object containing the encoded buffer of data to write. - * @hide - */ - @SystemApi - public static void write(@NonNull final StatsEvent statsEvent) { - writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId()); - statsEvent.release(); - } - - private static void enforceDumpCallingPermission(Context context) { - context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission."); - } - - private static void enforcesageStatsCallingPermission(Context context) { - context.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, - "Need PACKAGE_USAGE_STATS permission."); - } -} diff --git a/apex/statsd/framework/test/Android.bp b/apex/statsd/framework/test/Android.bp deleted file mode 100644 index b113d595b57c..000000000000 --- a/apex/statsd/framework/test/Android.bp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2020 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. - -android_test { - name: "FrameworkStatsdTest", - platform_apis: true, - srcs: [ - // TODO(b/147705194): Use framework-statsd as a lib dependency instead. - ":framework-statsd-sources", - "**/*.java", - ], - manifest: "AndroidManifest.xml", - static_libs: [ - "androidx.test.rules", - "truth-prebuilt", - ], - libs: [ - "android.test.runner.stubs", - "android.test.base.stubs", - ], - test_suites: [ - "device-tests", - "mts", - ], -}
\ No newline at end of file diff --git a/apex/statsd/framework/test/AndroidManifest.xml b/apex/statsd/framework/test/AndroidManifest.xml deleted file mode 100644 index 8f89d2332b12..000000000000 --- a/apex/statsd/framework/test/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.os.statsd.framework.test" - > - - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.os.statsd.framework.test" - android:label="Framework Statsd Tests" /> - -</manifest> diff --git a/apex/statsd/framework/test/AndroidTest.xml b/apex/statsd/framework/test/AndroidTest.xml deleted file mode 100644 index fb519150ecd5..000000000000 --- a/apex/statsd/framework/test/AndroidTest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 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. ---> -<configuration description="Runs Tests for Statsd."> - <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> - <option name="test-file-name" value="FrameworkStatsdTest.apk" /> - <option name="install-arg" value="-g" /> - </target_preparer> - - <option name="test-suite-tag" value="apct" /> - <option name="test-suite-tag" value="mts" /> - <option name="test-tag" value="FrameworkStatsdTest" /> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.os.statsd.framework.test" /> - <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> - <option name="hidden-api-checks" value="false"/> - </test> - - <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.os.statsd" /> - </object> -</configuration>
\ No newline at end of file diff --git a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java b/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java deleted file mode 100644 index fd386bd8e32e..000000000000 --- a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019 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.app; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.StatsManager.PullAtomMetadata; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public final class PullAtomMetadataTest { - - @Test - public void testEmpty() { - PullAtomMetadata metadata = new PullAtomMetadata.Builder().build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS); - assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS); - assertThat(metadata.getAdditiveFields()).isNull(); - } - - @Test - public void testSetTimeoutMillis() { - long timeoutMillis = 500L; - PullAtomMetadata metadata = - new PullAtomMetadata.Builder().setTimeoutMillis(timeoutMillis).build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis); - assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS); - assertThat(metadata.getAdditiveFields()).isNull(); - } - - @Test - public void testSetCoolDownMillis() { - long coolDownMillis = 10_000L; - PullAtomMetadata metadata = - new PullAtomMetadata.Builder().setCoolDownMillis(coolDownMillis).build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS); - assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis); - assertThat(metadata.getAdditiveFields()).isNull(); - } - - @Test - public void testSetAdditiveFields() { - int[] fields = {2, 4, 6}; - PullAtomMetadata metadata = - new PullAtomMetadata.Builder().setAdditiveFields(fields).build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS); - assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS); - assertThat(metadata.getAdditiveFields()).isEqualTo(fields); - } - - @Test - public void testSetAllElements() { - long timeoutMillis = 300L; - long coolDownMillis = 9572L; - int[] fields = {3, 2}; - PullAtomMetadata metadata = new PullAtomMetadata.Builder() - .setTimeoutMillis(timeoutMillis) - .setCoolDownMillis(coolDownMillis) - .setAdditiveFields(fields) - .build(); - assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis); - assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis); - assertThat(metadata.getAdditiveFields()).isEqualTo(fields); - } -} diff --git a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java b/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java deleted file mode 100644 index db25911e6eee..000000000000 --- a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2019 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.os; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.util.List; - -@RunWith(JUnit4.class) -public final class StatsDimensionsValueTest { - - @Test - public void testConversionFromStructuredParcel() { - int tupleField = 100; // atom id - String stringValue = "Hello"; - int intValue = 123; - long longValue = 123456789L; - float floatValue = 1.1f; - boolean boolValue = true; - - // Construct structured parcel - StatsDimensionsValueParcel sdvp = new StatsDimensionsValueParcel(); - sdvp.field = tupleField; - sdvp.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; - sdvp.tupleValue = new StatsDimensionsValueParcel[5]; - - for (int i = 0; i < 5; i++) { - sdvp.tupleValue[i] = new StatsDimensionsValueParcel(); - sdvp.tupleValue[i].field = i + 1; - } - - sdvp.tupleValue[0].valueType = StatsDimensionsValue.STRING_VALUE_TYPE; - sdvp.tupleValue[1].valueType = StatsDimensionsValue.INT_VALUE_TYPE; - sdvp.tupleValue[2].valueType = StatsDimensionsValue.LONG_VALUE_TYPE; - sdvp.tupleValue[3].valueType = StatsDimensionsValue.FLOAT_VALUE_TYPE; - sdvp.tupleValue[4].valueType = StatsDimensionsValue.BOOLEAN_VALUE_TYPE; - - sdvp.tupleValue[0].stringValue = stringValue; - sdvp.tupleValue[1].intValue = intValue; - sdvp.tupleValue[2].longValue = longValue; - sdvp.tupleValue[3].floatValue = floatValue; - sdvp.tupleValue[4].boolValue = boolValue; - - // Convert to StatsDimensionsValue and check result - StatsDimensionsValue sdv = new StatsDimensionsValue(sdvp); - - assertThat(sdv.getField()).isEqualTo(tupleField); - assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); - List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); - assertThat(sdvChildren.size()).isEqualTo(5); - - for (int i = 0; i < 5; i++) { - assertThat(sdvChildren.get(i).getField()).isEqualTo(i + 1); - } - - assertThat(sdvChildren.get(0).getValueType()) - .isEqualTo(StatsDimensionsValue.STRING_VALUE_TYPE); - assertThat(sdvChildren.get(1).getValueType()) - .isEqualTo(StatsDimensionsValue.INT_VALUE_TYPE); - assertThat(sdvChildren.get(2).getValueType()) - .isEqualTo(StatsDimensionsValue.LONG_VALUE_TYPE); - assertThat(sdvChildren.get(3).getValueType()) - .isEqualTo(StatsDimensionsValue.FLOAT_VALUE_TYPE); - assertThat(sdvChildren.get(4).getValueType()) - .isEqualTo(StatsDimensionsValue.BOOLEAN_VALUE_TYPE); - - assertThat(sdvChildren.get(0).getStringValue()).isEqualTo(stringValue); - assertThat(sdvChildren.get(1).getIntValue()).isEqualTo(intValue); - assertThat(sdvChildren.get(2).getLongValue()).isEqualTo(longValue); - assertThat(sdvChildren.get(3).getFloatValue()).isEqualTo(floatValue); - assertThat(sdvChildren.get(4).getBooleanValue()).isEqualTo(boolValue); - - // Ensure that StatsDimensionsValue and StatsDimensionsValueParcel are - // parceled equivalently - Parcel sdvpParcel = Parcel.obtain(); - Parcel sdvParcel = Parcel.obtain(); - sdvp.writeToParcel(sdvpParcel, 0); - sdv.writeToParcel(sdvParcel, 0); - assertThat(sdvpParcel.dataSize()).isEqualTo(sdvParcel.dataSize()); - } - - @Test - public void testNullTupleArray() { - int tupleField = 100; // atom id - - StatsDimensionsValueParcel parcel = new StatsDimensionsValueParcel(); - parcel.field = tupleField; - parcel.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; - parcel.tupleValue = null; - - StatsDimensionsValue sdv = new StatsDimensionsValue(parcel); - assertThat(sdv.getField()).isEqualTo(tupleField); - assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); - List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); - assertThat(sdvChildren.size()).isEqualTo(0); - } -} diff --git a/apex/statsd/framework/test/src/android/util/StatsEventTest.java b/apex/statsd/framework/test/src/android/util/StatsEventTest.java deleted file mode 100644 index 8d263699d9c8..000000000000 --- a/apex/statsd/framework/test/src/android/util/StatsEventTest.java +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright (C) 2019 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.util; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import android.os.SystemClock; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.google.common.collect.Range; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Random; - -/** - * Internal tests for {@link StatsEvent}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class StatsEventTest { - - @Test - public void testNoFields() { - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder().usePooledBuffer().build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - final int expectedAtomId = 0; - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask") - .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testOnlyAtomId() { - final int expectedAtomId = 109; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(2); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testIntBooleanIntInt() { - final int expectedAtomId = 109; - final int field1 = 1; - final boolean field2 = true; - final int field3 = 3; - final int field4 = 4; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeInt(field1) - .writeBoolean(field2) - .writeInt(field3) - .writeInt(field4) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(6); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not Int") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect field 1") - .that(buffer.getInt()).isEqualTo(field1); - - assertWithMessage("Second field is not Boolean") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN); - - assertWithMessage("Incorrect field 2") - .that(buffer.get()).isEqualTo(1); - - assertWithMessage("Third field is not Int") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect field 3") - .that(buffer.getInt()).isEqualTo(field3); - - assertWithMessage("Fourth field is not Int") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect field 4") - .that(buffer.getInt()).isEqualTo(field4); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testStringFloatByteArray() { - final int expectedAtomId = 109; - final String field1 = "Str 1"; - final float field2 = 9.334f; - final byte[] field3 = new byte[] { 56, 23, 89, -120 }; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeString(field1) - .writeFloat(field2) - .writeByteArray(field3) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(5); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not String") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING); - - final String field1Actual = getStringFromByteBuffer(buffer); - assertWithMessage("Incorrect field 1") - .that(field1Actual).isEqualTo(field1); - - assertWithMessage("Second field is not Float") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT); - - assertWithMessage("Incorrect field 2") - .that(buffer.getFloat()).isEqualTo(field2); - - assertWithMessage("Third field is not byte array") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY); - - final byte[] field3Actual = getByteArrayFromByteBuffer(buffer); - assertWithMessage("Incorrect field 3") - .that(field3Actual).isEqualTo(field3); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testAttributionChainLong() { - final int expectedAtomId = 109; - final int[] uids = new int[] { 1, 2, 3, 4, 5 }; - final String[] tags = new String[] { "1", "2", "3", "4", "5" }; - final long field2 = -230909823L; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeAttributionChain(uids, tags) - .writeLong(field2) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(4); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not Attribution Chain") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN); - - assertWithMessage("Incorrect number of attribution nodes") - .that(buffer.get()).isEqualTo((byte) uids.length); - - for (int i = 0; i < tags.length; i++) { - assertWithMessage("Incorrect uid in Attribution Chain") - .that(buffer.getInt()).isEqualTo(uids[i]); - - final String tag = getStringFromByteBuffer(buffer); - assertWithMessage("Incorrect tag in Attribution Chain") - .that(tag).isEqualTo(tags[i]); - } - - assertWithMessage("Second field is not Long") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect field 2") - .that(buffer.getLong()).isEqualTo(field2); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testKeyValuePairs() { - final int expectedAtomId = 109; - final SparseIntArray intMap = new SparseIntArray(); - final SparseLongArray longMap = new SparseLongArray(); - final SparseArray<String> stringMap = new SparseArray<>(); - final SparseArray<Float> floatMap = new SparseArray<>(); - intMap.put(1, -1); - intMap.put(2, -2); - stringMap.put(3, "abc"); - stringMap.put(4, "2h"); - floatMap.put(9, -234.344f); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeKeyValuePairs(intMap, longMap, stringMap, floatMap) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("First field is not KeyValuePairs") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS); - - assertWithMessage("Incorrect number of key value pairs") - .that(buffer.get()).isEqualTo( - (byte) (intMap.size() + longMap.size() + stringMap.size() - + floatMap.size())); - - for (int i = 0; i < intMap.size(); i++) { - assertWithMessage("Incorrect key in intMap") - .that(buffer.getInt()).isEqualTo(intMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_INT in intMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Incorrect value in intMap") - .that(buffer.getInt()).isEqualTo(intMap.valueAt(i)); - } - - for (int i = 0; i < longMap.size(); i++) { - assertWithMessage("Incorrect key in longMap") - .that(buffer.getInt()).isEqualTo(longMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_LONG in longMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - assertWithMessage("Incorrect value in longMap") - .that(buffer.getLong()).isEqualTo(longMap.valueAt(i)); - } - - for (int i = 0; i < stringMap.size(); i++) { - assertWithMessage("Incorrect key in stringMap") - .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_STRING in stringMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING); - final String value = getStringFromByteBuffer(buffer); - assertWithMessage("Incorrect value in stringMap") - .that(value).isEqualTo(stringMap.valueAt(i)); - } - - for (int i = 0; i < floatMap.size(); i++) { - assertWithMessage("Incorrect key in floatMap") - .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i)); - assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT); - assertWithMessage("Incorrect value in floatMap") - .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i)); - } - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testSingleAnnotations() { - final int expectedAtomId = 109; - final int field1 = 1; - final byte field1AnnotationId = 45; - final boolean field1AnnotationValue = false; - final boolean field2 = true; - final byte field2AnnotationId = 1; - final int field2AnnotationValue = 23; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeInt(field1) - .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue) - .writeBoolean(field2) - .addIntAnnotation(field2AnnotationId, field2AnnotationValue) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(4); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - final byte field1Header = buffer.get(); - final int field1AnnotationValueCount = field1Header >> 4; - final byte field1Type = (byte) (field1Header & 0x0F); - assertWithMessage("First field is not Int") - .that(field1Type).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("First field annotation count is wrong") - .that(field1AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 1") - .that(buffer.getInt()).isEqualTo(field1); - assertWithMessage("First field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationId); - assertWithMessage("First field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("First field's annotation value is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0); - - final byte field2Header = buffer.get(); - final int field2AnnotationValueCount = field2Header >> 4; - final byte field2Type = (byte) (field2Header & 0x0F); - assertWithMessage("Second field is not boolean") - .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("Second field annotation count is wrong") - .that(field2AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 2") - .that(buffer.get()).isEqualTo(field2 ? 1 : 0); - assertWithMessage("Second field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field2AnnotationId); - assertWithMessage("Second field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Second field's annotation value is wrong") - .that(buffer.getInt()).isEqualTo(field2AnnotationValue); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testAtomIdAnnotations() { - final int expectedAtomId = 109; - final byte atomAnnotationId = 84; - final int atomAnnotationValue = 9; - final int field1 = 1; - final byte field1AnnotationId = 45; - final boolean field1AnnotationValue = false; - final boolean field2 = true; - final byte field2AnnotationId = 1; - final int field2AnnotationValue = 23; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .addIntAnnotation(atomAnnotationId, atomAnnotationValue) - .writeInt(field1) - .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue) - .writeBoolean(field2) - .addIntAnnotation(field2AnnotationId, field2AnnotationValue) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(4); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - final byte atomIdHeader = buffer.get(); - final int atomIdAnnotationValueCount = atomIdHeader >> 4; - final byte atomIdValueType = (byte) (atomIdHeader & 0x0F); - assertWithMessage("Second element is not atom id") - .that(atomIdValueType).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Atom id annotation count is wrong") - .that(atomIdAnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - assertWithMessage("Atom id's annotation id is wrong") - .that(buffer.get()).isEqualTo(atomAnnotationId); - assertWithMessage("Atom id's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Atom id's annotation value is wrong") - .that(buffer.getInt()).isEqualTo(atomAnnotationValue); - - final byte field1Header = buffer.get(); - final int field1AnnotationValueCount = field1Header >> 4; - final byte field1Type = (byte) (field1Header & 0x0F); - assertWithMessage("First field is not Int") - .that(field1Type).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("First field annotation count is wrong") - .that(field1AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 1") - .that(buffer.getInt()).isEqualTo(field1); - assertWithMessage("First field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationId); - assertWithMessage("First field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("First field's annotation value is wrong") - .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0); - - final byte field2Header = buffer.get(); - final int field2AnnotationValueCount = field2Header >> 4; - final byte field2Type = (byte) (field2Header & 0x0F); - assertWithMessage("Second field is not boolean") - .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN); - assertWithMessage("Second field annotation count is wrong") - .that(field2AnnotationValueCount).isEqualTo(1); - assertWithMessage("Incorrect field 2") - .that(buffer.get()).isEqualTo(field2 ? 1 : 0); - assertWithMessage("Second field's annotation id is wrong") - .that(buffer.get()).isEqualTo(field2AnnotationId); - assertWithMessage("Second field's annotation type is wrong") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - assertWithMessage("Second field's annotation value is wrong") - .that(buffer.getInt()).isEqualTo(field2AnnotationValue); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testSetAtomIdNotCalledImmediately() { - final int expectedAtomId = 109; - final int field1 = 25; - final boolean field2 = true; - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .writeInt(field1) - .setAtomId(expectedAtomId) - .writeBoolean(field2) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()).isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id") - .that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_ATOM_ID_INVALID_POSITION should be the only error in the mask") - .that(errorMask).isEqualTo(StatsEvent.ERROR_ATOM_ID_INVALID_POSITION); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testLargePulledEvent() { - final int expectedAtomId = 10_020; - byte[] field1 = new byte[10 * 1024]; - new Random().nextBytes(field1); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = - StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()) - .isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()) - .isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not byte array") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_BYTE_ARRAY); - - final byte[] field1Actual = getByteArrayFromByteBuffer(buffer); - assertWithMessage("Incorrect field 1").that(field1Actual).isEqualTo(field1); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testPulledEventOverflow() { - final int expectedAtomId = 10_020; - byte[] field1 = new byte[50 * 1024]; - new Random().nextBytes(field1); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = - StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()) - .isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()) - .isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask") - .that(errorMask) - .isEqualTo(StatsEvent.ERROR_OVERFLOW); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - @Test - public void testPushedEventOverflow() { - final int expectedAtomId = 10_020; - byte[] field1 = new byte[10 * 1024]; - new Random().nextBytes(field1); - - final long minTimestamp = SystemClock.elapsedRealtimeNanos(); - final StatsEvent statsEvent = StatsEvent.newBuilder() - .setAtomId(expectedAtomId) - .writeByteArray(field1) - .usePooledBuffer() - .build(); - final long maxTimestamp = SystemClock.elapsedRealtimeNanos(); - - assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId); - - final ByteBuffer buffer = - ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN); - - assertWithMessage("Root element in buffer is not TYPE_OBJECT") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_OBJECT); - - assertWithMessage("Incorrect number of elements in root object") - .that(buffer.get()) - .isEqualTo(3); - - assertWithMessage("First element is not timestamp") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_LONG); - - assertWithMessage("Incorrect timestamp") - .that(buffer.getLong()) - .isIn(Range.closed(minTimestamp, maxTimestamp)); - - assertWithMessage("Second element is not atom id") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_INT); - - assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId); - - assertWithMessage("Third element is not errors type") - .that(buffer.get()) - .isEqualTo(StatsEvent.TYPE_ERRORS); - - final int errorMask = buffer.getInt(); - - assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask") - .that(errorMask) - .isEqualTo(StatsEvent.ERROR_OVERFLOW); - - assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position()); - - statsEvent.release(); - } - - private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) { - final int numBytes = buffer.getInt(); - byte[] bytes = new byte[numBytes]; - buffer.get(bytes); - return bytes; - } - - private static String getStringFromByteBuffer(final ByteBuffer buffer) { - final byte[] bytes = getByteArrayFromByteBuffer(buffer); - return new String(bytes, UTF_8); - } -} diff --git a/apex/statsd/jni/android_util_StatsLog.cpp b/apex/statsd/jni/android_util_StatsLog.cpp deleted file mode 100644 index 71ce94923c8d..000000000000 --- a/apex/statsd/jni/android_util_StatsLog.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#define LOG_NAMESPACE "StatsLog.tag." -#define LOG_TAG "StatsLog_println" - -#include <jni.h> -#include <log/log.h> -#include <nativehelper/scoped_local_ref.h> -#include "stats_buffer_writer.h" - -namespace android { - -static void android_util_StatsLog_write(JNIEnv* env, jobject clazz, jbyteArray buf, jint size, - jint atomId) { - if (buf == NULL) { - return; - } - jint actualSize = env->GetArrayLength(buf); - if (actualSize < size) { - return; - } - - jbyte* bufferArray = env->GetByteArrayElements(buf, NULL); - if (bufferArray == NULL) { - return; - } - - write_buffer_to_statsd((void*) bufferArray, size, atomId); - - env->ReleaseByteArrayElements(buf, bufferArray, 0); -} - -/* - * JNI registration. - */ -static const JNINativeMethod gMethods[] = { - /* name, signature, funcPtr */ - { "writeImpl", "([BII)V", (void*) android_util_StatsLog_write }, -}; - -int register_android_util_StatsLog(JNIEnv* env) -{ - static const char* kStatsLogClass = "android/util/StatsLog"; - - ScopedLocalRef<jclass> cls(env, env->FindClass(kStatsLogClass)); - if (cls.get() == nullptr) { - ALOGE("jni statsd registration failure, class not found '%s'", kStatsLogClass); - return JNI_ERR; - } - - const jint count = sizeof(gMethods) / sizeof(gMethods[0]); - int status = env->RegisterNatives(cls.get(), gMethods, count); - if (status < 0) { - ALOGE("jni statsd registration failure, status: %d", status); - return JNI_ERR; - } - return JNI_VERSION_1_4; -} - -}; // namespace android - -/* - * JNI Initialization - */ -jint JNI_OnLoad(JavaVM* jvm, void* reserved) { - JNIEnv* e; - - ALOGV("statsd : loading JNI\n"); - // Check JNI version - if (jvm->GetEnv((void**)&e, JNI_VERSION_1_4)) { - ALOGE("JNI version mismatch error"); - return JNI_ERR; - } - - return android::register_android_util_StatsLog(e); -} diff --git a/apex/statsd/service/Android.bp b/apex/statsd/service/Android.bp deleted file mode 100644 index df0ccfc54d64..000000000000 --- a/apex/statsd/service/Android.bp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2020 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. - -filegroup { - name: "service-statsd-sources", - srcs: [ - "java/**/*.java", - ], -} - -java_library { - name: "service-statsd", - srcs: [ ":service-statsd-sources" ], - sdk_version: "system_server_current", - libs: [ - "framework-annotations-lib", - "framework-statsd", - ], - plugins: ["java_api_finder"], - apex_available: [ - "com.android.os.statsd", - "test_com.android.os.statsd", - ], -} diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java deleted file mode 100644 index dc477a5590ea..000000000000 --- a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2019 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 com.android.server.stats; - -import android.app.PendingIntent; -import android.app.StatsManager; -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.IPendingIntentRef; -import android.os.Process; -import android.os.StatsDimensionsValue; -import android.os.StatsDimensionsValueParcel; -import android.util.Log; - -import com.android.server.SystemService; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * @hide - */ -public class StatsCompanion { - private static final String TAG = "StatsCompanion"; - private static final boolean DEBUG = false; - - private static final int AID_STATSD = 1066; - - private static final String STATS_COMPANION_SERVICE = "statscompanion"; - private static final String STATS_MANAGER_SERVICE = "statsmanager"; - - static void enforceStatsdCallingUid() { - if (Binder.getCallingPid() == Process.myPid()) { - return; - } - if (Binder.getCallingUid() != AID_STATSD) { - throw new SecurityException("Not allowed to access StatsCompanion"); - } - } - - /** - * Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}. - */ - public static final class Lifecycle extends SystemService { - private StatsCompanionService mStatsCompanionService; - private StatsManagerService mStatsManagerService; - - public Lifecycle(Context context) { - super(context); - } - - @Override - public void onStart() { - mStatsCompanionService = new StatsCompanionService(getContext()); - mStatsManagerService = new StatsManagerService(getContext()); - mStatsCompanionService.setStatsManagerService(mStatsManagerService); - mStatsManagerService.setStatsCompanionService(mStatsCompanionService); - - try { - publishBinderService(STATS_COMPANION_SERVICE, mStatsCompanionService); - if (DEBUG) Log.d(TAG, "Published " + STATS_COMPANION_SERVICE); - publishBinderService(STATS_MANAGER_SERVICE, mStatsManagerService); - if (DEBUG) Log.d(TAG, "Published " + STATS_MANAGER_SERVICE); - } catch (Exception e) { - Log.e(TAG, "Failed to publishBinderService", e); - } - } - - @Override - public void onBootPhase(int phase) { - super.onBootPhase(phase); - if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { - mStatsCompanionService.systemReady(); - } - if (phase == PHASE_BOOT_COMPLETED) { - mStatsCompanionService.bootCompleted(); - } - } - } - - /** - * Wrapper for {@link PendingIntent}. Allows Statsd to send PendingIntents. - */ - public static class PendingIntentRef extends IPendingIntentRef.Stub { - - private static final String TAG = "PendingIntentRef"; - - /** - * The last report time is provided with each intent registered to - * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if - * statsd is requesting the client to retrieve the same statsd data. The last report time - * corresponds to the last_report_elapsed_nanos that will provided in the current - * ConfigMetricsReport, and this timestamp also corresponds to the - * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport. - */ - private static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME"; - private static final int CODE_DATA_BROADCAST = 1; - private static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1; - private static final int CODE_SUBSCRIBER_BROADCAST = 1; - - private final PendingIntent mPendingIntent; - private final Context mContext; - - public PendingIntentRef(PendingIntent pendingIntent, Context context) { - mPendingIntent = pendingIntent; - mContext = context; - } - - @Override - public void sendDataBroadcast(long lastReportTimeNs) { - enforceStatsdCallingUid(); - Intent intent = new Intent(); - intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs); - try { - mPendingIntent.send(mContext, CODE_DATA_BROADCAST, intent, null, null); - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "Unable to send PendingIntent"); - } - } - - @Override - public void sendActiveConfigsChangedBroadcast(long[] configIds) { - enforceStatsdCallingUid(); - Intent intent = new Intent(); - intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds); - try { - mPendingIntent.send(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null); - if (DEBUG) { - Log.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds)); - } - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "Unable to send active configs changed broadcast using PendingIntent"); - } - } - - @Override - public void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId, - long subscriptionRuleId, String[] cookies, - StatsDimensionsValueParcel dimensionsValueParcel) { - enforceStatsdCallingUid(); - StatsDimensionsValue dimensionsValue = new StatsDimensionsValue(dimensionsValueParcel); - Intent intent = - new Intent() - .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid) - .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configId) - .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId) - .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID, - subscriptionRuleId) - .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue); - - ArrayList<String> cookieList = new ArrayList<>(cookies.length); - cookieList.addAll(Arrays.asList(cookies)); - intent.putStringArrayListExtra( - StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList); - - if (DEBUG) { - Log.d(TAG, - String.format( - "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}", - configUid, configId, subscriptionId, subscriptionRuleId, - Arrays.toString(cookies), - dimensionsValue)); - } - try { - mPendingIntent.send(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null); - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, - "Unable to send using PendingIntent from uid " + configUid - + "; presumably it had been cancelled."); - } - } - } -} diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java deleted file mode 100644 index b5e72247a4a3..000000000000 --- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Copyright (C) 2017 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 com.android.server.stats; - -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; - -import android.app.AlarmManager; -import android.app.AlarmManager.OnAlarmListener; -import android.app.StatsManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.Binder; -import android.os.Bundle; -import android.os.FileUtils; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.IStatsCompanionService; -import android.os.IStatsd; -import android.os.Looper; -import android.os.ParcelFileDescriptor; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.StatsFrameworkInitializer; -import android.os.SystemClock; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.Log; -import android.util.proto.ProtoOutputStream; - -import com.android.internal.annotations.GuardedBy; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Helper service for statsd (the native stats management service in cmds/statsd/). - * Used for registering and receiving alarms on behalf of statsd. - * - * @hide - */ -public class StatsCompanionService extends IStatsCompanionService.Stub { - - private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1); - - public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity"; - public static final String CONFIG_DIR = "/data/misc/stats-service"; - - static final String TAG = "StatsCompanionService"; - static final boolean DEBUG = false; - /** - * Hard coded field ids of frameworks/base/cmds/statsd/src/uid_data.proto - * to be used in ProtoOutputStream. - */ - private static final int APPLICATION_INFO_FIELD_ID = 1; - private static final int UID_FIELD_ID = 1; - private static final int VERSION_FIELD_ID = 2; - private static final int VERSION_STRING_FIELD_ID = 3; - private static final int PACKAGE_NAME_FIELD_ID = 4; - private static final int INSTALLER_FIELD_ID = 5; - - public static final int DEATH_THRESHOLD = 10; - - static final class CompanionHandler extends Handler { - CompanionHandler(Looper looper) { - super(looper); - } - } - - private final Context mContext; - private final AlarmManager mAlarmManager; - @GuardedBy("sStatsdLock") - private static IStatsd sStatsd; - private static final Object sStatsdLock = new Object(); - - private final OnAlarmListener mPullingAlarmListener; - private final OnAlarmListener mPeriodicAlarmListener; - - private StatsManagerService mStatsManagerService; - - @GuardedBy("sStatsdLock") - private final HashSet<Long> mDeathTimeMillis = new HashSet<>(); - @GuardedBy("sStatsdLock") - private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); - private final CompanionHandler mHandler; - - // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle. - private AtomicBoolean mBootCompleted = new AtomicBoolean(false); - - public StatsCompanionService(Context context) { - super(); - mContext = context; - mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); - if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED."); - HandlerThread handlerThread = new HandlerThread(TAG); - handlerThread.start(); - mHandler = new CompanionHandler(handlerThread.getLooper()); - - mPullingAlarmListener = new PullingAlarmListener(context); - mPeriodicAlarmListener = new PeriodicAlarmListener(context); - } - - private final static int[] toIntArray(List<Integer> list) { - int[] ret = new int[list.size()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = list.get(i); - } - return ret; - } - - private final static long[] toLongArray(List<Long> list) { - long[] ret = new long[list.size()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = list.get(i); - } - return ret; - } - - /** - * Non-blocking call to retrieve a reference to statsd - * - * @return IStatsd object if statsd is ready, null otherwise. - */ - private static IStatsd getStatsdNonblocking() { - synchronized (sStatsdLock) { - return sStatsd; - } - } - - private static void informAllUids(Context context) { - ParcelFileDescriptor[] fds; - try { - fds = ParcelFileDescriptor.createPipe(); - } catch (IOException e) { - Log.e(TAG, "Failed to create a pipe to send uid map data.", e); - return; - } - HandlerThread backgroundThread = new HandlerThread( - "statsCompanionService.bg", THREAD_PRIORITY_BACKGROUND); - backgroundThread.start(); - Handler handler = new Handler(backgroundThread.getLooper()); - handler.post(() -> { - UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); - PackageManager pm = context.getPackageManager(); - final List<UserHandle> users = um.getUserHandles(true); - if (DEBUG) { - Log.d(TAG, "Iterating over " + users.size() + " userHandles."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - return; - } - try { - statsd.informAllUidData(fds[0]); - } catch (RemoteException e) { - Log.e(TAG, "Failed to send uid map to statsd"); - } - try { - fds[0].close(); - } catch (IOException e) { - Log.e(TAG, "Failed to close the read side of the pipe.", e); - } - final ParcelFileDescriptor writeFd = fds[1]; - FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd); - try { - ProtoOutputStream output = new ProtoOutputStream(fout); - int numRecords = 0; - // Add in all the apps for every user/profile. - for (UserHandle userHandle : users) { - List<PackageInfo> pi = - pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES - | PackageManager.MATCH_ANY_USER - | PackageManager.MATCH_APEX, - userHandle.getIdentifier()); - for (int j = 0; j < pi.size(); j++) { - if (pi.get(j).applicationInfo != null) { - String installer; - try { - installer = pm.getInstallerPackageName(pi.get(j).packageName); - } catch (IllegalArgumentException e) { - installer = ""; - } - long applicationInfoToken = - output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE - | ProtoOutputStream.FIELD_COUNT_REPEATED - | APPLICATION_INFO_FIELD_ID); - output.write(ProtoOutputStream.FIELD_TYPE_INT32 - | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID, - pi.get(j).applicationInfo.uid); - output.write(ProtoOutputStream.FIELD_TYPE_INT64 - | ProtoOutputStream.FIELD_COUNT_SINGLE - | VERSION_FIELD_ID, pi.get(j).getLongVersionCode()); - output.write(ProtoOutputStream.FIELD_TYPE_STRING - | ProtoOutputStream.FIELD_COUNT_SINGLE - | VERSION_STRING_FIELD_ID, - pi.get(j).versionName); - output.write(ProtoOutputStream.FIELD_TYPE_STRING - | ProtoOutputStream.FIELD_COUNT_SINGLE - | PACKAGE_NAME_FIELD_ID, pi.get(j).packageName); - output.write(ProtoOutputStream.FIELD_TYPE_STRING - | ProtoOutputStream.FIELD_COUNT_SINGLE - | INSTALLER_FIELD_ID, - installer == null ? "" : installer); - numRecords++; - output.end(applicationInfoToken); - } - } - } - output.flush(); - if (DEBUG) { - Log.d(TAG, "Sent data for " + numRecords + " apps"); - } - } finally { - FileUtils.closeQuietly(fout); - backgroundThread.quit(); - backgroundThread.interrupt(); - } - }); - } - - private static class WakelockThread extends Thread { - private final PowerManager.WakeLock mWl; - private final Runnable mRunnable; - - WakelockThread(Context context, String wakelockName, Runnable runnable) { - PowerManager powerManager = (PowerManager) - context.getSystemService(Context.POWER_SERVICE); - mWl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName); - mRunnable = runnable; - } - @Override - public void run() { - try { - mRunnable.run(); - } finally { - mWl.release(); - } - } - @Override - public void start() { - mWl.acquire(); - super.start(); - } - } - - private final static class AppUpdateReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - /** - * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid - * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag. - * If we can't find the value for EXTRA_REPLACING, we default to false. - */ - if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) - && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - return; // Keep only replacing or normal add and remove. - } - if (DEBUG) Log.d(TAG, "StatsCompanionService noticed an app was updated."); - synchronized (sStatsdLock) { - if (sStatsd == null) { - Log.w(TAG, "Could not access statsd to inform it of an app update"); - return; - } - try { - if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { - Bundle b = intent.getExtras(); - int uid = b.getInt(Intent.EXTRA_UID); - boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); - if (!replacing) { - // Don't bother sending an update if we're right about to get another - // intent for the new version that's added. - String app = intent.getData().getSchemeSpecificPart(); - sStatsd.informOnePackageRemoved(app, uid); - } - } else { - PackageManager pm = context.getPackageManager(); - Bundle b = intent.getExtras(); - int uid = b.getInt(Intent.EXTRA_UID); - String app = intent.getData().getSchemeSpecificPart(); - PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER); - String installer; - try { - installer = pm.getInstallerPackageName(app); - } catch (IllegalArgumentException e) { - installer = ""; - } - sStatsd.informOnePackage( - app, - uid, - pi.getLongVersionCode(), - pi.versionName == null ? "" : pi.versionName, - installer == null ? "" : installer); - } - } catch (Exception e) { - Log.w(TAG, "Failed to inform statsd of an app update", e); - } - } - } - } - - private static final class UserUpdateReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - // Pull the latest state of UID->app name, version mapping. - // Needed since the new user basically has a version of every app. - informAllUids(context); - } - } - - public final static class PullingAlarmListener implements OnAlarmListener { - private final Context mContext; - - PullingAlarmListener(Context context) { - mContext = context; - } - - @Override - public void onAlarm() { - if (DEBUG) { - Log.d(TAG, "Time to poll something."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing."); - return; - } - - // Wakelock needs to be retained while calling statsd. - Thread thread = new WakelockThread(mContext, - PullingAlarmListener.class.getCanonicalName(), new Runnable() { - @Override - public void run() { - try { - statsd.informPollAlarmFired(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e); - } - } - }); - thread.start(); - } - } - - public final static class PeriodicAlarmListener implements OnAlarmListener { - private final Context mContext; - - PeriodicAlarmListener(Context context) { - mContext = context; - } - - @Override - public void onAlarm() { - if (DEBUG) { - Log.d(TAG, "Time to trigger periodic alarm."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing."); - return; - } - - // Wakelock needs to be retained while calling statsd. - Thread thread = new WakelockThread(mContext, - PeriodicAlarmListener.class.getCanonicalName(), new Runnable() { - @Override - public void run() { - try { - statsd.informAlarmForSubscriberTriggeringFired(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e); - } - } - }); - thread.start(); - } - } - - public final static class ShutdownEventReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - /** - * Skip immediately if intent is not relevant to device shutdown. - */ - if (!intent.getAction().equals(Intent.ACTION_REBOOT) - && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN) - && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) { - return; - } - - if (DEBUG) { - Log.i(TAG, "StatsCompanionService noticed a shutdown."); - } - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - Log.w(TAG, "Could not access statsd to inform it of a shutdown event."); - return; - } - try { - // two way binder call - statsd.informDeviceShutdown(); - } catch (Exception e) { - Log.w(TAG, "Failed to inform statsd of a shutdown event.", e); - } - } - } - - @Override // Binder call - public void setAlarmForSubscriberTriggering(long timestampMs) { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, - "Setting periodic alarm in about " + (timestampMs - - SystemClock.elapsedRealtime())); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will - // only fire when it awakens. - mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".periodic", - mPeriodicAlarmListener, mHandler); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void cancelAlarmForSubscriberTriggering() { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "Cancelling periodic alarm"); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - mAlarmManager.cancel(mPeriodicAlarmListener); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void setPullingAlarm(long nextPullTimeMs) { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "Setting pulling alarm in about " - + (nextPullTimeMs - SystemClock.elapsedRealtime())); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will - // only fire when it awakens. - mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, TAG + ".pull", - mPullingAlarmListener, mHandler); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void cancelPullingAlarm() { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "Cancelling pulling alarm"); - } - final long callingToken = Binder.clearCallingIdentity(); - try { - mAlarmManager.cancel(mPullingAlarmListener); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - @Override // Binder call - public void statsdReady() { - StatsCompanion.enforceStatsdCallingUid(); - if (DEBUG) { - Log.d(TAG, "learned that statsdReady"); - } - sayHiToStatsd(); // tell statsd that we're ready too and link to it - - final Intent intent = new Intent(StatsManager.ACTION_STATSD_STARTED); - // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts - // to wake them up (if they're in background). - List<ResolveInfo> resolveInfos = - mContext.getPackageManager().queryBroadcastReceiversAsUser( - intent, 0, UserHandle.SYSTEM); - if (resolveInfos == null || resolveInfos.isEmpty()) { - return; // No need to send broadcast. - } - - for (ResolveInfo resolveInfo : resolveInfos) { - Intent intentToSend = new Intent(intent); - intentToSend.setComponent(new ComponentName( - resolveInfo.activityInfo.applicationInfo.packageName, - resolveInfo.activityInfo.name)); - mContext.sendBroadcastAsUser(intentToSend, UserHandle.SYSTEM, - android.Manifest.permission.DUMP); - } - } - - @Override // Binder call - public boolean checkPermission(String permission, int pid, int uid) { - StatsCompanion.enforceStatsdCallingUid(); - return mContext.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED; - } - - // Statsd related code - - /** - * Fetches the statsd IBinder service. This is a blocking call that always refetches statsd - * instead of returning the cached sStatsd. - * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use - * the cached sStatsd via {@link #getStatsdNonblocking()}. - */ - private IStatsd fetchStatsdServiceLocked() { - sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer - .getStatsServiceManager() - .getStatsdServiceRegisterer() - .get()); - return sStatsd; - } - - private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { - StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers); - - try { - statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0); - } catch (RemoteException e) { - Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed"); - // Statsd has already died. Unregister receivers ourselves. - for (BroadcastReceiver receiver : receivers) { - mContext.unregisterReceiver(receiver); - } - synchronized (sStatsdLock) { - if (statsd == sStatsd) { - statsdNotReadyLocked(); - } - } - } - } - - /** - * Now that the android system is ready, StatsCompanion is ready too, so inform statsd. - */ - void systemReady() { - if (DEBUG) Log.d(TAG, "Learned that systemReady"); - sayHiToStatsd(); - } - - void setStatsManagerService(StatsManagerService statsManagerService) { - mStatsManagerService = statsManagerService; - } - - /** - * Tells statsd that statscompanion is ready. If the binder call returns, link to - * statsd. - */ - private void sayHiToStatsd() { - IStatsd statsd; - synchronized (sStatsdLock) { - if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) { - Log.e(TAG, "statsd has already been fetched before", - new IllegalStateException("IStatsd object should be null or dead")); - return; - } - statsd = fetchStatsdServiceLocked(); - } - - if (statsd == null) { - Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive."); - return; - } - - // Cleann up from previous statsd - cancel any alarms that had been set. Do this here - // instead of in binder death because statsd can come back and set different alarms, or not - // want to set an alarm when it had been set. This guarantees that when we get a new statsd, - // we cancel any alarms before it is able to set them. - cancelPullingAlarm(); - cancelAlarmForSubscriberTriggering(); - - if (DEBUG) Log.d(TAG, "Saying hi to statsd"); - mStatsManagerService.statsdReady(statsd); - try { - statsd.statsCompanionReady(); - - BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver(); - BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver(); - BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver(); - - // Setup broadcast receiver for updates. - IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addDataScheme("package"); - mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); - - // Setup receiver for user initialize (which happens once for a new user) - // and if a user is removed. - filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); - filter.addAction(Intent.ACTION_USER_REMOVED); - mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); - - // Setup receiver for device reboots or shutdowns. - filter = new IntentFilter(Intent.ACTION_REBOOT); - filter.addAction(Intent.ACTION_SHUTDOWN); - mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null); - - // Register death recipient. - List<BroadcastReceiver> broadcastReceivers = - List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver); - registerStatsdDeathRecipient(statsd, broadcastReceivers); - - // Tell statsd that boot has completed. The signal may have already been sent, but since - // the signal-receiving function is idempotent, that's ok. - if (mBootCompleted.get()) { - statsd.bootCompleted(); - } - - // Pull the latest state of UID->app name, version mapping when statsd starts. - informAllUids(mContext); - - Log.i(TAG, "Told statsd that StatsCompanionService is alive."); - } catch (RemoteException e) { - Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e); - } - } - - private class StatsdDeathRecipient implements IBinder.DeathRecipient { - - private final IStatsd mStatsd; - private final List<BroadcastReceiver> mReceiversToUnregister; - - StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { - mStatsd = statsd; - mReceiversToUnregister = receivers; - } - - // It is possible for binderDied to be called after a restarted statsd calls statsdReady, - // but that's alright because the code does not assume an ordering of the two calls. - @Override - public void binderDied() { - Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); - synchronized (sStatsdLock) { - long now = SystemClock.elapsedRealtime(); - for (Long timeMillis : mDeathTimeMillis) { - long ageMillis = now - timeMillis; - if (ageMillis > MILLIS_IN_A_DAY) { - mDeathTimeMillis.remove(timeMillis); - } - } - for (Long timeMillis : mDeletedFiles.keySet()) { - long ageMillis = now - timeMillis; - if (ageMillis > MILLIS_IN_A_DAY * 7) { - mDeletedFiles.remove(timeMillis); - } - } - mDeathTimeMillis.add(now); - if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) { - mDeathTimeMillis.clear(); - File[] configs = new File(CONFIG_DIR).listFiles(); - if (configs != null && configs.length > 0) { - String fileName = configs[0].getName(); - if (configs[0].delete()) { - mDeletedFiles.put(now, fileName); - } - } - } - - // Unregister receivers on death because receivers can only be unregistered once. - // Otherwise, an IllegalArgumentException is thrown. - for (BroadcastReceiver receiver: mReceiversToUnregister) { - mContext.unregisterReceiver(receiver); - } - - // It's possible for statsd to have restarted and called statsdReady, causing a new - // sStatsd binder object to be fetched, before the binderDied callback runs. Only - // call #statsdNotReadyLocked if that hasn't happened yet. - if (mStatsd == sStatsd) { - statsdNotReadyLocked(); - } - } - } - } - - private void statsdNotReadyLocked() { - sStatsd = null; - mStatsManagerService.statsdNotReady(); - } - - void bootCompleted() { - mBootCompleted.set(true); - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - // Statsd is not yet ready. - // Delay the boot completed ping to {@link #sayHiToStatsd()} - return; - } - try { - statsd.bootCompleted(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to notify statsd that boot completed"); - } - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - return; - } - - synchronized (sStatsdLock) { - writer.println("Number of configuration files deleted: " + mDeletedFiles.size()); - if (mDeletedFiles.size() > 0) { - writer.println(" timestamp, deleted file name"); - } - long lastBootMillis = - SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); - for (Long elapsedMillis : mDeletedFiles.keySet()) { - long deletionMillis = lastBootMillis + elapsedMillis; - writer.println(" " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); - } - } - } -} diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java deleted file mode 100644 index 97846f2397a5..000000000000 --- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java +++ /dev/null @@ -1,661 +0,0 @@ -/* - * Copyright (C) 2019 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 com.android.server.stats; - -import static com.android.server.stats.StatsCompanion.PendingIntentRef; - -import android.Manifest; -import android.annotation.Nullable; -import android.app.AppOpsManager; -import android.app.PendingIntent; -import android.content.Context; -import android.os.Binder; -import android.os.IPullAtomCallback; -import android.os.IStatsManagerService; -import android.os.IStatsd; -import android.os.Process; -import android.os.RemoteException; -import android.util.ArrayMap; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; - -import java.util.Map; -import java.util.Objects; - -/** - * Service for {@link android.app.StatsManager}. - * - * @hide - */ -public class StatsManagerService extends IStatsManagerService.Stub { - - private static final String TAG = "StatsManagerService"; - private static final boolean DEBUG = false; - - private static final int STATSD_TIMEOUT_MILLIS = 5000; - - private static final String USAGE_STATS_PERMISSION_OPS = "android:get_usage_stats"; - - @GuardedBy("mLock") - private IStatsd mStatsd; - private final Object mLock = new Object(); - - private StatsCompanionService mStatsCompanionService; - private Context mContext; - - @GuardedBy("mLock") - private ArrayMap<ConfigKey, PendingIntentRef> mDataFetchPirMap = new ArrayMap<>(); - @GuardedBy("mLock") - private ArrayMap<Integer, PendingIntentRef> mActiveConfigsPirMap = new ArrayMap<>(); - @GuardedBy("mLock") - private ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> mBroadcastSubscriberPirMap = - new ArrayMap<>(); - - public StatsManagerService(Context context) { - super(); - mContext = context; - } - - private static class ConfigKey { - private final int mUid; - private final long mConfigId; - - ConfigKey(int uid, long configId) { - mUid = uid; - mConfigId = configId; - } - - public int getUid() { - return mUid; - } - - public long getConfigId() { - return mConfigId; - } - - @Override - public int hashCode() { - return Objects.hash(mUid, mConfigId); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ConfigKey) { - ConfigKey other = (ConfigKey) obj; - return this.mUid == other.getUid() && this.mConfigId == other.getConfigId(); - } - return false; - } - } - - private static class PullerKey { - private final int mUid; - private final int mAtomTag; - - PullerKey(int uid, int atom) { - mUid = uid; - mAtomTag = atom; - } - - public int getUid() { - return mUid; - } - - public int getAtom() { - return mAtomTag; - } - - @Override - public int hashCode() { - return Objects.hash(mUid, mAtomTag); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PullerKey) { - PullerKey other = (PullerKey) obj; - return this.mUid == other.getUid() && this.mAtomTag == other.getAtom(); - } - return false; - } - } - - private static class PullerValue { - private final long mCoolDownMillis; - private final long mTimeoutMillis; - private final int[] mAdditiveFields; - private final IPullAtomCallback mCallback; - - PullerValue(long coolDownMillis, long timeoutMillis, int[] additiveFields, - IPullAtomCallback callback) { - mCoolDownMillis = coolDownMillis; - mTimeoutMillis = timeoutMillis; - mAdditiveFields = additiveFields; - mCallback = callback; - } - - public long getCoolDownMillis() { - return mCoolDownMillis; - } - - public long getTimeoutMillis() { - return mTimeoutMillis; - } - - public int[] getAdditiveFields() { - return mAdditiveFields; - } - - public IPullAtomCallback getCallback() { - return mCallback; - } - } - - private final ArrayMap<PullerKey, PullerValue> mPullers = new ArrayMap<>(); - - @Override - public void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis, - int[] additiveFields, IPullAtomCallback pullerCallback) { - enforceRegisterStatsPullAtomPermission(); - if (pullerCallback == null) { - Log.w(TAG, "Puller callback is null for atom " + atomTag); - return; - } - int callingUid = Binder.getCallingUid(); - PullerKey key = new PullerKey(callingUid, atomTag); - PullerValue val = - new PullerValue(coolDownMillis, timeoutMillis, additiveFields, pullerCallback); - - // Always cache the puller in StatsManagerService. If statsd is down, we will register the - // puller when statsd comes back up. - synchronized (mLock) { - mPullers.put(key, val); - } - - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - try { - statsd.registerPullAtomCallback(callingUid, atomTag, coolDownMillis, timeoutMillis, - additiveFields, pullerCallback); - } catch (RemoteException e) { - Log.e(TAG, "Failed to access statsd to register puller for atom " + atomTag); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void unregisterPullAtomCallback(int atomTag) { - enforceRegisterStatsPullAtomPermission(); - int callingUid = Binder.getCallingUid(); - PullerKey key = new PullerKey(callingUid, atomTag); - - // Always remove the puller from StatsManagerService even if statsd is down. When statsd - // comes back up, we will not re-register the removed puller. - synchronized (mLock) { - mPullers.remove(key); - } - - IStatsd statsd = getStatsdNonblocking(); - if (statsd == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - try { - statsd.unregisterPullAtomCallback(callingUid, atomTag); - } catch (RemoteException e) { - Log.e(TAG, "Failed to access statsd to unregister puller for atom " + atomTag); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void setDataFetchOperation(long configId, PendingIntent pendingIntent, - String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext); - ConfigKey key = new ConfigKey(callingUid, configId); - // We add the PIR to a map so we can reregister if statsd is unavailable. - synchronized (mLock) { - mDataFetchPirMap.put(key, pir); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.setDataFetchOperation(configId, pir, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to setDataFetchOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void removeDataFetchOperation(long configId, String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - ConfigKey key = new ConfigKey(callingUid, configId); - synchronized (mLock) { - mDataFetchPirMap.remove(key); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.removeDataFetchOperation(configId, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to removeDataFetchOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent, - String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext); - // We add the PIR to a map so we can reregister if statsd is unavailable. - synchronized (mLock) { - mActiveConfigsPirMap.put(callingUid, pir); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - return statsd.setActiveConfigsChangedOperation(pir, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to setActiveConfigsChangedOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - return new long[] {}; - } - - @Override - public void removeActiveConfigsChangedOperation(String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - synchronized (mLock) { - mActiveConfigsPirMap.remove(callingUid); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.removeActiveConfigsChangedOperation(callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to removeActiveConfigsChangedOperation with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void setBroadcastSubscriber(long configId, long subscriberId, - PendingIntent pendingIntent, String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext); - ConfigKey key = new ConfigKey(callingUid, configId); - // We add the PIR to a map so we can reregister if statsd is unavailable. - synchronized (mLock) { - ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap - .getOrDefault(key, new ArrayMap<>()); - innerMap.put(subscriberId, pir); - mBroadcastSubscriberPirMap.put(key, innerMap); - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.setBroadcastSubscriber( - configId, subscriberId, pir, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to setBroadcastSubscriber with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void unsetBroadcastSubscriber(long configId, long subscriberId, String packageName) { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - ConfigKey key = new ConfigKey(callingUid, configId); - synchronized (mLock) { - ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap - .getOrDefault(key, new ArrayMap<>()); - innerMap.remove(subscriberId); - if (innerMap.isEmpty()) { - mBroadcastSubscriberPirMap.remove(key); - } - } - try { - IStatsd statsd = getStatsdNonblocking(); - if (statsd != null) { - statsd.unsetBroadcastSubscriber(configId, subscriberId, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to unsetBroadcastSubscriber with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public long[] getRegisteredExperimentIds() throws IllegalStateException { - enforceDumpAndUsageStatsPermission(null); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - return statsd.getRegisteredExperimentIds(); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to getRegisteredExperimentIds with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to registerExperimentIds"); - } - - @Override - public byte[] getMetadata(String packageName) throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - return statsd.getMetadata(); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to getMetadata with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to getMetadata"); - } - - @Override - public byte[] getData(long key, String packageName) throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - return statsd.getData(key, callingUid); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to getData with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to getData"); - } - - @Override - public void addConfiguration(long configId, byte[] config, String packageName) - throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - statsd.addConfiguration(configId, config, callingUid); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to addConfiguration with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to addConfig"); - } - - @Override - public void removeConfiguration(long configId, String packageName) - throws IllegalStateException { - enforceDumpAndUsageStatsPermission(packageName); - int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - IStatsd statsd = waitForStatsd(); - if (statsd != null) { - statsd.removeConfiguration(configId, callingUid); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to removeConfiguration with statsd"); - throw new IllegalStateException(e.getMessage(), e); - } finally { - Binder.restoreCallingIdentity(token); - } - throw new IllegalStateException("Failed to connect to statsd to removeConfig"); - } - - void setStatsCompanionService(StatsCompanionService statsCompanionService) { - mStatsCompanionService = statsCompanionService; - } - - /** - * Checks that the caller has both DUMP and PACKAGE_USAGE_STATS permissions. Also checks that - * the caller has USAGE_STATS_PERMISSION_OPS for the specified packageName if it is not null. - * - * @param packageName The packageName to check USAGE_STATS_PERMISSION_OPS. - */ - private void enforceDumpAndUsageStatsPermission(@Nullable String packageName) { - int callingUid = Binder.getCallingUid(); - int callingPid = Binder.getCallingPid(); - - if (callingPid == Process.myPid()) { - return; - } - - mContext.enforceCallingPermission(Manifest.permission.DUMP, null); - mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, null); - - if (packageName == null) { - return; - } - AppOpsManager appOpsManager = (AppOpsManager) mContext - .getSystemService(Context.APP_OPS_SERVICE); - switch (appOpsManager.noteOp(USAGE_STATS_PERMISSION_OPS, - Binder.getCallingUid(), packageName, null, null)) { - case AppOpsManager.MODE_ALLOWED: - case AppOpsManager.MODE_DEFAULT: - break; - default: - throw new SecurityException( - String.format("UID %d / PID %d lacks app-op %s", - callingUid, callingPid, USAGE_STATS_PERMISSION_OPS) - ); - } - } - - private void enforceRegisterStatsPullAtomPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.REGISTER_STATS_PULL_ATOM, - "Need REGISTER_STATS_PULL_ATOM permission."); - } - - - /** - * Clients should call this if blocking until statsd to be ready is desired - * - * @return IStatsd object if statsd becomes ready within the timeout, null otherwise. - */ - private IStatsd waitForStatsd() { - synchronized (mLock) { - if (mStatsd == null) { - try { - mLock.wait(STATSD_TIMEOUT_MILLIS); - } catch (InterruptedException e) { - Log.e(TAG, "wait for statsd interrupted"); - } - } - return mStatsd; - } - } - - /** - * Clients should call this to receive a reference to statsd. - * - * @return IStatsd object if statsd is ready, null otherwise. - */ - private IStatsd getStatsdNonblocking() { - synchronized (mLock) { - return mStatsd; - } - } - - /** - * Called from {@link StatsCompanionService}. - * - * Tells StatsManagerService that Statsd is ready and updates - * Statsd with the contents of our local cache. - */ - void statsdReady(IStatsd statsd) { - synchronized (mLock) { - mStatsd = statsd; - mLock.notify(); - } - sayHiToStatsd(statsd); - } - - /** - * Called from {@link StatsCompanionService}. - * - * Tells StatsManagerService that Statsd is no longer ready - * and we should no longer make binder calls with statsd. - */ - void statsdNotReady() { - synchronized (mLock) { - mStatsd = null; - } - } - - private void sayHiToStatsd(IStatsd statsd) { - if (statsd == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - try { - registerAllPullers(statsd); - registerAllDataFetchOperations(statsd); - registerAllActiveConfigsChangedOperations(statsd); - registerAllBroadcastSubscribers(statsd); - } catch (RemoteException e) { - Log.e(TAG, "StatsManager failed to (re-)register data with statsd"); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllPullers(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a copy of the - // data with the lock held before iterating through the map. - ArrayMap<PullerKey, PullerValue> pullersCopy; - synchronized (mLock) { - pullersCopy = new ArrayMap<>(mPullers); - } - - for (Map.Entry<PullerKey, PullerValue> entry : pullersCopy.entrySet()) { - PullerKey key = entry.getKey(); - PullerValue value = entry.getValue(); - statsd.registerPullAtomCallback(key.getUid(), key.getAtom(), value.getCoolDownMillis(), - value.getTimeoutMillis(), value.getAdditiveFields(), value.getCallback()); - } - statsd.allPullersFromBootRegistered(); - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllDataFetchOperations(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a copy of the - // data with the lock held before iterating through the map. - ArrayMap<ConfigKey, PendingIntentRef> dataFetchCopy; - synchronized (mLock) { - dataFetchCopy = new ArrayMap<>(mDataFetchPirMap); - } - - for (Map.Entry<ConfigKey, PendingIntentRef> entry : dataFetchCopy.entrySet()) { - ConfigKey key = entry.getKey(); - statsd.setDataFetchOperation(key.getConfigId(), entry.getValue(), key.getUid()); - } - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllActiveConfigsChangedOperations(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a copy of the - // data with the lock held before iterating through the map. - ArrayMap<Integer, PendingIntentRef> activeConfigsChangedCopy; - synchronized (mLock) { - activeConfigsChangedCopy = new ArrayMap<>(mActiveConfigsPirMap); - } - - for (Map.Entry<Integer, PendingIntentRef> entry : activeConfigsChangedCopy.entrySet()) { - statsd.setActiveConfigsChangedOperation(entry.getValue(), entry.getKey()); - } - } - - // Pre-condition: the Binder calling identity has already been cleared - private void registerAllBroadcastSubscribers(IStatsd statsd) throws RemoteException { - // Since we do not want to make an IPC with the lock held, we first create a deep copy of - // the data with the lock held before iterating through the map. - ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> broadcastSubscriberCopy = - new ArrayMap<>(); - synchronized (mLock) { - for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry : - mBroadcastSubscriberPirMap.entrySet()) { - broadcastSubscriberCopy.put(entry.getKey(), new ArrayMap(entry.getValue())); - } - } - - for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry : - mBroadcastSubscriberPirMap.entrySet()) { - ConfigKey configKey = entry.getKey(); - for (Map.Entry<Long, PendingIntentRef> subscriberEntry : entry.getValue().entrySet()) { - statsd.setBroadcastSubscriber(configKey.getConfigId(), subscriberEntry.getKey(), - subscriberEntry.getValue(), configKey.getUid()); - } - } - } -} diff --git a/apex/statsd/statsd.rc b/apex/statsd/statsd.rc deleted file mode 100644 index 605da2af0c19..000000000000 --- a/apex/statsd/statsd.rc +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2017 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. - -service statsd /apex/com.android.os.statsd/bin/statsd - class main - socket statsdw dgram+passcred 0222 statsd statsd - user statsd - group statsd log - writepid /dev/cpuset/system-background/tasks diff --git a/apex/statsd/testing/Android.bp b/apex/statsd/testing/Android.bp deleted file mode 100644 index a9cd0ccb53e8..000000000000 --- a/apex/statsd/testing/Android.bp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2019 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. - -apex_test { - name: "test_com.android.os.statsd", - visibility: [ - "//system/apex/tests", - ], - defaults: ["com.android.os.statsd-defaults"], - manifest: "test_manifest.json", - file_contexts: ":com.android.os.statsd-file_contexts", - // Test APEX, should never be installed - installable: false, -} diff --git a/apex/statsd/testing/test_manifest.json b/apex/statsd/testing/test_manifest.json deleted file mode 100644 index 57343d3e6ae5..000000000000 --- a/apex/statsd/testing/test_manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.os.statsd", - "version": 2147483647 -} diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp deleted file mode 100644 index 05b3e049ac39..000000000000 --- a/apex/statsd/tests/libstatspull/Android.bp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2019 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. - -android_test { - name: "LibStatsPullTests", - static_libs: [ - "androidx.test.rules", - "platformprotoslite", - "statsdprotolite", - "truth-prebuilt", - ], - libs: [ - "android.test.runner.stubs", - "android.test.base.stubs", - ], - jni_libs: [ - "libstatspull_testhelper", - ], - srcs: [ - "src/**/*.java", - "protos/**/*.proto", - ], - test_suites: [ - "device-tests", - "mts", - ], - platform_apis: true, - privileged: true, - certificate: "platform", - compile_multilib: "both", -} - -cc_library_shared { - name: "libstatspull_testhelper", - srcs: ["jni/stats_pull_helper.cpp"], - cflags: [ - "-Wall", - "-Werror", - ], - shared_libs: [ - "libbinder_ndk", - "statsd-aidl-ndk_platform", - ], - static_libs: [ - "libstatspull_private", - "libstatssocket_private", - "libutils", - "libcutils", - ], -} diff --git a/apex/statsd/tests/libstatspull/AndroidManifest.xml b/apex/statsd/tests/libstatspull/AndroidManifest.xml deleted file mode 100644 index 0c669b051c86..000000000000 --- a/apex/statsd/tests/libstatspull/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2020 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. - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.internal.os.statsd.libstats" > - - - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> - <uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM" /> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.internal.os.statsd.libstats" - android:label="Tests for libstatspull"> - </instrumentation> -</manifest> - diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp deleted file mode 100644 index 166592d35151..000000000000 --- a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019, 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. - */ - -#include <jni.h> -#include <log/log.h> -#include <stats_event.h> -#include <stats_pull_atom_callback.h> - -#include <chrono> -#include <thread> - -using std::this_thread::sleep_for; - -namespace { -static int32_t sAtomTag; -static int32_t sPullReturnVal; -static int64_t sLatencyMillis; -static int32_t sAtomsPerPull; -static int32_t sNumPulls = 0; - -static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, AStatsEventList* data, - void* /*cookie*/) { - sNumPulls++; - sleep_for(std::chrono::milliseconds(sLatencyMillis)); - for (int i = 0; i < sAtomsPerPull; i++) { - AStatsEvent* event = AStatsEventList_addStatsEvent(data); - AStatsEvent_setAtomId(event, atomTag); - AStatsEvent_writeInt64(event, (int64_t) sNumPulls); - AStatsEvent_build(event); - } - return sPullReturnVal; -} - -extern "C" JNIEXPORT void JNICALL -Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_setStatsPuller( - JNIEnv* /*env*/, jobject /* this */, jint atomTag, jlong timeoutMillis, - jlong coolDownMillis, jint pullRetVal, jlong latencyMillis, int atomsPerPull) { - sAtomTag = atomTag; - sPullReturnVal = pullRetVal; - sLatencyMillis = latencyMillis; - sAtomsPerPull = atomsPerPull; - sNumPulls = 0; - AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); - AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis); - AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis); - - AStatsManager_setPullAtomCallback(sAtomTag, metadata, &pullAtomCallback, nullptr); - AStatsManager_PullAtomMetadata_release(metadata); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_clearStatsPuller(JNIEnv* /*env*/, - jobject /* this */, - jint /*atomTag*/) { - AStatsManager_clearPullAtomCallback(sAtomTag); -} -} // namespace diff --git a/apex/statsd/tests/libstatspull/protos/test_atoms.proto b/apex/statsd/tests/libstatspull/protos/test_atoms.proto deleted file mode 100644 index 56c1b534a7ce..000000000000 --- a/apex/statsd/tests/libstatspull/protos/test_atoms.proto +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ -syntax = "proto2"; - -package com.android.internal.os.statsd.protos; - -option java_package = "com.android.internal.os.statsd.protos"; -option java_outer_classname = "TestAtoms"; - -message PullCallbackAtomWrapper { - optional PullCallbackAtom pull_callback_atom = 150030; -} - -message PullCallbackAtom { - optional int64 long_val = 1; -} - - - diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java deleted file mode 100644 index 6108a324e15e..000000000000 --- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2019 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 com.android.internal.os.statsd.libstats; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.StatsManager; -import android.content.Context; -import android.util.Log; -import android.util.StatsLog; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.MediumTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.os.StatsdConfigProto.AtomMatcher; -import com.android.internal.os.StatsdConfigProto.FieldFilter; -import com.android.internal.os.StatsdConfigProto.GaugeMetric; -import com.android.internal.os.StatsdConfigProto.PullAtomPackages; -import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; -import com.android.internal.os.StatsdConfigProto.StatsdConfig; -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import com.android.internal.os.statsd.protos.TestAtoms; -import com.android.os.AtomsProto.Atom; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -/** - * Test puller registration. - */ -@MediumTest -@RunWith(AndroidJUnit4.class) -public class LibStatsPullTests { - private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName(); - private static final int SHORT_SLEEP_MILLIS = 250; - private static final int LONG_SLEEP_MILLIS = 1_000; - private Context mContext; - private static final int PULL_ATOM_TAG = 150030; - private static final int APP_BREADCRUMB_LABEL = 3; - private static int sPullReturnValue; - private static long sConfigId; - private static long sPullLatencyMillis; - private static long sPullTimeoutMillis; - private static long sCoolDownMillis; - private static int sAtomsPerPull; - - static { - System.loadLibrary("statspull_testhelper"); - } - - /** - * Setup the tests. Initialize shared data. - */ - @Before - public void setup() { - mContext = InstrumentationRegistry.getTargetContext(); - assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull(); - sPullReturnValue = StatsManager.PULL_SUCCESS; - sPullLatencyMillis = 0; - sPullTimeoutMillis = 10_000L; - sCoolDownMillis = 1_000L; - sAtomsPerPull = 1; - } - - /** - * Teardown the tests. - */ - @After - public void tearDown() throws Exception { - clearStatsPuller(PULL_ATOM_TAG); - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - statsManager.removeConfig(sConfigId); - } - - /** - * Tests adding a puller callback and that pulls complete successfully. - */ - @Test - public void testPullAtomCallbackRegistration() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - // Upload a config that captures that pulled atom. - createAndAddConfigToStatsd(statsManager); - - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish. - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(1); - TestAtoms.PullCallbackAtomWrapper atomWrapper = null; - try { - atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser() - .parseFrom(data.get(0).toByteArray()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to parse primitive atoms"); - } - assertThat(atomWrapper).isNotNull(); - assertThat(atomWrapper.hasPullCallbackAtom()).isTrue(); - TestAtoms.PullCallbackAtom atom = - atomWrapper.getPullCallbackAtom(); - assertThat(atom.getLongVal()).isEqualTo(1); - } - - /** - * Tests that a failed pull is skipped. - */ - @Test - public void testPullAtomCallbackFailure() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - createAndAddConfigToStatsd(statsManager); - sPullReturnValue = StatsManager.PULL_SKIP; - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish. - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(0); - } - - /** - * Tests that a pull that times out is skipped. - */ - @Test - public void testPullAtomCallbackTimeout() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - createAndAddConfigToStatsd(statsManager); - // The puller will sleep for 1.5 sec. - sPullLatencyMillis = 1_500; - // 1 second timeout - sPullTimeoutMillis = 1_000; - - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish and the pull timeout. - Thread.sleep(sPullLatencyMillis * 2); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(0); - } - - /** - * Tests that 2 pulls in quick succession use the cache instead of pulling again. - */ - @Test - public void testPullAtomCallbackCache() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - createAndAddConfigToStatsd(statsManager); - - // Set the cooldown to 10 seconds - sCoolDownMillis = 10_000L; - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Pull from cache. - StatsLog.logStart(APP_BREADCRUMB_LABEL); - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(2); - for (int i = 0; i < data.size(); i++) { - TestAtoms.PullCallbackAtomWrapper atomWrapper = null; - try { - atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser() - .parseFrom(data.get(i).toByteArray()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to parse primitive atoms"); - } - assertThat(atomWrapper).isNotNull(); - assertThat(atomWrapper.hasPullCallbackAtom()).isTrue(); - TestAtoms.PullCallbackAtom atom = - atomWrapper.getPullCallbackAtom(); - assertThat(atom.getLongVal()).isEqualTo(1); - } - } - - /** - * Tests that a pull that returns 1000 stats events works properly. - */ - @Test - public void testPullAtomCallbackStress() throws Exception { - StatsManager statsManager = (StatsManager) mContext.getSystemService( - Context.STATS_MANAGER); - // Upload a config that captures that pulled atom. - createAndAddConfigToStatsd(statsManager); - sAtomsPerPull = 1000; - // Add the puller. - setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue, - sPullLatencyMillis, sAtomsPerPull); - - Thread.sleep(SHORT_SLEEP_MILLIS); - StatsLog.logStart(APP_BREADCRUMB_LABEL); - // Let the current bucket finish. - Thread.sleep(LONG_SLEEP_MILLIS); - List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId); - clearStatsPuller(PULL_ATOM_TAG); - assertThat(data.size()).isEqualTo(sAtomsPerPull); - - for (int i = 0; i < data.size(); i++) { - TestAtoms.PullCallbackAtomWrapper atomWrapper = null; - try { - atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser() - .parseFrom(data.get(i).toByteArray()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to parse primitive atoms"); - } - assertThat(atomWrapper).isNotNull(); - assertThat(atomWrapper.hasPullCallbackAtom()).isTrue(); - TestAtoms.PullCallbackAtom atom = - atomWrapper.getPullCallbackAtom(); - assertThat(atom.getLongVal()).isEqualTo(1); - } - } - - private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception { - sConfigId = System.currentTimeMillis(); - long triggerMatcherId = sConfigId + 10; - long pullerMatcherId = sConfigId + 11; - long metricId = sConfigId + 100; - StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId) - .addAtomMatcher( - StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId, - APP_BREADCRUMB_LABEL)) - .addAtomMatcher(AtomMatcher.newBuilder() - .setId(pullerMatcherId) - .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() - .setAtomId(PULL_ATOM_TAG)) - ) - .addGaugeMetric(GaugeMetric.newBuilder() - .setId(metricId) - .setWhat(pullerMatcherId) - .setTriggerEvent(triggerMatcherId) - .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true)) - .setBucket(TimeUnit.CTS) - .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES) - .setMaxNumGaugeAtomsPerBucket(1000) - ) - .addPullAtomPackages(PullAtomPackages.newBuilder() - .setAtomId(PULL_ATOM_TAG) - .addPackages(LibStatsPullTests.class.getPackage().getName())) - .build(); - statsManager.addConfig(sConfigId, config.toByteArray()); - assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue(); - } - - private native void setStatsPuller(int atomTag, long timeoutMillis, long coolDownMillis, - int pullReturnVal, long latencyMillis, int atomPerPull); - - private native void clearStatsPuller(int atomTag); -} - diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java deleted file mode 100644 index b5afb94886de..000000000000 --- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2019 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 com.android.internal.os.statsd.libstats; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.StatsManager; -import android.util.Log; - -import com.android.internal.os.StatsdConfigProto.AtomMatcher; -import com.android.internal.os.StatsdConfigProto.FieldValueMatcher; -import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; -import com.android.internal.os.StatsdConfigProto.StatsdConfig; -import com.android.os.AtomsProto.AppBreadcrumbReported; -import com.android.os.AtomsProto.Atom; -import com.android.os.StatsLog.ConfigMetricsReport; -import com.android.os.StatsLog.ConfigMetricsReportList; -import com.android.os.StatsLog.GaugeBucketInfo; -import com.android.os.StatsLog.GaugeMetricData; -import com.android.os.StatsLog.StatsLogReport; -import com.android.os.StatsLog.StatsdStatsReport; -import com.android.os.StatsLog.StatsdStatsReport.ConfigStats; - -import java.util.ArrayList; -import java.util.List; - -/** - * Util class for constructing statsd configs. - */ -public class StatsConfigUtils { - public static final String TAG = "statsd.StatsConfigUtils"; - public static final int SHORT_WAIT = 2_000; // 2 seconds. - - /** - * @return An empty StatsdConfig in serialized proto format. - */ - public static StatsdConfig.Builder getSimpleTestConfig(long configId) { - return StatsdConfig.newBuilder().setId(configId) - .addAllowedLogSource(StatsConfigUtils.class.getPackage().getName()); - } - - - public static boolean verifyValidConfigExists(StatsManager statsManager, long configId) { - StatsdStatsReport report = null; - try { - report = StatsdStatsReport.parser().parseFrom(statsManager.getStatsMetadata()); - } catch (Exception e) { - Log.e(TAG, "getMetadata failed", e); - } - assertThat(report).isNotNull(); - boolean foundConfig = false; - for (ConfigStats configStats : report.getConfigStatsList()) { - if (configStats.getId() == configId && configStats.getIsValid() - && configStats.getDeletionTimeSec() == 0) { - foundConfig = true; - } - } - return foundConfig; - } - - public static AtomMatcher getAppBreadcrumbMatcher(long id, int label) { - return AtomMatcher.newBuilder() - .setId(id) - .setSimpleAtomMatcher( - SimpleAtomMatcher.newBuilder() - .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER) - .addFieldValueMatcher(FieldValueMatcher.newBuilder() - .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER) - .setEqInt(label) - ) - ) - .build(); - } - - public static ConfigMetricsReport getConfigMetricsReport(StatsManager statsManager, - long configId) { - ConfigMetricsReportList reportList = null; - try { - reportList = ConfigMetricsReportList.parser() - .parseFrom(statsManager.getReports(configId)); - } catch (Exception e) { - Log.e(TAG, "getData failed", e); - } - assertThat(reportList).isNotNull(); - assertThat(reportList.getReportsCount()).isEqualTo(1); - ConfigMetricsReport report = reportList.getReports(0); - assertThat(report.getDumpReportReason()) - .isEqualTo(ConfigMetricsReport.DumpReportReason.GET_DATA_CALLED); - return report; - - } - public static List<Atom> getGaugeMetricDataList(ConfigMetricsReport report) { - List<Atom> data = new ArrayList<>(); - for (StatsLogReport metric : report.getMetricsList()) { - for (GaugeMetricData gaugeMetricData : metric.getGaugeMetrics().getDataList()) { - for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) { - for (Atom atom : bucketInfo.getAtomList()) { - data.add(atom); - } - } - } - } - return data; - } - - public static List<Atom> getGaugeMetricDataList(StatsManager statsManager, long configId) { - ConfigMetricsReport report = getConfigMetricsReport(statsManager, configId); - return getGaugeMetricDataList(report); - } -} - |