New IpConnectivityMetrics service am: eab511b582
am: 3a353a2044
Change-Id: I5cf485edd3ab1ebb81a2a9d35dfb8bd6d8bcc305
This commit is contained in:
@@ -201,6 +201,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/net/ICaptivePortal.aidl \
|
||||
core/java/android/net/IConnectivityManager.aidl \
|
||||
core/java/android/net/IConnectivityMetricsLogger.aidl \
|
||||
core/java/android/net/IIpConnectivityMetrics.aidl \
|
||||
core/java/android/net/IEthernetManager.aidl \
|
||||
core/java/android/net/IEthernetServiceListener.aidl \
|
||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||
|
||||
29
core/java/android/net/IIpConnectivityMetrics.aidl
Normal file
29
core/java/android/net/IIpConnectivityMetrics.aidl
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net;
|
||||
|
||||
import android.os.Parcelable;
|
||||
import android.net.ConnectivityMetricsEvent;
|
||||
|
||||
/** {@hide} */
|
||||
interface IIpConnectivityMetrics {
|
||||
|
||||
/**
|
||||
* @return number of remaining available slots in buffer.
|
||||
*/
|
||||
int logEvent(in ConnectivityMetricsEvent event);
|
||||
}
|
||||
@@ -33,6 +33,8 @@ public class IpConnectivityLog extends ConnectivityMetricsLogger {
|
||||
private static String TAG = "IpConnectivityMetricsLogger";
|
||||
private static final boolean DBG = true;
|
||||
|
||||
public static final String SERVICE_NAME = "connmetrics";
|
||||
|
||||
public IpConnectivityLog() {
|
||||
// mService initialized in super constructor.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.connectivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityMetricsEvent;
|
||||
import android.net.IIpConnectivityMetrics;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.SystemService;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityEvent;
|
||||
|
||||
/** {@hide} */
|
||||
final public class IpConnectivityMetrics extends SystemService {
|
||||
private static final String TAG = IpConnectivityMetrics.class.getSimpleName();
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private static final String SERVICE_NAME = IpConnectivityLog.SERVICE_NAME;
|
||||
|
||||
// Default size of the event buffer. Once the buffer is full, incoming events are dropped.
|
||||
private static final int DEFAULT_BUFFER_SIZE = 2000;
|
||||
|
||||
// Lock ensuring that concurrent manipulations of the event buffer are correct.
|
||||
// There are three concurrent operations to synchronize:
|
||||
// - appending events to the buffer.
|
||||
// - iterating throught the buffer.
|
||||
// - flushing the buffer content and replacing it by a new buffer.
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@VisibleForTesting
|
||||
public final Impl impl = new Impl();
|
||||
@GuardedBy("mLock")
|
||||
private ArrayList<ConnectivityMetricsEvent> mBuffer;
|
||||
@GuardedBy("mLock")
|
||||
private int mDropped;
|
||||
@GuardedBy("mLock")
|
||||
private int mCapacity;
|
||||
|
||||
public IpConnectivityMetrics(Context ctx) {
|
||||
super(ctx);
|
||||
initBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (DBG) Log.d(TAG, "onStart");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBootPhase(int phase) {
|
||||
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
|
||||
if (DBG) Log.d(TAG, "onBootPhase");
|
||||
|
||||
publishBinderService(SERVICE_NAME, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int bufferCapacity() {
|
||||
return DEFAULT_BUFFER_SIZE; // TODO: read from config
|
||||
}
|
||||
|
||||
private void initBuffer() {
|
||||
synchronized (mLock) {
|
||||
mDropped = 0;
|
||||
mCapacity = bufferCapacity();
|
||||
mBuffer = new ArrayList<>(mCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
private int append(ConnectivityMetricsEvent event) {
|
||||
if (DBG) Log.d(TAG, "logEvent: " + event);
|
||||
synchronized (mLock) {
|
||||
final int left = mCapacity - mBuffer.size();
|
||||
if (event == null) {
|
||||
return left;
|
||||
}
|
||||
if (left == 0) {
|
||||
mDropped++;
|
||||
return 0;
|
||||
}
|
||||
mBuffer.add(event);
|
||||
return left - 1;
|
||||
}
|
||||
}
|
||||
|
||||
private String flushEncodedOutput() {
|
||||
final ArrayList<ConnectivityMetricsEvent> events;
|
||||
final int dropped;
|
||||
synchronized (mLock) {
|
||||
events = mBuffer;
|
||||
dropped = mDropped;
|
||||
initBuffer();
|
||||
}
|
||||
|
||||
final byte[] data;
|
||||
try {
|
||||
data = IpConnectivityEventBuilder.serialize(dropped, events);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "could not serialize events", e);
|
||||
return "";
|
||||
}
|
||||
|
||||
return Base64.encodeToString(data, Base64.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the event buffer and prints its content as a protobuf serialized byte array
|
||||
* inside a base64 encoded string.
|
||||
*/
|
||||
private void cmdFlush(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.print(flushEncodedOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the content of the event buffer, either using the events ASCII representation
|
||||
* or using protobuf text format.
|
||||
*/
|
||||
private void cmdList(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
final ArrayList<ConnectivityMetricsEvent> events;
|
||||
synchronized (mLock) {
|
||||
events = new ArrayList(mBuffer);
|
||||
}
|
||||
|
||||
if (args.length > 1 && args[1].equals("proto")) {
|
||||
for (IpConnectivityEvent ev : IpConnectivityEventBuilder.toProto(events)) {
|
||||
pw.print(ev.toString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (ConnectivityMetricsEvent ev : events) {
|
||||
pw.println(ev.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void cmdStats(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
synchronized (mLock) {
|
||||
pw.println("Buffered events: " + mBuffer.size());
|
||||
pw.println("Buffer capacity: " + mCapacity);
|
||||
pw.println("Dropped events: " + mDropped);
|
||||
}
|
||||
}
|
||||
|
||||
private void cmdDefault(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (args.length == 0) {
|
||||
pw.println("No command");
|
||||
return;
|
||||
}
|
||||
pw.println("Unknown command " + TextUtils.join(" ", args));
|
||||
}
|
||||
|
||||
public final class Impl extends IIpConnectivityMetrics.Stub {
|
||||
static final String CMD_FLUSH = "flush";
|
||||
static final String CMD_LIST = "list";
|
||||
static final String CMD_STATS = "stats";
|
||||
static final String CMD_DEFAULT = CMD_STATS;
|
||||
|
||||
@Override
|
||||
public int logEvent(ConnectivityMetricsEvent event) {
|
||||
enforceConnectivityInternalPermission();
|
||||
return append(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
enforceDumpPermission();
|
||||
if (DBG) Log.d(TAG, "dumpsys " + TextUtils.join(" ", args));
|
||||
final String cmd = (args.length > 0) ? args[0] : CMD_DEFAULT;
|
||||
switch (cmd) {
|
||||
case CMD_FLUSH:
|
||||
cmdFlush(fd, pw, args);
|
||||
return;
|
||||
case CMD_LIST:
|
||||
cmdList(fd, pw, args);
|
||||
return;
|
||||
case CMD_STATS:
|
||||
cmdStats(fd, pw, args);
|
||||
return;
|
||||
default:
|
||||
cmdDefault(fd, pw, args);
|
||||
}
|
||||
}
|
||||
|
||||
private void enforceConnectivityInternalPermission() {
|
||||
enforcePermission(android.Manifest.permission.CONNECTIVITY_INTERNAL);
|
||||
}
|
||||
|
||||
private void enforceDumpPermission() {
|
||||
enforcePermission(android.Manifest.permission.DUMP);
|
||||
}
|
||||
|
||||
private void enforcePermission(String what) {
|
||||
getContext().enforceCallingOrSelfPermission(what, "IpConnectivityMetrics");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -61,6 +61,7 @@ import com.android.server.am.ActivityManagerService;
|
||||
import com.android.server.audio.AudioService;
|
||||
import com.android.server.camera.CameraService;
|
||||
import com.android.server.clipboard.ClipboardService;
|
||||
import com.android.server.connectivity.IpConnectivityMetrics;
|
||||
import com.android.server.connectivity.MetricsLoggerService;
|
||||
import com.android.server.devicepolicy.DevicePolicyManagerService;
|
||||
import com.android.server.display.DisplayManagerService;
|
||||
@@ -661,6 +662,10 @@ public final class SystemServer {
|
||||
mSystemServiceManager.startService(MetricsLoggerService.class);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
|
||||
traceBeginAndSlog("IpConnectivityMetrics");
|
||||
mSystemServiceManager.startService(IpConnectivityMetrics.class);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
|
||||
traceBeginAndSlog("PinnerService");
|
||||
mSystemServiceManager.startService(PinnerService.class);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
|
||||
Reference in New Issue
Block a user