diff options
5 files changed, 168 insertions, 61 deletions
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index 7ecf69b0abae..1004e17e91e6 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -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)); + } + } } diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java index 007980150237..5fa96bd9a152 100644 --- a/core/java/com/android/internal/os/BinderLatencyObserver.java +++ b/core/java/com/android/internal/os/BinderLatencyObserver.java @@ -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(); } diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java index 8c5e0fc8e658..e2e672ea6f68 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -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); diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java index bf87683593e7..4157f5e72871 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java @@ -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<>(); } diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index 78610a2857bd..0bd331b737c6 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -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); |