Add a version of SettingsObserver to BinderCallsStats and make it public so it could be
used to collect binder latency data from bluetooth and telephony. Test: latency collection is unit tested, this is just an alternative settings configuration Bug: 180584913 Change-Id: Ide51afb7eb26a96c7692bceb0a22585a74f08aa7
This commit is contained in:
@@ -16,18 +16,25 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.BinderLatencyProto.Dims.SYSTEM_SERVER;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IntArray;
|
||||
import android.util.KeyValueListParser;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -157,15 +164,20 @@ public class BinderCallsStats implements BinderInternal.Observer {
|
||||
return new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
public BinderLatencyObserver getLatencyObserver() {
|
||||
return new BinderLatencyObserver(new BinderLatencyObserver.Injector());
|
||||
/** Create a latency observer for the specified process. */
|
||||
public BinderLatencyObserver getLatencyObserver(int processSource) {
|
||||
return new BinderLatencyObserver(new BinderLatencyObserver.Injector(), processSource);
|
||||
}
|
||||
}
|
||||
|
||||
public BinderCallsStats(Injector injector) {
|
||||
this(injector, SYSTEM_SERVER);
|
||||
}
|
||||
|
||||
public BinderCallsStats(Injector injector, int processSource) {
|
||||
this.mRandom = injector.getRandomGenerator();
|
||||
this.mCallStatsObserverHandler = injector.getHandler();
|
||||
this.mLatencyObserver = injector.getLatencyObserver();
|
||||
this.mLatencyObserver = injector.getLatencyObserver(processSource);
|
||||
}
|
||||
|
||||
public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
|
||||
@@ -1074,4 +1086,120 @@ public class BinderCallsStats implements BinderInternal.Observer {
|
||||
? result
|
||||
: Integer.compare(a.transactionCode, b.transactionCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Settings observer for other processes (not system_server).
|
||||
*
|
||||
* We do not want to collect cpu data from other processes so only latency collection should be
|
||||
* possible to enable.
|
||||
*/
|
||||
public static class SettingsObserver extends ContentObserver {
|
||||
// Settings for BinderCallsStats.
|
||||
public static final String SETTINGS_ENABLED_KEY = "enabled";
|
||||
public static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
|
||||
public static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
|
||||
public static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
|
||||
public static final String SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state";
|
||||
public static final String SETTINGS_TRACK_DIRECT_CALLING_UID_KEY = "track_calling_uid";
|
||||
public static final String SETTINGS_MAX_CALL_STATS_KEY = "max_call_stats_count";
|
||||
public static final String SETTINGS_IGNORE_BATTERY_STATUS_KEY = "ignore_battery_status";
|
||||
// Settings for BinderLatencyObserver.
|
||||
public static final String SETTINGS_COLLECT_LATENCY_DATA_KEY = "collect_Latency_data";
|
||||
public static final String SETTINGS_LATENCY_OBSERVER_SAMPLING_INTERVAL_KEY =
|
||||
"latency_observer_sampling_interval";
|
||||
public static final String SETTINGS_LATENCY_OBSERVER_PUSH_INTERVAL_MINUTES_KEY =
|
||||
"latency_observer_push_interval_minutes";
|
||||
public static final String SETTINGS_LATENCY_HISTOGRAM_BUCKET_COUNT_KEY =
|
||||
"latency_histogram_bucket_count";
|
||||
public static final String SETTINGS_LATENCY_HISTOGRAM_FIRST_BUCKET_SIZE_KEY =
|
||||
"latency_histogram_first_bucket_size";
|
||||
public static final String SETTINGS_LATENCY_HISTOGRAM_BUCKET_SCALE_FACTOR_KEY =
|
||||
"latency_histogram_bucket_scale_factor";
|
||||
|
||||
private boolean mEnabled;
|
||||
private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
|
||||
private final Context mContext;
|
||||
private final KeyValueListParser mParser = new KeyValueListParser(',');
|
||||
private final BinderCallsStats mBinderCallsStats;
|
||||
private final int mProcessSource;
|
||||
|
||||
public SettingsObserver(Context context, BinderCallsStats binderCallsStats,
|
||||
int processSource, int userHandle) {
|
||||
super(BackgroundThread.getHandler());
|
||||
mContext = context;
|
||||
context.getContentResolver().registerContentObserver(mUri, false, this,
|
||||
userHandle);
|
||||
mBinderCallsStats = binderCallsStats;
|
||||
mProcessSource = processSource;
|
||||
// Always kick once to ensure that we match current state
|
||||
onChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri, int userId) {
|
||||
if (mUri.equals(uri)) {
|
||||
onChange();
|
||||
}
|
||||
}
|
||||
|
||||
void onChange() {
|
||||
try {
|
||||
mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
|
||||
Settings.Global.BINDER_CALLS_STATS));
|
||||
} catch (IllegalArgumentException e) {
|
||||
Slog.e(TAG, "Bad binder call stats settings", e);
|
||||
}
|
||||
|
||||
// Cpu data collection should always be disabled for other processes.
|
||||
mBinderCallsStats.setDetailedTracking(false);
|
||||
mBinderCallsStats.setTrackScreenInteractive(false);
|
||||
mBinderCallsStats.setTrackDirectCallerUid(false);
|
||||
|
||||
mBinderCallsStats.setIgnoreBatteryStatus(
|
||||
mParser.getBoolean(SETTINGS_IGNORE_BATTERY_STATUS_KEY,
|
||||
BinderCallsStats.DEFAULT_IGNORE_BATTERY_STATUS));
|
||||
mBinderCallsStats.setCollectLatencyData(
|
||||
mParser.getBoolean(SETTINGS_COLLECT_LATENCY_DATA_KEY,
|
||||
BinderCallsStats.DEFAULT_COLLECT_LATENCY_DATA));
|
||||
|
||||
// Binder latency observer settings.
|
||||
configureLatencyObserver(mParser, mBinderCallsStats.getLatencyObserver());
|
||||
|
||||
final boolean enabled =
|
||||
mParser.getBoolean(SETTINGS_ENABLED_KEY, BinderCallsStats.ENABLED_DEFAULT);
|
||||
if (mEnabled != enabled) {
|
||||
if (enabled) {
|
||||
Binder.setObserver(mBinderCallsStats);
|
||||
} else {
|
||||
Binder.setObserver(null);
|
||||
}
|
||||
mEnabled = enabled;
|
||||
mBinderCallsStats.reset();
|
||||
mBinderCallsStats.setAddDebugEntries(enabled);
|
||||
mBinderCallsStats.getLatencyObserver().reset();
|
||||
}
|
||||
}
|
||||
|
||||
/** Configures the binder latency observer related settings. */
|
||||
public static void configureLatencyObserver(
|
||||
KeyValueListParser mParser, BinderLatencyObserver binderLatencyObserver) {
|
||||
binderLatencyObserver.setSamplingInterval(mParser.getInt(
|
||||
SETTINGS_LATENCY_OBSERVER_SAMPLING_INTERVAL_KEY,
|
||||
BinderLatencyObserver.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
|
||||
binderLatencyObserver.setHistogramBucketsParams(
|
||||
mParser.getInt(
|
||||
SETTINGS_LATENCY_HISTOGRAM_BUCKET_COUNT_KEY,
|
||||
BinderLatencyObserver.BUCKET_COUNT_DEFAULT),
|
||||
mParser.getInt(
|
||||
SETTINGS_LATENCY_HISTOGRAM_FIRST_BUCKET_SIZE_KEY,
|
||||
BinderLatencyObserver.FIRST_BUCKET_SIZE_DEFAULT),
|
||||
mParser.getFloat(
|
||||
SETTINGS_LATENCY_HISTOGRAM_BUCKET_SCALE_FACTOR_KEY,
|
||||
BinderLatencyObserver.BUCKET_SCALE_FACTOR_DEFAULT));
|
||||
binderLatencyObserver.setPushInterval(mParser.getInt(
|
||||
SETTINGS_LATENCY_OBSERVER_PUSH_INTERVAL_MINUTES_KEY,
|
||||
BinderLatencyObserver.STATSD_PUSH_INTERVAL_MINUTES_DEFAULT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.BinderLatencyProto.Dims.SYSTEM_SERVER;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
@@ -68,9 +66,10 @@ public class BinderLatencyObserver {
|
||||
private int mStatsdPushIntervalMinutes = STATSD_PUSH_INTERVAL_MINUTES_DEFAULT;
|
||||
|
||||
private final Random mRandom;
|
||||
private BinderLatencyBuckets mLatencyBuckets;
|
||||
|
||||
private final Handler mLatencyObserverHandler;
|
||||
private final int mProcessSource;
|
||||
|
||||
private BinderLatencyBuckets mLatencyBuckets;
|
||||
|
||||
private Runnable mLatencyObserverRunnable = new Runnable() {
|
||||
@Override
|
||||
@@ -134,7 +133,7 @@ public class BinderLatencyObserver {
|
||||
|
||||
// Write the dims.
|
||||
long dimsToken = proto.start(ApiStats.DIMS);
|
||||
proto.write(Dims.PROCESS_SOURCE, SYSTEM_SERVER);
|
||||
proto.write(Dims.PROCESS_SOURCE, mProcessSource);
|
||||
proto.write(Dims.SERVICE_CLASS_NAME, dims.getBinderClass().getName());
|
||||
proto.write(Dims.SERVICE_METHOD_NAME, transactionName);
|
||||
proto.end(dimsToken);
|
||||
@@ -180,11 +179,12 @@ public class BinderLatencyObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public BinderLatencyObserver(Injector injector) {
|
||||
public BinderLatencyObserver(Injector injector, int processSource) {
|
||||
mRandom = injector.getRandomGenerator();
|
||||
mLatencyObserverHandler = injector.getHandler();
|
||||
mLatencyBuckets = new BinderLatencyBuckets(
|
||||
mBucketCount, mFirstBucketSize, mBucketScaleFactor);
|
||||
mProcessSource = processSource;
|
||||
noteLatencyDelayed();
|
||||
}
|
||||
|
||||
|
||||
@@ -984,8 +984,9 @@ public class BinderCallsStatsTest {
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
public BinderLatencyObserver getLatencyObserver() {
|
||||
return new BinderLatencyObserverTest.TestBinderLatencyObserver();
|
||||
@Override
|
||||
public BinderLatencyObserver getLatencyObserver(int processSource) {
|
||||
return new BinderLatencyObserverTest.TestBinderLatencyObserver(processSource);
|
||||
}
|
||||
});
|
||||
setSamplingInterval(1);
|
||||
|
||||
@@ -245,18 +245,24 @@ public class BinderLatencyObserverTest {
|
||||
private ArrayList<String> mWrittenAtoms;
|
||||
|
||||
TestBinderLatencyObserver() {
|
||||
// Make random generator not random.
|
||||
super(new Injector() {
|
||||
public Random getRandomGenerator() {
|
||||
return new Random() {
|
||||
int mCallCount = 0;
|
||||
this(SYSTEM_SERVER);
|
||||
}
|
||||
|
||||
public int nextInt() {
|
||||
return mCallCount++;
|
||||
TestBinderLatencyObserver(int processSource) {
|
||||
// Make random generator not random.
|
||||
super(
|
||||
new Injector() {
|
||||
public Random getRandomGenerator() {
|
||||
return new Random() {
|
||||
int mCallCount = 0;
|
||||
|
||||
public int nextInt() {
|
||||
return mCallCount++;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
processSource);
|
||||
setSamplingInterval(1);
|
||||
mWrittenAtoms = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,15 @@ package com.android.server;
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
||||
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_COLLECT_LATENCY_DATA_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_DETAILED_TRACKING_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_ENABLED_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_IGNORE_BATTERY_STATUS_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_MAX_CALL_STATS_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_SAMPLING_INTERVAL_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_TRACK_DIRECT_CALLING_UID_KEY;
|
||||
import static com.android.internal.os.BinderCallsStats.SettingsObserver.SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY;
|
||||
|
||||
import android.app.ActivityThread;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
@@ -43,7 +52,6 @@ import com.android.internal.os.AppIdToPackageMap;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.os.BinderCallsStats;
|
||||
import com.android.internal.os.BinderInternal;
|
||||
import com.android.internal.os.BinderLatencyObserver;
|
||||
import com.android.internal.os.CachedDeviceState;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
|
||||
@@ -125,28 +133,6 @@ public class BinderCallsStatsService extends Binder {
|
||||
|
||||
/** Listens for flag changes. */
|
||||
private static class SettingsObserver extends ContentObserver {
|
||||
// Settings for BinderCallsStats.
|
||||
private static final String SETTINGS_ENABLED_KEY = "enabled";
|
||||
private static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
|
||||
private static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
|
||||
private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
|
||||
private static final String SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state";
|
||||
private static final String SETTINGS_TRACK_DIRECT_CALLING_UID_KEY = "track_calling_uid";
|
||||
private static final String SETTINGS_MAX_CALL_STATS_KEY = "max_call_stats_count";
|
||||
private static final String SETTINGS_IGNORE_BATTERY_STATUS_KEY = "ignore_battery_status";
|
||||
// Settings for BinderLatencyObserver.
|
||||
private static final String SETTINGS_COLLECT_LATENCY_DATA_KEY = "collect_Latency_data";
|
||||
private static final String SETTINGS_LATENCY_OBSERVER_SAMPLING_INTERVAL_KEY =
|
||||
"latency_observer_sampling_interval";
|
||||
private static final String SETTINGS_LATENCY_OBSERVER_PUSH_INTERVAL_MINUTES_KEY =
|
||||
"latency_observer_push_interval_minutes";
|
||||
private static final String SETTINGS_LATENCY_HISTOGRAM_BUCKET_COUNT_KEY =
|
||||
"latency_histogram_bucket_count";
|
||||
private static final String SETTINGS_LATENCY_HISTOGRAM_FIRST_BUCKET_SIZE_KEY =
|
||||
"latency_histogram_first_bucket_size";
|
||||
private static final String SETTINGS_LATENCY_HISTOGRAM_BUCKET_SCALE_FACTOR_KEY =
|
||||
"latency_histogram_bucket_scale_factor";
|
||||
|
||||
private boolean mEnabled;
|
||||
private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
|
||||
private final Context mContext;
|
||||
@@ -206,23 +192,9 @@ public class BinderCallsStatsService extends Binder {
|
||||
mParser.getBoolean(SETTINGS_COLLECT_LATENCY_DATA_KEY,
|
||||
BinderCallsStats.DEFAULT_COLLECT_LATENCY_DATA));
|
||||
// Binder latency observer settings.
|
||||
BinderLatencyObserver binderLatencyObserver = mBinderCallsStats.getLatencyObserver();
|
||||
binderLatencyObserver.setSamplingInterval(mParser.getInt(
|
||||
SETTINGS_LATENCY_OBSERVER_SAMPLING_INTERVAL_KEY,
|
||||
BinderLatencyObserver.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
|
||||
binderLatencyObserver.setHistogramBucketsParams(
|
||||
mParser.getInt(
|
||||
SETTINGS_LATENCY_HISTOGRAM_BUCKET_COUNT_KEY,
|
||||
BinderLatencyObserver.BUCKET_COUNT_DEFAULT),
|
||||
mParser.getInt(
|
||||
SETTINGS_LATENCY_HISTOGRAM_FIRST_BUCKET_SIZE_KEY,
|
||||
BinderLatencyObserver.FIRST_BUCKET_SIZE_DEFAULT),
|
||||
mParser.getFloat(
|
||||
SETTINGS_LATENCY_HISTOGRAM_BUCKET_SCALE_FACTOR_KEY,
|
||||
BinderLatencyObserver.BUCKET_SCALE_FACTOR_DEFAULT));
|
||||
binderLatencyObserver.setPushInterval(mParser.getInt(
|
||||
SETTINGS_LATENCY_OBSERVER_PUSH_INTERVAL_MINUTES_KEY,
|
||||
BinderLatencyObserver.STATSD_PUSH_INTERVAL_MINUTES_DEFAULT));
|
||||
BinderCallsStats.SettingsObserver.configureLatencyObserver(
|
||||
mParser,
|
||||
mBinderCallsStats.getLatencyObserver());
|
||||
|
||||
final boolean enabled =
|
||||
mParser.getBoolean(SETTINGS_ENABLED_KEY, BinderCallsStats.ENABLED_DEFAULT);
|
||||
|
||||
Reference in New Issue
Block a user