Merge changes I1510e44b,I9313299e,I7df5c644
* changes: Update setBroadcastSubscriber Update activeConfigsChangedBroadcast Creating PendingIntentRef
This commit is contained in:
committed by
Android (Google) Code Review
commit
89e95d5b5f
@@ -18,6 +18,7 @@
|
||||
filegroup {
|
||||
name: "statsd_aidl",
|
||||
srcs: [
|
||||
"android/os/IPendingIntentRef.aidl",
|
||||
"android/os/IPullAtomCallback.aidl",
|
||||
"android/os/IPullAtomResultReceiver.aidl",
|
||||
"android/os/IStatsCompanionService.aidl",
|
||||
|
||||
46
apex/statsd/aidl/android/os/IPendingIntentRef.aidl
Normal file
46
apex/statsd/aidl/android/os/IPendingIntentRef.aidl
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.StatsDimensionsValue;
|
||||
|
||||
/**
|
||||
* 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 StatsDimensionsValue dimensionsValue);
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package android.os;
|
||||
|
||||
import android.os.IPullAtomCallback;
|
||||
import android.os.StatsDimensionsValue;
|
||||
import android.os.StatsLogEventWrapper;
|
||||
|
||||
/**
|
||||
@@ -66,24 +65,6 @@ interface IStatsCompanionService {
|
||||
/** Pull the specified data. Results will be sent to statsd when complete. */
|
||||
StatsLogEventWrapper[] pullData(int pullCode);
|
||||
|
||||
/** Send a broadcast to the specified PendingIntent's as IBinder that it should getData now. */
|
||||
oneway void sendDataBroadcast(in IBinder intentSender, long lastReportTimeNs);
|
||||
|
||||
/**
|
||||
* Send a broadcast to the specified PendingIntent's as IBinder notifying it that the list
|
||||
* of active configs has changed.
|
||||
*/
|
||||
oneway void sendActiveConfigsChangedBroadcast(in IBinder intentSender, in long[] configIds);
|
||||
|
||||
/**
|
||||
* Requests StatsCompanionService to send a broadcast using the given intentSender
|
||||
* (which should cast to an IIntentSender), along with the other information specified.
|
||||
*/
|
||||
oneway void sendSubscriberBroadcast(in IBinder intentSender, long configUid, long configId,
|
||||
long subscriptionId, long subscriptionRuleId,
|
||||
in String[] cookies,
|
||||
in StatsDimensionsValue dimensionsValue);
|
||||
|
||||
/** Tells StatsCompaionService to grab the uid map snapshot and send it to statsd. */
|
||||
oneway void triggerUidSnapshot();
|
||||
|
||||
|
||||
@@ -30,11 +30,18 @@ interface IStatsManagerService {
|
||||
* 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.
|
||||
* Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
|
||||
*/
|
||||
void setDataFetchOperation(long configKey, in PendingIntent pendingIntent,
|
||||
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
|
||||
@@ -45,6 +52,13 @@ interface IStatsManagerService {
|
||||
*/
|
||||
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.
|
||||
@@ -58,8 +72,17 @@ interface IStatsManagerService {
|
||||
* 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.
|
||||
* 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);
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.os;
|
||||
|
||||
import android.os.IStatsPullerCallback;
|
||||
import android.os.IPendingIntentRef;
|
||||
import android.os.IPullAtomCallback;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
@@ -114,14 +115,15 @@ interface IStatsd {
|
||||
*
|
||||
* Requires Manifest.permission.DUMP.
|
||||
*/
|
||||
void setDataFetchOperation(long configKey, in IBinder intentSender, in String packageName);
|
||||
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 configKey, in String packageName);
|
||||
void removeDataFetchOperation(long configId, int callingUid);
|
||||
|
||||
/**
|
||||
* Registers the given pending intent for this packagename. This intent is invoked when the
|
||||
@@ -131,14 +133,14 @@ interface IStatsd {
|
||||
*
|
||||
* Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
|
||||
*/
|
||||
long[] setActiveConfigsChangedOperation(in IBinder intentSender, in String packageName);
|
||||
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(in String packageName);
|
||||
void removeActiveConfigsChangedOperation(int callingUid);
|
||||
|
||||
/**
|
||||
* Removes the configuration with the matching config key. No-op if this config key does not
|
||||
@@ -149,34 +151,31 @@ interface IStatsd {
|
||||
void removeConfiguration(in long configKey, in String packageName);
|
||||
|
||||
/**
|
||||
* Set the IIntentSender (i.e. PendingIntent) to be used when broadcasting subscriber
|
||||
* 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 configKey, and that in this 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 intentSender with
|
||||
* that subscriberId (for that config), so that this intentSender is used to send the broadcast
|
||||
* 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 intentSender is stored.
|
||||
*
|
||||
* intentSender must be convertible into an IntentSender using IntentSender(IBinder)
|
||||
* and cannot be null.
|
||||
* time statsd starts. Later calls overwrite previous calls; only one pendingIntent is stored.
|
||||
*
|
||||
* Requires Manifest.permission.DUMP.
|
||||
*/
|
||||
void setBroadcastSubscriber(long configKey, long subscriberId, in IBinder intentSender,
|
||||
in String packageName);
|
||||
void setBroadcastSubscriber(long configId, long subscriberId, in IPendingIntentRef pir,
|
||||
int callingUid);
|
||||
|
||||
/**
|
||||
* Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair.
|
||||
* Undoes setBroadcastSubscriber() for the (configId, subscriberId) pair.
|
||||
* Any broadcasts associated with subscriberId will henceforth not be sent.
|
||||
* No-op if this (configKey, subsriberId) pair was not associated with an IntentSender.
|
||||
* No-op if this (configKey, subscriberId) pair was not associated with an PendingIntentRef.
|
||||
*
|
||||
* Requires Manifest.permission.DUMP.
|
||||
*/
|
||||
void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName);
|
||||
void unsetBroadcastSubscriber(long configId, long subscriberId, int callingUid);
|
||||
|
||||
/**
|
||||
* Apps can send an atom via this application breadcrumb with the specified label and state for
|
||||
|
||||
@@ -16,11 +16,21 @@
|
||||
|
||||
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.util.Slog;
|
||||
|
||||
import com.android.server.SystemService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -28,6 +38,13 @@ public class StatsCompanion {
|
||||
private static final String TAG = "StatsCompanion";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
static void enforceStatsCompanionPermission(Context context) {
|
||||
if (Binder.getCallingPid() == Process.myPid()) {
|
||||
return;
|
||||
}
|
||||
context.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}.
|
||||
*/
|
||||
@@ -63,7 +80,97 @@ public class StatsCompanion {
|
||||
super.onBootPhase(phase);
|
||||
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||
mStatsCompanionService.systemReady();
|
||||
mStatsManagerService.systemReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
enforceStatsCompanionPermission(mContext);
|
||||
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) {
|
||||
Slog.w(TAG, "Unable to send PendingIntent");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActiveConfigsChangedBroadcast(long[] configIds) {
|
||||
enforceStatsCompanionPermission(mContext);
|
||||
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) {
|
||||
Slog.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
|
||||
}
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Slog.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, StatsDimensionsValue dimensionsValue) {
|
||||
enforceStatsCompanionPermission(mContext);
|
||||
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) {
|
||||
Slog.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) {
|
||||
Slog.w(TAG,
|
||||
"Unable to send using PendingIntent from uid " + configUid
|
||||
+ "; presumably it had been cancelled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -85,11 +84,9 @@ import android.os.IThermalService;
|
||||
import android.os.Looper;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.StatFs;
|
||||
import android.os.StatsDimensionsValue;
|
||||
import android.os.StatsLogEventWrapper;
|
||||
import android.os.SynchronousResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
@@ -203,18 +200,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
private static final int PACKAGE_NAME_FIELD_ID = 4;
|
||||
private static final int INSTALLER_FIELD_ID = 5;
|
||||
|
||||
public static final int CODE_DATA_BROADCAST = 1;
|
||||
public static final int CODE_SUBSCRIBER_BROADCAST = 1;
|
||||
public static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME";
|
||||
public static final int DEATH_THRESHOLD = 10;
|
||||
/**
|
||||
* Which native processes to snapshot memory for.
|
||||
@@ -454,72 +439,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDataBroadcast(IBinder intentSenderBinder, long lastReportTimeNs) {
|
||||
enforceCallingPermission();
|
||||
IntentSender intentSender = new IntentSender(intentSenderBinder);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs);
|
||||
try {
|
||||
intentSender.sendIntent(mContext, CODE_DATA_BROADCAST, intent, null, null);
|
||||
} catch (IntentSender.SendIntentException e) {
|
||||
Slog.w(TAG, "Unable to send using IntentSender");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActiveConfigsChangedBroadcast(IBinder intentSenderBinder, long[] configIds) {
|
||||
enforceCallingPermission();
|
||||
IntentSender intentSender = new IntentSender(intentSenderBinder);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds);
|
||||
try {
|
||||
intentSender.sendIntent(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
|
||||
}
|
||||
} catch (IntentSender.SendIntentException e) {
|
||||
Slog.w(TAG, "Unable to send active configs changed broadcast using IntentSender");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey,
|
||||
long subscriptionId, long subscriptionRuleId, String[] cookies,
|
||||
StatsDimensionsValue dimensionsValue) {
|
||||
enforceCallingPermission();
|
||||
IntentSender intentSender = new IntentSender(intentSenderBinder);
|
||||
Intent intent =
|
||||
new Intent()
|
||||
.putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
|
||||
.putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configKey)
|
||||
.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);
|
||||
for (String cookie : cookies) {
|
||||
cookieList.add(cookie);
|
||||
}
|
||||
intent.putStringArrayListExtra(
|
||||
StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
String.format("Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
|
||||
configUid, configKey, subscriptionId, subscriptionRuleId,
|
||||
Arrays.toString(cookies),
|
||||
dimensionsValue));
|
||||
}
|
||||
try {
|
||||
intentSender.sendIntent(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
|
||||
} catch (IntentSender.SendIntentException e) {
|
||||
Slog.w(TAG,
|
||||
"Unable to send using IntentSender from uid " + configUid
|
||||
+ "; presumably it had been cancelled.");
|
||||
}
|
||||
}
|
||||
|
||||
private final static int[] toIntArray(List<Integer> list) {
|
||||
int[] ret = new int[list.size()];
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
@@ -770,7 +689,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void setAnomalyAlarm(long timestampMs) {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs);
|
||||
final long callingToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -786,7 +705,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelAnomalyAlarm() {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) Slog.d(TAG, "Cancelling anomaly alarm");
|
||||
final long callingToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -798,7 +717,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void setAlarmForSubscriberTriggering(long timestampMs) {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
"Setting periodic alarm in about " + (timestampMs
|
||||
@@ -817,7 +736,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelAlarmForSubscriberTriggering() {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Cancelling periodic alarm");
|
||||
}
|
||||
@@ -831,7 +750,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void setPullingAlarm(long nextPullTimeMs) {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Setting pulling alarm in about "
|
||||
+ (nextPullTimeMs - SystemClock.elapsedRealtime()));
|
||||
@@ -849,7 +768,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelPullingAlarm() {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Cancelling pulling alarm");
|
||||
}
|
||||
@@ -2455,7 +2374,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
*/
|
||||
@Override // Binder call
|
||||
public StatsLogEventWrapper[] pullData(int tagId) {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Pulling " + tagId);
|
||||
}
|
||||
@@ -2690,12 +2609,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override // Binder call
|
||||
public void statsdReady() {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "learned that statsdReady");
|
||||
}
|
||||
sayHiToStatsd(); // tell statsd that we're ready too and link to it
|
||||
mStatsManagerService.systemReady();
|
||||
mContext.sendBroadcastAsUser(new Intent(StatsManager.ACTION_STATSD_STARTED)
|
||||
.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
|
||||
UserHandle.SYSTEM, android.Manifest.permission.DUMP);
|
||||
@@ -2703,7 +2621,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
|
||||
@Override
|
||||
public void triggerUidSnapshot() {
|
||||
enforceCallingPermission();
|
||||
StatsCompanion.enforceStatsCompanionPermission(mContext);
|
||||
synchronized (sStatsdLock) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -2716,13 +2634,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void enforceCallingPermission() {
|
||||
if (Binder.getCallingPid() == Process.myPid()) {
|
||||
return;
|
||||
}
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPullAtomCallback(int atomTag, long coolDownNs, long timeoutNs,
|
||||
int[] additiveFields, IPullAtomCallback pullerCallback) {
|
||||
@@ -2817,6 +2728,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
+ "alive.");
|
||||
return;
|
||||
}
|
||||
mStatsManagerService.statsdReady(sStatsd);
|
||||
if (DEBUG) Slog.d(TAG, "Saying hi to statsd");
|
||||
try {
|
||||
sStatsd.statsCompanionReady();
|
||||
@@ -2928,6 +2840,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
if (looperStats != null) {
|
||||
looperStats.reset();
|
||||
}
|
||||
mStatsManagerService.statsdNotReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,18 +16,28 @@
|
||||
|
||||
package com.android.server.stats;
|
||||
|
||||
import static com.android.server.stats.StatsCompanion.PendingIntentRef;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.os.Binder;
|
||||
import android.os.IStatsManagerService;
|
||||
import android.os.IStatsd;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
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 {
|
||||
@@ -35,41 +45,203 @@ public class StatsManagerService extends IStatsManagerService.Stub {
|
||||
private static final String TAG = "StatsManagerService";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@GuardedBy("sStatsdLock")
|
||||
private static IStatsd sStatsd;
|
||||
private static final Object sStatsdLock = new Object();
|
||||
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 int mUid;
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataFetchOperation(long configKey, PendingIntent pendingIntent,
|
||||
public void setDataFetchOperation(long configId, PendingIntent pendingIntent,
|
||||
String packageName) {
|
||||
// no-op
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setDataFetchOperation");
|
||||
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) {
|
||||
Slog.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) {
|
||||
Slog.e(TAG, "Failed to removeDataFetchOperation with statsd");
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent,
|
||||
String packageName) {
|
||||
// no-op
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setActiveConfigsChangedOperation");
|
||||
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);
|
||||
}
|
||||
return new long[]{};
|
||||
try {
|
||||
IStatsd statsd = getStatsdNonblocking();
|
||||
if (statsd != null) {
|
||||
return statsd.setActiveConfigsChangedOperation(pir, callingUid);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to setActiveConfigsChangedOperation with statsd");
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
return new long[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBroadcastSubscriber(long configKey, long subscriberId,
|
||||
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) {
|
||||
Slog.e(TAG, "Failed to removeActiveConfigsChangedOperation with statsd");
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBroadcastSubscriber(long configId, long subscriberId,
|
||||
PendingIntent pendingIntent, String packageName) {
|
||||
//no-op
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setBroadcastSubscriber");
|
||||
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) {
|
||||
Slog.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) {
|
||||
Slog.e(TAG, "Failed to unsetBroadcastSubscriber with statsd");
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,37 +249,130 @@ public class StatsManagerService extends IStatsManagerService.Stub {
|
||||
mStatsCompanionService = statsCompanionService;
|
||||
}
|
||||
|
||||
void systemReady() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "statsdReady");
|
||||
private void enforceDumpAndUsageStatsPermission(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);
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
setupStatsManagerService();
|
||||
}
|
||||
|
||||
private void setupStatsManagerService() {
|
||||
synchronized (sStatsdLock) {
|
||||
if (sStatsd != null) {
|
||||
if (DEBUG) {
|
||||
Slog.e(TAG, "Trying to fetch statsd, but it was already fetched",
|
||||
new IllegalStateException(
|
||||
"sStatsd is not null when being fetched"));
|
||||
/**
|
||||
* 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) {
|
||||
Slog.e(TAG, "wait for statsd interrupted");
|
||||
}
|
||||
return;
|
||||
}
|
||||
sStatsd = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
|
||||
if (sStatsd == null) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Failed to get stats service.");
|
||||
}
|
||||
return;
|
||||
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;
|
||||
}
|
||||
// Since we do not want to make an IPC with the a lock held, we first create local deep
|
||||
// copies of the data with the lock held before iterating through the maps.
|
||||
ArrayMap<ConfigKey, PendingIntentRef> dataFetchCopy;
|
||||
ArrayMap<Integer, PendingIntentRef> activeConfigsChangedCopy;
|
||||
ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> broadcastSubscriberCopy;
|
||||
synchronized (mLock) {
|
||||
dataFetchCopy = new ArrayMap<>(mDataFetchPirMap);
|
||||
activeConfigsChangedCopy = new ArrayMap<>(mActiveConfigsPirMap);
|
||||
broadcastSubscriberCopy = new ArrayMap<>();
|
||||
for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry
|
||||
: mBroadcastSubscriberPirMap.entrySet()) {
|
||||
broadcastSubscriberCopy.put(entry.getKey(), new ArrayMap<>(entry.getValue()));
|
||||
}
|
||||
// Assume statsd is ready since this is called form statscompanion, link to statsd.
|
||||
}
|
||||
for (Map.Entry<ConfigKey, PendingIntentRef> entry : dataFetchCopy.entrySet()) {
|
||||
ConfigKey key = entry.getKey();
|
||||
try {
|
||||
sStatsd.asBinder().linkToDeath((IBinder.DeathRecipient) () -> {
|
||||
sStatsd = null;
|
||||
}, 0);
|
||||
statsd.setDataFetchOperation(key.getConfigId(), entry.getValue(), key.getUid());
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e);
|
||||
Slog.e(TAG, "Failed to setDataFetchOperation from pirMap");
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Integer, PendingIntentRef> entry
|
||||
: activeConfigsChangedCopy.entrySet()) {
|
||||
try {
|
||||
statsd.setActiveConfigsChangedOperation(entry.getValue(), entry.getKey());
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to setActiveConfigsChangedOperation from pirMap");
|
||||
}
|
||||
}
|
||||
for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry
|
||||
: broadcastSubscriberCopy.entrySet()) {
|
||||
for (Map.Entry<Long, PendingIntentRef> subscriberEntry : entry.getValue().entrySet()) {
|
||||
ConfigKey configKey = entry.getKey();
|
||||
try {
|
||||
statsd.setBroadcastSubscriber(configKey.getConfigId(), subscriberEntry.getKey(),
|
||||
subscriberEntry.getValue(), configKey.getUid());
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to setBroadcastSubscriber from pirMap");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,33 +170,32 @@ StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQ
|
||||
mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
|
||||
getElapsedRealtimeNs(),
|
||||
[this](const ConfigKey& key) {
|
||||
sp<IStatsCompanionService> sc = getStatsCompanionService();
|
||||
auto receiver = mConfigManager->GetConfigReceiver(key);
|
||||
if (sc == nullptr) {
|
||||
VLOG("Could not find StatsCompanionService");
|
||||
sp<IPendingIntentRef> receiver = mConfigManager->GetConfigReceiver(key);
|
||||
if (receiver == nullptr) {
|
||||
VLOG("Could not find a broadcast receiver for %s",
|
||||
key.ToString().c_str());
|
||||
return false;
|
||||
} else if (receiver == nullptr) {
|
||||
VLOG("Statscompanion could not find a broadcast receiver for %s",
|
||||
key.ToString().c_str());
|
||||
return false;
|
||||
} else {
|
||||
sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
|
||||
} else if (receiver->sendDataBroadcast(
|
||||
mProcessor->getLastReportTimeNs(key)).isOk()) {
|
||||
return true;
|
||||
} else {
|
||||
VLOG("Failed to send a broadcast for receiver %s",
|
||||
key.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[this](const int& uid, const vector<int64_t>& activeConfigs) {
|
||||
auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
|
||||
sp<IStatsCompanionService> sc = getStatsCompanionService();
|
||||
if (sc == nullptr) {
|
||||
VLOG("Could not access statsCompanion");
|
||||
return false;
|
||||
} else if (receiver == nullptr) {
|
||||
sp<IPendingIntentRef> receiver =
|
||||
mConfigManager->GetActiveConfigsChangedReceiver(uid);
|
||||
if (receiver == nullptr) {
|
||||
VLOG("Could not find receiver for uid %d", uid);
|
||||
return false;
|
||||
} else {
|
||||
sc->sendActiveConfigsChangedBroadcast(receiver, activeConfigs);
|
||||
} else if (receiver->sendActiveConfigsChangedBroadcast(activeConfigs).isOk()) {
|
||||
VLOG("StatsService::active configs broadcast succeeded for uid %d" , uid);
|
||||
return true;
|
||||
} else {
|
||||
VLOG("StatsService::active configs broadcast failed for uid %d" , uid);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -574,18 +573,19 @@ status_t StatsService::cmd_trigger_broadcast(int out, Vector<String8>& args) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
ConfigKey key(uid, StrToInt64(name));
|
||||
auto receiver = mConfigManager->GetConfigReceiver(key);
|
||||
sp<IStatsCompanionService> sc = getStatsCompanionService();
|
||||
if (sc == nullptr) {
|
||||
VLOG("Could not access statsCompanion");
|
||||
} else if (receiver == nullptr) {
|
||||
VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str())
|
||||
} else {
|
||||
sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
|
||||
sp<IPendingIntentRef> receiver = mConfigManager->GetConfigReceiver(key);
|
||||
if (receiver == nullptr) {
|
||||
VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
} else if (receiver->sendDataBroadcast(
|
||||
mProcessor->getLastReportTimeNs(key)).isOk()) {
|
||||
VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(),
|
||||
args[2].c_str());
|
||||
} else {
|
||||
VLOG("StatsService::trigger broadcast failed to %s, %s", args[1].c_str(),
|
||||
args[2].c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -629,15 +629,15 @@ status_t StatsService::cmd_trigger_active_config_broadcast(int out, Vector<Strin
|
||||
}
|
||||
}
|
||||
}
|
||||
auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
|
||||
sp<IStatsCompanionService> sc = getStatsCompanionService();
|
||||
if (sc == nullptr) {
|
||||
VLOG("Could not access statsCompanion");
|
||||
} else if (receiver == nullptr) {
|
||||
sp<IPendingIntentRef> receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
|
||||
if (receiver == nullptr) {
|
||||
VLOG("Could not find receiver for uid %d", uid);
|
||||
} else {
|
||||
sc->sendActiveConfigsChangedBroadcast(receiver, configIds);
|
||||
return UNKNOWN_ERROR;
|
||||
} else if (receiver->sendActiveConfigsChangedBroadcast(configIds).isOk()) {
|
||||
VLOG("StatsService::trigger active configs changed broadcast succeeded for uid %d" , uid);
|
||||
} else {
|
||||
VLOG("StatsService::trigger active configs changed broadcast failed for uid %d", uid);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -1111,7 +1111,6 @@ Status StatsService::statsCompanionReady() {
|
||||
mPullerManager->SetStatsCompanionService(statsCompanion);
|
||||
mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion);
|
||||
mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion);
|
||||
SubscriberReporter::getInstance().setStatsCompanionService(statsCompanion);
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
@@ -1185,23 +1184,21 @@ bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<ui
|
||||
return true;
|
||||
}
|
||||
|
||||
Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) {
|
||||
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
|
||||
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
ConfigKey configKey(ipc->getCallingUid(), key);
|
||||
Status StatsService::removeDataFetchOperation(int64_t key,
|
||||
const int32_t callingUid) {
|
||||
ENFORCE_UID(AID_SYSTEM);
|
||||
ConfigKey configKey(callingUid, key);
|
||||
mConfigManager->RemoveConfigReceiver(configKey);
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
Status StatsService::setDataFetchOperation(int64_t key,
|
||||
const sp<android::IBinder>& intentSender,
|
||||
const String16& packageName) {
|
||||
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
|
||||
const sp<IPendingIntentRef>& pir,
|
||||
const int32_t callingUid) {
|
||||
ENFORCE_UID(AID_SYSTEM);
|
||||
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
ConfigKey configKey(ipc->getCallingUid(), key);
|
||||
mConfigManager->SetConfigReceiver(configKey, intentSender);
|
||||
ConfigKey configKey(callingUid, key);
|
||||
mConfigManager->SetConfigReceiver(configKey, pir);
|
||||
if (StorageManager::hasConfigMetricsReport(configKey)) {
|
||||
VLOG("StatsService::setDataFetchOperation marking configKey %s to dump reports on disk",
|
||||
configKey.ToString().c_str());
|
||||
@@ -1210,27 +1207,24 @@ Status StatsService::setDataFetchOperation(int64_t key,
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
Status StatsService::setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender,
|
||||
const String16& packageName,
|
||||
Status StatsService::setActiveConfigsChangedOperation(const sp<IPendingIntentRef>& pir,
|
||||
const int32_t callingUid,
|
||||
vector<int64_t>* output) {
|
||||
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
|
||||
ENFORCE_UID(AID_SYSTEM);
|
||||
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
int uid = ipc->getCallingUid();
|
||||
mConfigManager->SetActiveConfigsChangedReceiver(uid, intentSender);
|
||||
mConfigManager->SetActiveConfigsChangedReceiver(callingUid, pir);
|
||||
if (output != nullptr) {
|
||||
mProcessor->GetActiveConfigs(uid, *output);
|
||||
mProcessor->GetActiveConfigs(callingUid, *output);
|
||||
} else {
|
||||
ALOGW("StatsService::setActiveConfigsChanged output was nullptr");
|
||||
}
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
Status StatsService::removeActiveConfigsChangedOperation(const String16& packageName) {
|
||||
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
|
||||
Status StatsService::removeActiveConfigsChangedOperation(const int32_t callingUid) {
|
||||
ENFORCE_UID(AID_SYSTEM);
|
||||
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
mConfigManager->RemoveActiveConfigsChangedReceiver(ipc->getCallingUid());
|
||||
mConfigManager->RemoveActiveConfigsChangedReceiver(callingUid);
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
@@ -1246,26 +1240,24 @@ Status StatsService::removeConfiguration(int64_t key, const String16& packageNam
|
||||
|
||||
Status StatsService::setBroadcastSubscriber(int64_t configId,
|
||||
int64_t subscriberId,
|
||||
const sp<android::IBinder>& intentSender,
|
||||
const String16& packageName) {
|
||||
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
|
||||
const sp<IPendingIntentRef>& pir,
|
||||
const int32_t callingUid) {
|
||||
ENFORCE_UID(AID_SYSTEM);
|
||||
|
||||
VLOG("StatsService::setBroadcastSubscriber called.");
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
ConfigKey configKey(ipc->getCallingUid(), configId);
|
||||
ConfigKey configKey(callingUid, configId);
|
||||
SubscriberReporter::getInstance()
|
||||
.setBroadcastSubscriber(configKey, subscriberId, intentSender);
|
||||
.setBroadcastSubscriber(configKey, subscriberId, pir);
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
Status StatsService::unsetBroadcastSubscriber(int64_t configId,
|
||||
int64_t subscriberId,
|
||||
const String16& packageName) {
|
||||
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
|
||||
const int32_t callingUid) {
|
||||
ENFORCE_UID(AID_SYSTEM);
|
||||
|
||||
VLOG("StatsService::unsetBroadcastSubscriber called.");
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
ConfigKey configKey(ipc->getCallingUid(), configId);
|
||||
ConfigKey configKey(callingUid, configId);
|
||||
SubscriberReporter::getInstance()
|
||||
.unsetBroadcastSubscriber(configKey, subscriberId);
|
||||
return Status::ok();
|
||||
@@ -1631,7 +1623,6 @@ void StatsService::binderDied(const wp <IBinder>& who) {
|
||||
}
|
||||
mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
|
||||
mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
|
||||
SubscriberReporter::getInstance().setStatsCompanionService(nullptr);
|
||||
mPullerManager->SetStatsCompanionService(nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <android/frameworks/stats/1.0/IStats.h>
|
||||
#include <android/frameworks/stats/1.0/types.h>
|
||||
#include <android/os/BnStatsd.h>
|
||||
#include <android/os/IPendingIntentRef.h>
|
||||
#include <android/os/IStatsCompanionService.h>
|
||||
#include <android/os/IStatsd.h>
|
||||
#include <binder/IResultReceiver.h>
|
||||
@@ -121,26 +122,26 @@ public:
|
||||
* Binder call to let clients register the data fetch operation for a configuration.
|
||||
*/
|
||||
virtual Status setDataFetchOperation(int64_t key,
|
||||
const sp<android::IBinder>& intentSender,
|
||||
const String16& packageName) override;
|
||||
const sp<IPendingIntentRef>& pir,
|
||||
const int32_t callingUid) override;
|
||||
|
||||
/**
|
||||
* Binder call to remove the data fetch operation for the specified config key.
|
||||
*/
|
||||
virtual Status removeDataFetchOperation(int64_t key,
|
||||
const String16& packageName) override;
|
||||
const int32_t callingUid) override;
|
||||
|
||||
/**
|
||||
* Binder call to let clients register the active configs changed operation.
|
||||
*/
|
||||
virtual Status setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender,
|
||||
const String16& packageName,
|
||||
virtual Status setActiveConfigsChangedOperation(const sp<IPendingIntentRef>& pir,
|
||||
const int32_t callingUid,
|
||||
vector<int64_t>* output) override;
|
||||
|
||||
/**
|
||||
* Binder call to remove the active configs changed operation for the specified package..
|
||||
*/
|
||||
virtual Status removeActiveConfigsChangedOperation(const String16& packageName) override;
|
||||
virtual Status removeActiveConfigsChangedOperation(const int32_t callingUid) override;
|
||||
/**
|
||||
* Binder call to allow clients to remove the specified configuration.
|
||||
*/
|
||||
@@ -148,20 +149,19 @@ public:
|
||||
const String16& packageName) override;
|
||||
|
||||
/**
|
||||
* Binder call to associate the given config's subscriberId with the given intentSender.
|
||||
* intentSender must be convertible into an IntentSender (in Java) using IntentSender(IBinder).
|
||||
* Binder call to associate the given config's subscriberId with the given pendingIntentRef.
|
||||
*/
|
||||
virtual Status setBroadcastSubscriber(int64_t configId,
|
||||
int64_t subscriberId,
|
||||
const sp<android::IBinder>& intentSender,
|
||||
const String16& packageName) override;
|
||||
const sp<IPendingIntentRef>& pir,
|
||||
const int32_t callingUid) override;
|
||||
|
||||
/**
|
||||
* Binder call to unassociate the given config's subscriberId with any intentSender.
|
||||
* Binder call to unassociate the given config's subscriberId with any pendingIntentRef.
|
||||
*/
|
||||
virtual Status unsetBroadcastSubscriber(int64_t configId,
|
||||
int64_t subscriberId,
|
||||
const String16& packageName) override;
|
||||
const int32_t callingUid) override;
|
||||
|
||||
/** Inform statsCompanion that statsd is ready. */
|
||||
virtual void sayHiToStatsCompanion();
|
||||
|
||||
@@ -46,6 +46,41 @@ using std::vector;
|
||||
using android::base::StringPrintf;
|
||||
using std::unique_ptr;
|
||||
|
||||
class ConfigReceiverDeathRecipient : public android::IBinder::DeathRecipient {
|
||||
public:
|
||||
ConfigReceiverDeathRecipient(sp<ConfigManager> configManager, const ConfigKey& configKey):
|
||||
mConfigManager(configManager),
|
||||
mConfigKey(configKey) {}
|
||||
~ConfigReceiverDeathRecipient() override = default;
|
||||
private:
|
||||
sp<ConfigManager> mConfigManager;
|
||||
ConfigKey mConfigKey;
|
||||
|
||||
void binderDied(const android::wp<android::IBinder>& who) override {
|
||||
if (IInterface::asBinder(mConfigManager->GetConfigReceiver(mConfigKey)) == who.promote()) {
|
||||
mConfigManager->RemoveConfigReceiver(mConfigKey);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ActiveConfigChangedReceiverDeathRecipient : public android::IBinder::DeathRecipient {
|
||||
public:
|
||||
ActiveConfigChangedReceiverDeathRecipient(sp<ConfigManager> configManager, const int uid):
|
||||
mConfigManager(configManager),
|
||||
mUid(uid) {}
|
||||
~ActiveConfigChangedReceiverDeathRecipient() override = default;
|
||||
private:
|
||||
sp<ConfigManager> mConfigManager;
|
||||
int mUid;
|
||||
|
||||
void binderDied(const android::wp<android::IBinder>& who) override {
|
||||
if (IInterface::asBinder(mConfigManager->GetActiveConfigsChangedReceiver(mUid))
|
||||
== who.promote()) {
|
||||
mConfigManager->RemoveActiveConfigsChangedReceiver(mUid);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ConfigManager::ConfigManager() {
|
||||
}
|
||||
|
||||
@@ -118,9 +153,11 @@ void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& confi
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
|
||||
void ConfigManager::SetConfigReceiver(const ConfigKey& key,
|
||||
const sp<IPendingIntentRef>& pir) {
|
||||
lock_guard<mutex> lock(mMutex);
|
||||
mConfigReceivers[key] = intentSender;
|
||||
mConfigReceivers[key] = pir;
|
||||
IInterface::asBinder(pir)->linkToDeath(new ConfigReceiverDeathRecipient(this, key));
|
||||
}
|
||||
|
||||
void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
|
||||
@@ -129,9 +166,11 @@ void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
|
||||
}
|
||||
|
||||
void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
|
||||
const sp<IBinder>& intentSender) {
|
||||
const sp<IPendingIntentRef>& pir) {
|
||||
lock_guard<mutex> lock(mMutex);
|
||||
mActiveConfigsChangedReceivers[uid] = intentSender;
|
||||
mActiveConfigsChangedReceivers[uid] = pir;
|
||||
IInterface::asBinder(pir)->linkToDeath(
|
||||
new ActiveConfigChangedReceiverDeathRecipient(this, uid));
|
||||
}
|
||||
|
||||
void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
|
||||
@@ -266,7 +305,7 @@ vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
|
||||
const sp<IPendingIntentRef> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
|
||||
lock_guard<mutex> lock(mMutex);
|
||||
|
||||
auto it = mConfigReceivers.find(key);
|
||||
@@ -277,7 +316,7 @@ const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key
|
||||
}
|
||||
}
|
||||
|
||||
const sp<android::IBinder> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
|
||||
const sp<IPendingIntentRef> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
|
||||
lock_guard<mutex> lock(mMutex);
|
||||
|
||||
auto it = mActiveConfigsChangedReceivers.find(uid);
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "binder/IBinder.h"
|
||||
#include "config/ConfigKey.h"
|
||||
#include "config/ConfigListener.h"
|
||||
|
||||
#include <android/os/IPendingIntentRef.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
@@ -64,12 +64,12 @@ public:
|
||||
/**
|
||||
* Sets the broadcast receiver for a configuration key.
|
||||
*/
|
||||
void SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender);
|
||||
void SetConfigReceiver(const ConfigKey& key, const sp<IPendingIntentRef>& pir);
|
||||
|
||||
/**
|
||||
* Returns the package name and class name representing the broadcast receiver for this config.
|
||||
*/
|
||||
const sp<android::IBinder> GetConfigReceiver(const ConfigKey& key) const;
|
||||
const sp<IPendingIntentRef> GetConfigReceiver(const ConfigKey& key) const;
|
||||
|
||||
/**
|
||||
* Returns all config keys registered.
|
||||
@@ -85,13 +85,13 @@ public:
|
||||
* Sets the broadcast receiver that is notified whenever the list of active configs
|
||||
* changes for this uid.
|
||||
*/
|
||||
void SetActiveConfigsChangedReceiver(const int uid, const sp<IBinder>& intentSender);
|
||||
void SetActiveConfigsChangedReceiver(const int uid, const sp<IPendingIntentRef>& pir);
|
||||
|
||||
/**
|
||||
* Returns the broadcast receiver for active configs changed for this uid.
|
||||
*/
|
||||
|
||||
const sp<IBinder> GetActiveConfigsChangedReceiver(const int uid) const;
|
||||
const sp<IPendingIntentRef> GetActiveConfigsChangedReceiver(const int uid) const;
|
||||
|
||||
/**
|
||||
* Erase any active configs changed broadcast receiver associated with this uid.
|
||||
@@ -141,16 +141,15 @@ private:
|
||||
std::map<int, std::set<ConfigKey>> mConfigs;
|
||||
|
||||
/**
|
||||
* Each config key can be subscribed by up to one receiver, specified as IBinder from
|
||||
* PendingIntent.
|
||||
* Each config key can be subscribed by up to one receiver, specified as IPendingIntentRef.
|
||||
*/
|
||||
std::map<ConfigKey, sp<android::IBinder>> mConfigReceivers;
|
||||
std::map<ConfigKey, sp<IPendingIntentRef>> mConfigReceivers;
|
||||
|
||||
/**
|
||||
* Each uid can be subscribed by up to one receiver to notify that the list of active configs
|
||||
* for this uid has changed. The receiver is specified as IBinder from PendingIntent.
|
||||
* for this uid has changed. The receiver is specified as IPendingIntentRef.
|
||||
*/
|
||||
std::map<int, sp<android::IBinder>> mActiveConfigsChangedReceivers;
|
||||
std::map<int, sp<IPendingIntentRef>> mActiveConfigsChangedReceivers;
|
||||
|
||||
/**
|
||||
* The ConfigListeners that will be told about changes.
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "SubscriberReporter.h"
|
||||
|
||||
using android::IBinder;
|
||||
using std::lock_guard;
|
||||
using std::unordered_map;
|
||||
|
||||
@@ -29,12 +28,32 @@ namespace statsd {
|
||||
|
||||
using std::vector;
|
||||
|
||||
class BroadcastSubscriberDeathRecipient : public android::IBinder::DeathRecipient {
|
||||
public:
|
||||
BroadcastSubscriberDeathRecipient(const ConfigKey& configKey, int64_t subscriberId):
|
||||
mConfigKey(configKey),
|
||||
mSubscriberId(subscriberId) {}
|
||||
~BroadcastSubscriberDeathRecipient() override = default;
|
||||
private:
|
||||
ConfigKey mConfigKey;
|
||||
int64_t mSubscriberId;
|
||||
|
||||
void binderDied(const android::wp<android::IBinder>& who) override {
|
||||
if (IInterface::asBinder(SubscriberReporter::getInstance().getBroadcastSubscriber(
|
||||
mConfigKey, mSubscriberId)) == who.promote()) {
|
||||
SubscriberReporter::getInstance().unsetBroadcastSubscriber(mConfigKey, mSubscriberId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void SubscriberReporter::setBroadcastSubscriber(const ConfigKey& configKey,
|
||||
int64_t subscriberId,
|
||||
const sp<IBinder>& intentSender) {
|
||||
const sp<IPendingIntentRef>& pir) {
|
||||
VLOG("SubscriberReporter::setBroadcastSubscriber called.");
|
||||
lock_guard<std::mutex> lock(mLock);
|
||||
mIntentMap[configKey][subscriberId] = intentSender;
|
||||
mIntentMap[configKey][subscriberId] = pir;
|
||||
IInterface::asBinder(pir)->linkToDeath(
|
||||
new BroadcastSubscriberDeathRecipient(configKey, subscriberId));
|
||||
}
|
||||
|
||||
void SubscriberReporter::unsetBroadcastSubscriber(const ConfigKey& configKey,
|
||||
@@ -97,18 +116,13 @@ void SubscriberReporter::alertBroadcastSubscriber(const ConfigKey& configKey,
|
||||
sendBroadcastLocked(it2->second, configKey, subscription, cookies, dimKey);
|
||||
}
|
||||
|
||||
void SubscriberReporter::sendBroadcastLocked(const sp<IBinder>& intentSender,
|
||||
void SubscriberReporter::sendBroadcastLocked(const sp<IPendingIntentRef>& pir,
|
||||
const ConfigKey& configKey,
|
||||
const Subscription& subscription,
|
||||
const vector<String16>& cookies,
|
||||
const MetricDimensionKey& dimKey) const {
|
||||
VLOG("SubscriberReporter::sendBroadcastLocked called.");
|
||||
if (mStatsCompanionService == nullptr) {
|
||||
ALOGW("Failed to send subscriber broadcast: could not access StatsCompanionService.");
|
||||
return;
|
||||
}
|
||||
mStatsCompanionService->sendSubscriberBroadcast(
|
||||
intentSender,
|
||||
pir->sendSubscriberBroadcast(
|
||||
configKey.GetUid(),
|
||||
configKey.GetId(),
|
||||
subscription.id(),
|
||||
@@ -117,6 +131,20 @@ void SubscriberReporter::sendBroadcastLocked(const sp<IBinder>& intentSender,
|
||||
getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
|
||||
}
|
||||
|
||||
sp<IPendingIntentRef> SubscriberReporter::getBroadcastSubscriber(const ConfigKey& configKey,
|
||||
int64_t subscriberId) {
|
||||
lock_guard<std::mutex> lock(mLock);
|
||||
auto subscriberMapIt = mIntentMap.find(configKey);
|
||||
if (subscriberMapIt == mIntentMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto pirMapIt = subscriberMapIt->second.find(subscriberId);
|
||||
if (pirMapIt == subscriberMapIt->second.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return pirMapIt->second;
|
||||
}
|
||||
|
||||
void getStatsDimensionsValueHelper(const vector<FieldValue>& dims, size_t* index, int depth,
|
||||
int prefix, vector<StatsDimensionsValue>* output) {
|
||||
size_t count = dims.size();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/os/IPendingIntentRef.h>
|
||||
#include <android/os/IStatsCompanionService.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
@@ -46,24 +47,12 @@ public:
|
||||
SubscriberReporter(SubscriberReporter const&) = delete;
|
||||
void operator=(SubscriberReporter const&) = delete;
|
||||
|
||||
/**
|
||||
* Tells SubscriberReporter what IStatsCompanionService to use.
|
||||
* May be nullptr, but SubscriberReporter will not send broadcasts for any calls
|
||||
* to alertBroadcastSubscriber that occur while nullptr.
|
||||
*/
|
||||
void setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) {
|
||||
std::lock_guard<std::mutex> lock(mLock);
|
||||
sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
|
||||
mStatsCompanionService = statsCompanionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given intentSender, associating it with the given (configKey, subscriberId) pair.
|
||||
* intentSender must be convertible into an IntentSender (in Java) using IntentSender(IBinder).
|
||||
*/
|
||||
void setBroadcastSubscriber(const ConfigKey& configKey,
|
||||
int64_t subscriberId,
|
||||
const sp<android::IBinder>& intentSender);
|
||||
const sp<IPendingIntentRef>& pir);
|
||||
|
||||
/**
|
||||
* Erases any intentSender information from the given (configKey, subscriberId) pair.
|
||||
@@ -82,6 +71,8 @@ public:
|
||||
const Subscription& subscription,
|
||||
const MetricDimensionKey& dimKey) const;
|
||||
|
||||
sp<IPendingIntentRef> getBroadcastSubscriber(const ConfigKey& configKey, int64_t subscriberId);
|
||||
|
||||
static StatsDimensionsValue getStatsDimensionsValue(const HashableDimensionKey& dim);
|
||||
|
||||
private:
|
||||
@@ -92,15 +83,15 @@ private:
|
||||
/** Binder interface for communicating with StatsCompanionService. */
|
||||
sp<IStatsCompanionService> mStatsCompanionService = nullptr;
|
||||
|
||||
/** Maps <ConfigKey, SubscriberId> -> IBinder (which represents an IIntentSender). */
|
||||
/** Maps <ConfigKey, SubscriberId> -> IPendingIntentRef (which represents a PendingIntent). */
|
||||
std::unordered_map<ConfigKey,
|
||||
std::unordered_map<int64_t, sp<android::IBinder>>> mIntentMap;
|
||||
std::unordered_map<int64_t, sp<IPendingIntentRef>>> mIntentMap;
|
||||
|
||||
/**
|
||||
* Sends a broadcast via the given intentSender (using mStatsCompanionService), along
|
||||
* with the information in the other parameters.
|
||||
*/
|
||||
void sendBroadcastLocked(const sp<android::IBinder>& intentSender,
|
||||
void sendBroadcastLocked(const sp<IPendingIntentRef>& pir,
|
||||
const ConfigKey& configKey,
|
||||
const Subscription& subscription,
|
||||
const std::vector<String16>& cookies,
|
||||
|
||||
@@ -255,18 +255,17 @@ public final class StatsManager {
|
||||
throws StatsUnavailableException {
|
||||
synchronized (sLock) {
|
||||
try {
|
||||
IStatsd service = getIStatsdLocked();
|
||||
IStatsManagerService service = getIStatsManagerServiceLocked();
|
||||
if (pendingIntent != null) {
|
||||
// Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
|
||||
IBinder intentSender = pendingIntent.getTarget().asBinder();
|
||||
service.setBroadcastSubscriber(configKey, subscriberId, intentSender,
|
||||
service.setBroadcastSubscriber(configKey, subscriberId, pendingIntent,
|
||||
mContext.getOpPackageName());
|
||||
} else {
|
||||
service.unsetBroadcastSubscriber(configKey, subscriberId,
|
||||
mContext.getOpPackageName());
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to connect to statsd when adding broadcast subscriber", e);
|
||||
Slog.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);
|
||||
@@ -309,18 +308,16 @@ public final class StatsManager {
|
||||
throws StatsUnavailableException {
|
||||
synchronized (sLock) {
|
||||
try {
|
||||
IStatsd service = getIStatsdLocked();
|
||||
IStatsManagerService service = getIStatsManagerServiceLocked();
|
||||
if (pendingIntent == null) {
|
||||
service.removeDataFetchOperation(configKey, mContext.getOpPackageName());
|
||||
} else {
|
||||
// Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
|
||||
IBinder intentSender = pendingIntent.getTarget().asBinder();
|
||||
service.setDataFetchOperation(configKey, intentSender,
|
||||
service.setDataFetchOperation(configKey, pendingIntent,
|
||||
mContext.getOpPackageName());
|
||||
}
|
||||
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to connect to statsd when registering data listener.");
|
||||
Slog.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);
|
||||
@@ -347,20 +344,18 @@ public final class StatsManager {
|
||||
throws StatsUnavailableException {
|
||||
synchronized (sLock) {
|
||||
try {
|
||||
IStatsd service = getIStatsdLocked();
|
||||
IStatsManagerService service = getIStatsManagerServiceLocked();
|
||||
if (pendingIntent == null) {
|
||||
service.removeActiveConfigsChangedOperation(mContext.getOpPackageName());
|
||||
return new long[0];
|
||||
} else {
|
||||
// Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
|
||||
IBinder intentSender = pendingIntent.getTarget().asBinder();
|
||||
return service.setActiveConfigsChangedOperation(intentSender,
|
||||
return service.setActiveConfigsChangedOperation(pendingIntent,
|
||||
mContext.getOpPackageName());
|
||||
}
|
||||
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG,
|
||||
"Failed to connect to statsd when registering active configs listener.");
|
||||
Slog.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);
|
||||
|
||||
Reference in New Issue
Block a user