Create statsmanager service

Bug: 146074170
Test: Manual
Change-Id: Ia96f2df24e660fe3293fb2e873e9050a55398cee
This commit is contained in:
Jeffrey Huang 2019-12-12 10:56:24 -08:00
parent 56911a8623
commit 8c1ae5aef8
9 changed files with 289 additions and 36 deletions

View File

@ -245,7 +245,7 @@ filegroup {
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
// TODO: this needs to be removed when statsd-framework.jar is separated out
":statsd_aidl",
":statsd_java_aidl",
":storaged_aidl",
":vold_aidl",

View File

@ -17,6 +17,18 @@
// TODO(b/145815909): move StatsDimensionsValue.aidl and StatsLogEventWrapper.aidl here
filegroup {
name: "statsd_aidl",
srcs: [
"android/os/IPullAtomCallback.aidl",
"android/os/IPullAtomResultReceiver.aidl",
"android/os/IStatsCompanionService.aidl",
"android/os/IStatsd.aidl",
"android/os/IStatsPullerCallback.aidl",
"android/util/StatsEventParcel.aidl",
],
}
filegroup {
name: "statsd_java_aidl",
srcs: ["**/*.aidl"],
}

View File

@ -0,0 +1,65 @@
/**
* 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;
/**
* 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.
*/
void setDataFetchOperation(long configKey, in PendingIntent pendingIntent,
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);
/**
* 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.
*/
void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent,
in String packageName);
}

View File

@ -0,0 +1,70 @@
/*
* 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.content.Context;
import android.util.Slog;
import com.android.server.SystemService;
/**
* @hide
*/
public class StatsCompanion {
private static final String TAG = "StatsCompanion";
private static final boolean DEBUG = false;
/**
* 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(Context.STATS_COMPANION_SERVICE,
mStatsCompanionService);
if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE);
publishBinderService(Context.STATS_MANAGER_SERVICE,
mStatsManagerService);
if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_MANAGER_SERVICE);
} catch (Exception e) {
Slog.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();
mStatsManagerService.systemReady();
}
}
}
}

View File

@ -137,7 +137,6 @@ import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.am.MemoryStatUtil.MemoryStat;
import com.android.server.notification.NotificationManagerService;
@ -278,6 +277,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final BroadcastReceiver mUserUpdateReceiver;
private final ShutdownEventReceiver mShutdownEventReceiver;
private StatsManagerService mStatsManagerService;
private static final class PullerKey {
private final int mUid;
private final int mAtomTag;
@ -2681,6 +2682,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
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);
@ -2736,7 +2738,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
// Lifecycle and related code
// Statsd related code
/**
* Fetches the statsd IBinder service.
@ -2747,42 +2749,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
return IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
}
public static final class Lifecycle extends SystemService {
private StatsCompanionService mStatsCompanionService;
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
mStatsCompanionService = new StatsCompanionService(getContext());
try {
publishBinderService(Context.STATS_COMPANION_SERVICE,
mStatsCompanionService);
if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE);
} catch (Exception e) {
Slog.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();
}
}
}
/**
* Now that the android system is ready, StatsCompanion is ready too, so inform statsd.
*/
private void systemReady() {
void systemReady() {
if (DEBUG) Slog.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.

View File

@ -0,0 +1,108 @@
/*
* 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.content.Context;
import android.os.IBinder;
import android.os.IStatsManagerService;
import android.os.IStatsd;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
/**
* @hide
*/
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 StatsCompanionService mStatsCompanionService;
public StatsManagerService(Context context) {
super();
}
@Override
public void setDataFetchOperation(long configKey, PendingIntent pendingIntent,
String packageName) {
// no-op
if (DEBUG) {
Slog.d(TAG, "setDataFetchOperation");
}
}
@Override
public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent,
String packageName) {
// no-op
if (DEBUG) {
Slog.d(TAG, "setActiveConfigsChangedOperation");
}
return new long[]{};
}
@Override
public void setBroadcastSubscriber(long configKey, long subscriberId,
PendingIntent pendingIntent, String packageName) {
//no-op
if (DEBUG) {
Slog.d(TAG, "setBroadcastSubscriber");
}
}
void setStatsCompanionService(StatsCompanionService statsCompanionService) {
mStatsCompanionService = statsCompanionService;
}
void systemReady() {
if (DEBUG) {
Slog.d(TAG, "statsdReady");
}
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"));
}
return;
}
sStatsd = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
// Assume statsd is ready since this is called form statscompanion, link to statsd.
try {
sStatsd.asBinder().linkToDeath((IBinder.DeathRecipient) () -> {
sStatsd = null;
}, 0);
} catch (RemoteException e) {
Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e);
}
}
}
}

View File

@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.IPullAtomCallback;
import android.os.IPullAtomResultReceiver;
import android.os.IStatsCompanionService;
import android.os.IStatsManagerService;
import android.os.IStatsPullerCallback;
import android.os.IStatsd;
import android.os.RemoteException;
@ -61,6 +62,9 @@ public final class StatsManager {
@GuardedBy("sLock")
private IStatsCompanionService mStatsCompanion;
@GuardedBy("sLock")
private IStatsManagerService mStatsManagerService;
/**
* Long extra of uid that added the relevant stats config.
*/
@ -686,6 +690,16 @@ public final class StatsManager {
return mStatsCompanion;
}
@GuardedBy("sLock")
private IStatsManagerService getIStatsManagerServiceLocked() {
if (mStatsManagerService != null) {
return mStatsManagerService;
}
mStatsManagerService = IStatsManagerService.Stub.asInterface(
ServiceManager.getService(Context.STATS_MANAGER_SERVICE));
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.

View File

@ -4802,6 +4802,12 @@ public abstract class Context {
*/
public static final String INCIDENT_COMPANION_SERVICE = "incidentcompanion";
/**
* Service to assist {@link android.app.StatsManager} that lives in system server.
* @hide
*/
public static final String STATS_MANAGER_SERVICE = "statsmanager";
/**
* Service to assist statsd in obtaining general stats.
* @hide

View File

@ -209,8 +209,8 @@ public final class SystemServer {
"com.android.server.print.PrintManagerService";
private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
"com.android.server.companion.CompanionDeviceManagerService";
private static final String STATS_COMPANION_SERVICE_LIFECYCLE_CLASS =
"com.android.server.stats.StatsCompanionService$Lifecycle";
private static final String STATS_COMPANION_LIFECYCLE_CLASS =
"com.android.server.stats.StatsCompanion$Lifecycle";
private static final String USB_SERVICE_CLASS =
"com.android.server.usb.UsbService$Lifecycle";
private static final String MIDI_SERVICE_CLASS =
@ -1955,8 +1955,8 @@ public final class SystemServer {
}
// Statsd helper
t.traceBegin("StartStatsCompanionService");
mSystemServiceManager.startService(STATS_COMPANION_SERVICE_LIFECYCLE_CLASS);
t.traceBegin("StartStatsCompanion");
mSystemServiceManager.startService(STATS_COMPANION_LIFECYCLE_CLASS);
t.traceEnd();
// Incidentd and dumpstated helper