Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -398,6 +398,7 @@ java_defaults { "bouncycastle-repackaged-unbundled", "com.android.sysprop.foldlockbehavior", "com.android.sysprop.view", "com.android.sysprop.nativebinderstats", "framework-internal-utils", "dropboxmanager_aidl-java", "dynamic_instrumentation_manager_aidl-java", Loading core/java/com/android/internal/os/NativeBinderStats.java +63 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; import android.sysprop.NativeBinderStatsProperties; import android.util.KeyValueListParser; import android.util.Slog; Loading Loading @@ -74,10 +75,18 @@ public class NativeBinderStats { private final Context mContext; private final PropertiesWrapper mPropertiesWrapper; private final SettingsObserver mSettingsObserver; public NativeBinderStats(Context context) { this(context, new PropertiesWrapper()); } @VisibleForTesting public NativeBinderStats(Context context, PropertiesWrapper propertiesWrapper) { mContext = context; mPropertiesWrapper = propertiesWrapper; mSettingsObserver = new SettingsObserver(context); } Loading @@ -86,6 +95,51 @@ public class NativeBinderStats { mSettingsObserver.register(); } /** * A wrapper around System properties for testability. */ @VisibleForTesting public static class PropertiesWrapper { /** Sets the enabled property. */ public void setEnabled(boolean value) { NativeBinderStatsProperties.enabled(value); } /** Sets the process_sharding property. */ public void setProcessSharding(int value) { NativeBinderStatsProperties.process_sharding(value); } /** * Sets the spam_sharding property. */ public void setSpamSharding(int value) { NativeBinderStatsProperties.spam_sharding(value); } /** * Sets the call_sharding property. */ public void setCallSharding(int value) { NativeBinderStatsProperties.call_sharding(value); } /** Like {@link #setProcessSharding} but for system_server. */ public void setSystemProcessSharding(int value) { NativeBinderStatsProperties.system_process_sharding(value); } /** Like {@link #setSpamSharding} but for system_server. */ public void setSystemSpamSharding(int value) { NativeBinderStatsProperties.system_spam_sharding(value); } /** Like {@link #setCallSharding} but for system_server. */ public void setSystemCallSharding(int value) { NativeBinderStatsProperties.system_call_sharding(value); } } @VisibleForTesting public class SettingsObserver extends ContentObserver { private static final String KEY_ENABLED = "enabled"; Loading Loading @@ -138,7 +192,15 @@ public class NativeBinderStats { mParser.getInt(KEY_SYSTEM_SPAM_SHARDING, DEFAULT_SYSTEM_SPAM_SHARDING); mSystemCallSharding = mParser.getInt(KEY_SYSTEM_CALL_SHARDING, DEFAULT_SYSTEM_CALL_SHARDING); // TODO(b/407694522): If settings change, propagate to other processes. mPropertiesWrapper.setEnabled(mEnabled); mPropertiesWrapper.setProcessSharding(mProcessSharding); mPropertiesWrapper.setSpamSharding(mSpamSharding); mPropertiesWrapper.setCallSharding(mCallSharding); mPropertiesWrapper.setSystemProcessSharding(mSystemProcessSharding); mPropertiesWrapper.setSystemSpamSharding(mSystemSpamSharding); mPropertiesWrapper.setSystemCallSharding(mSystemCallSharding); Slog.i( TAG, String.format( Loading core/sysprop/Android.bp +7 −0 Original line number Diff line number Diff line Loading @@ -50,3 +50,10 @@ sysprop_library { property_owner: "Platform", api_packages: ["android.sysprop"], } sysprop_library { name: "com.android.sysprop.nativebinderstats", srcs: ["NativeBinderStatsProperties.sysprop"], property_owner: "Platform", api_packages: ["android.sysprop"], } core/sysprop/NativeBinderStatsProperties.sysprop 0 → 100644 +80 −0 Original line number Diff line number Diff line # This file is used to define system properties for native binder stats. # The properties are used to control the collection of binder stats. # The properties are set by the NativeBinderStats class. # The module that owns this property. module: "android.sysprop.NativeBinderStatsProperties" # Whether native binder stats are enabled. prop { api_name: "enabled" type: Boolean prop_name: "persist.sys.native_binder_stats.enabled" scope: Internal access: ReadWrite } # The inverse probability that a given process will track binder stats. E.g. 100 means that # 1% of the processes will report stats. 0 is a special value that means no process will # report stats. prop { api_name: "process_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.process_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for spam detection and # reporting (provided the containing process is selected for stats). 0 means no spam # tracking. prop { api_name: "spam_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.spam_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for call stats # (provided the containing process is selected for stats). 0 means no call stats. prop { api_name: "call_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.call_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given process will track binder stats. E.g. 100 means that # 1% of the processes will report stats. 0 is a special value that means no process will # report stats. This property is for system_server. prop { api_name: "system_process_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.system_process_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for spam detection and # reporting (provided the containing process is selected for stats). 0 means no spam # tracking. This property is for system_server. prop { api_name: "system_spam_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.system_spam_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for call stats # (provided the containing process is selected for stats). 0 means no call stats. # This property is for system_server. prop { api_name: "system_call_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.system_call_sharding" scope: Internal access: ReadWrite } core/tests/coretests/src/com/android/internal/os/NativeBinderStatsTest.java +135 −5 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; Loading @@ -38,6 +39,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @SmallTest @RunWith(AndroidJUnit4.class) Loading @@ -46,6 +48,7 @@ import org.junit.runner.RunWith; public class NativeBinderStatsTest { private Context mContext; private MockContentResolver mResolver; private NativeBinderStats.PropertiesWrapper mMockPropertiesWrapper; @Before public void setup() { Loading @@ -53,6 +56,7 @@ public class NativeBinderStatsTest { mContext = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); mResolver = new MockContentResolver(mContext); mResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mMockPropertiesWrapper = mock(NativeBinderStats.PropertiesWrapper.class); when(mContext.getContentResolver()).thenReturn(mResolver); } Loading @@ -63,16 +67,36 @@ public class NativeBinderStatsTest { @Test public void testSettingsObserver_disabledByDefault() { NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); // Verify that the injector was called with default values Mockito.verify(mMockPropertiesWrapper).setEnabled(NativeBinderStats.DEFAULT_ENABLED); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); assertThat(nativeBinderStats.mEnabled).isFalse(); } @Test public void testSettingsObserver_enabled() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=true"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); // Reset mock to clear previous interactions from setup (if any) Mockito.reset(mMockPropertiesWrapper); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isTrue(); Loading @@ -88,24 +112,58 @@ public class NativeBinderStatsTest { .isEqualTo(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); assertThat(nativeBinderStats.mSystemCallSharding) .isEqualTo(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); // Verify that the injector was called correctly Mockito.verify(mMockPropertiesWrapper).setEnabled(true); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); } @Test public void testSettingsObserver_disabled() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=false"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isFalse(); // Verify that the injector was called correctly Mockito.verify(mMockPropertiesWrapper).setEnabled(false); } @Test public void testSettingsObserver_changed() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=true"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isTrue(); Mockito.verify(mMockPropertiesWrapper).setEnabled(true); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); // Reset mock to clear previous interactions Mockito.reset(mMockPropertiesWrapper); Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=false"); // FakeSettingsProvider doesn't support notifications, so we need to notify manually. Loading @@ -115,6 +173,19 @@ public class NativeBinderStatsTest { false, Settings.Global.getUriFor(Settings.Global.NATIVE_BINDER_STATS), 0); assertThat(nativeBinderStats.mEnabled).isFalse(); Mockito.verify(mMockPropertiesWrapper).setEnabled(false); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); } @Test Loading @@ -124,7 +195,8 @@ public class NativeBinderStatsTest { Settings.Global.NATIVE_BINDER_STATS, "enabled=true,process_sharding=5,spam_sharding=1,call_sharding=2," + "system_process_sharding=1,system_spam_sharding=5,system_call_sharding=10"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isTrue(); Loading @@ -134,5 +206,63 @@ public class NativeBinderStatsTest { assertThat(nativeBinderStats.mSystemProcessSharding).isEqualTo(1); assertThat(nativeBinderStats.mSystemSpamSharding).isEqualTo(5); assertThat(nativeBinderStats.mSystemCallSharding).isEqualTo(10); // Verify that the injector was called with required values Mockito.verify(mMockPropertiesWrapper).setEnabled(true); Mockito.verify(mMockPropertiesWrapper).setProcessSharding(5); Mockito.verify(mMockPropertiesWrapper).setSpamSharding(1); Mockito.verify(mMockPropertiesWrapper).setCallSharding(2); Mockito.verify(mMockPropertiesWrapper).setSystemProcessSharding(1); Mockito.verify(mMockPropertiesWrapper).setSystemSpamSharding(5); Mockito.verify(mMockPropertiesWrapper).setSystemCallSharding(10); } @Test public void testSettingsObserver_badInput() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=truepxrocess_sharding=5,spam_sharding=1,call_sharding=2," + "system_process_sharding=1,system_spam_sharding=5,system_call_sharding=" + "10"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); // Verify that the injector was called with default values Mockito.verify(mMockPropertiesWrapper).setEnabled(NativeBinderStats.DEFAULT_ENABLED); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); // Verify that correctly got values were set Mockito.verify(mMockPropertiesWrapper).setSpamSharding(1); Mockito.verify(mMockPropertiesWrapper).setCallSharding(2); Mockito.verify(mMockPropertiesWrapper).setSystemProcessSharding(1); Mockito.verify(mMockPropertiesWrapper).setSystemSpamSharding(5); Mockito.verify(mMockPropertiesWrapper).setSystemCallSharding(10); assertThat(nativeBinderStats.mEnabled).isFalse(); } @Test public void testSettingsObserver_triggerInputException() { Settings.Global.putString( mResolver, Settings.Global.NATIVE_BINDER_STATS, "Lorem,ipsum,enable123"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); // Verify that the injector was called with default values Mockito.verify(mMockPropertiesWrapper).setEnabled(NativeBinderStats.DEFAULT_ENABLED); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); } } Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -398,6 +398,7 @@ java_defaults { "bouncycastle-repackaged-unbundled", "com.android.sysprop.foldlockbehavior", "com.android.sysprop.view", "com.android.sysprop.nativebinderstats", "framework-internal-utils", "dropboxmanager_aidl-java", "dynamic_instrumentation_manager_aidl-java", Loading
core/java/com/android/internal/os/NativeBinderStats.java +63 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; import android.sysprop.NativeBinderStatsProperties; import android.util.KeyValueListParser; import android.util.Slog; Loading Loading @@ -74,10 +75,18 @@ public class NativeBinderStats { private final Context mContext; private final PropertiesWrapper mPropertiesWrapper; private final SettingsObserver mSettingsObserver; public NativeBinderStats(Context context) { this(context, new PropertiesWrapper()); } @VisibleForTesting public NativeBinderStats(Context context, PropertiesWrapper propertiesWrapper) { mContext = context; mPropertiesWrapper = propertiesWrapper; mSettingsObserver = new SettingsObserver(context); } Loading @@ -86,6 +95,51 @@ public class NativeBinderStats { mSettingsObserver.register(); } /** * A wrapper around System properties for testability. */ @VisibleForTesting public static class PropertiesWrapper { /** Sets the enabled property. */ public void setEnabled(boolean value) { NativeBinderStatsProperties.enabled(value); } /** Sets the process_sharding property. */ public void setProcessSharding(int value) { NativeBinderStatsProperties.process_sharding(value); } /** * Sets the spam_sharding property. */ public void setSpamSharding(int value) { NativeBinderStatsProperties.spam_sharding(value); } /** * Sets the call_sharding property. */ public void setCallSharding(int value) { NativeBinderStatsProperties.call_sharding(value); } /** Like {@link #setProcessSharding} but for system_server. */ public void setSystemProcessSharding(int value) { NativeBinderStatsProperties.system_process_sharding(value); } /** Like {@link #setSpamSharding} but for system_server. */ public void setSystemSpamSharding(int value) { NativeBinderStatsProperties.system_spam_sharding(value); } /** Like {@link #setCallSharding} but for system_server. */ public void setSystemCallSharding(int value) { NativeBinderStatsProperties.system_call_sharding(value); } } @VisibleForTesting public class SettingsObserver extends ContentObserver { private static final String KEY_ENABLED = "enabled"; Loading Loading @@ -138,7 +192,15 @@ public class NativeBinderStats { mParser.getInt(KEY_SYSTEM_SPAM_SHARDING, DEFAULT_SYSTEM_SPAM_SHARDING); mSystemCallSharding = mParser.getInt(KEY_SYSTEM_CALL_SHARDING, DEFAULT_SYSTEM_CALL_SHARDING); // TODO(b/407694522): If settings change, propagate to other processes. mPropertiesWrapper.setEnabled(mEnabled); mPropertiesWrapper.setProcessSharding(mProcessSharding); mPropertiesWrapper.setSpamSharding(mSpamSharding); mPropertiesWrapper.setCallSharding(mCallSharding); mPropertiesWrapper.setSystemProcessSharding(mSystemProcessSharding); mPropertiesWrapper.setSystemSpamSharding(mSystemSpamSharding); mPropertiesWrapper.setSystemCallSharding(mSystemCallSharding); Slog.i( TAG, String.format( Loading
core/sysprop/Android.bp +7 −0 Original line number Diff line number Diff line Loading @@ -50,3 +50,10 @@ sysprop_library { property_owner: "Platform", api_packages: ["android.sysprop"], } sysprop_library { name: "com.android.sysprop.nativebinderstats", srcs: ["NativeBinderStatsProperties.sysprop"], property_owner: "Platform", api_packages: ["android.sysprop"], }
core/sysprop/NativeBinderStatsProperties.sysprop 0 → 100644 +80 −0 Original line number Diff line number Diff line # This file is used to define system properties for native binder stats. # The properties are used to control the collection of binder stats. # The properties are set by the NativeBinderStats class. # The module that owns this property. module: "android.sysprop.NativeBinderStatsProperties" # Whether native binder stats are enabled. prop { api_name: "enabled" type: Boolean prop_name: "persist.sys.native_binder_stats.enabled" scope: Internal access: ReadWrite } # The inverse probability that a given process will track binder stats. E.g. 100 means that # 1% of the processes will report stats. 0 is a special value that means no process will # report stats. prop { api_name: "process_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.process_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for spam detection and # reporting (provided the containing process is selected for stats). 0 means no spam # tracking. prop { api_name: "spam_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.spam_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for call stats # (provided the containing process is selected for stats). 0 means no call stats. prop { api_name: "call_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.call_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given process will track binder stats. E.g. 100 means that # 1% of the processes will report stats. 0 is a special value that means no process will # report stats. This property is for system_server. prop { api_name: "system_process_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.system_process_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for spam detection and # reporting (provided the containing process is selected for stats). 0 means no spam # tracking. This property is for system_server. prop { api_name: "system_spam_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.system_spam_sharding" scope: Internal access: ReadWrite } # The inverse probability that a given AIDL method will be selected for call stats # (provided the containing process is selected for stats). 0 means no call stats. # This property is for system_server. prop { api_name: "system_call_sharding" type: Integer prop_name: "persist.sys.native_binder_stats.system_call_sharding" scope: Internal access: ReadWrite }
core/tests/coretests/src/com/android/internal/os/NativeBinderStatsTest.java +135 −5 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; Loading @@ -38,6 +39,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @SmallTest @RunWith(AndroidJUnit4.class) Loading @@ -46,6 +48,7 @@ import org.junit.runner.RunWith; public class NativeBinderStatsTest { private Context mContext; private MockContentResolver mResolver; private NativeBinderStats.PropertiesWrapper mMockPropertiesWrapper; @Before public void setup() { Loading @@ -53,6 +56,7 @@ public class NativeBinderStatsTest { mContext = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); mResolver = new MockContentResolver(mContext); mResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mMockPropertiesWrapper = mock(NativeBinderStats.PropertiesWrapper.class); when(mContext.getContentResolver()).thenReturn(mResolver); } Loading @@ -63,16 +67,36 @@ public class NativeBinderStatsTest { @Test public void testSettingsObserver_disabledByDefault() { NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); // Verify that the injector was called with default values Mockito.verify(mMockPropertiesWrapper).setEnabled(NativeBinderStats.DEFAULT_ENABLED); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); assertThat(nativeBinderStats.mEnabled).isFalse(); } @Test public void testSettingsObserver_enabled() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=true"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); // Reset mock to clear previous interactions from setup (if any) Mockito.reset(mMockPropertiesWrapper); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isTrue(); Loading @@ -88,24 +112,58 @@ public class NativeBinderStatsTest { .isEqualTo(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); assertThat(nativeBinderStats.mSystemCallSharding) .isEqualTo(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); // Verify that the injector was called correctly Mockito.verify(mMockPropertiesWrapper).setEnabled(true); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); } @Test public void testSettingsObserver_disabled() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=false"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isFalse(); // Verify that the injector was called correctly Mockito.verify(mMockPropertiesWrapper).setEnabled(false); } @Test public void testSettingsObserver_changed() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=true"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isTrue(); Mockito.verify(mMockPropertiesWrapper).setEnabled(true); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); // Reset mock to clear previous interactions Mockito.reset(mMockPropertiesWrapper); Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=false"); // FakeSettingsProvider doesn't support notifications, so we need to notify manually. Loading @@ -115,6 +173,19 @@ public class NativeBinderStatsTest { false, Settings.Global.getUriFor(Settings.Global.NATIVE_BINDER_STATS), 0); assertThat(nativeBinderStats.mEnabled).isFalse(); Mockito.verify(mMockPropertiesWrapper).setEnabled(false); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); } @Test Loading @@ -124,7 +195,8 @@ public class NativeBinderStatsTest { Settings.Global.NATIVE_BINDER_STATS, "enabled=true,process_sharding=5,spam_sharding=1,call_sharding=2," + "system_process_sharding=1,system_spam_sharding=5,system_call_sharding=10"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); assertThat(nativeBinderStats.mEnabled).isTrue(); Loading @@ -134,5 +206,63 @@ public class NativeBinderStatsTest { assertThat(nativeBinderStats.mSystemProcessSharding).isEqualTo(1); assertThat(nativeBinderStats.mSystemSpamSharding).isEqualTo(5); assertThat(nativeBinderStats.mSystemCallSharding).isEqualTo(10); // Verify that the injector was called with required values Mockito.verify(mMockPropertiesWrapper).setEnabled(true); Mockito.verify(mMockPropertiesWrapper).setProcessSharding(5); Mockito.verify(mMockPropertiesWrapper).setSpamSharding(1); Mockito.verify(mMockPropertiesWrapper).setCallSharding(2); Mockito.verify(mMockPropertiesWrapper).setSystemProcessSharding(1); Mockito.verify(mMockPropertiesWrapper).setSystemSpamSharding(5); Mockito.verify(mMockPropertiesWrapper).setSystemCallSharding(10); } @Test public void testSettingsObserver_badInput() { Settings.Global.putString(mResolver, Settings.Global.NATIVE_BINDER_STATS, "enabled=truepxrocess_sharding=5,spam_sharding=1,call_sharding=2," + "system_process_sharding=1,system_spam_sharding=5,system_call_sharding=" + "10"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); // Verify that the injector was called with default values Mockito.verify(mMockPropertiesWrapper).setEnabled(NativeBinderStats.DEFAULT_ENABLED); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); // Verify that correctly got values were set Mockito.verify(mMockPropertiesWrapper).setSpamSharding(1); Mockito.verify(mMockPropertiesWrapper).setCallSharding(2); Mockito.verify(mMockPropertiesWrapper).setSystemProcessSharding(1); Mockito.verify(mMockPropertiesWrapper).setSystemSpamSharding(5); Mockito.verify(mMockPropertiesWrapper).setSystemCallSharding(10); assertThat(nativeBinderStats.mEnabled).isFalse(); } @Test public void testSettingsObserver_triggerInputException() { Settings.Global.putString( mResolver, Settings.Global.NATIVE_BINDER_STATS, "Lorem,ipsum,enable123"); NativeBinderStats nativeBinderStats = new NativeBinderStats(mContext, mMockPropertiesWrapper); nativeBinderStats.systemReady(); // Verify that the injector was called with default values Mockito.verify(mMockPropertiesWrapper).setEnabled(NativeBinderStats.DEFAULT_ENABLED); Mockito.verify(mMockPropertiesWrapper) .setProcessSharding(NativeBinderStats.DEFAULT_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSpamSharding(NativeBinderStats.DEFAULT_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setCallSharding(NativeBinderStats.DEFAULT_CALL_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemProcessSharding(NativeBinderStats.DEFAULT_SYSTEM_PROCESS_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemSpamSharding(NativeBinderStats.DEFAULT_SYSTEM_SPAM_SHARDING); Mockito.verify(mMockPropertiesWrapper) .setSystemCallSharding(NativeBinderStats.DEFAULT_SYSTEM_CALL_SHARDING); } }