diff options
| author | 2024-11-13 04:51:36 +0000 | |
|---|---|---|
| committer | 2024-11-13 04:51:36 +0000 | |
| commit | 4bf8a0ae05d5b1c9c9c2d7b6441e0970bebddd3c (patch) | |
| tree | 183a7dbef8d6f93baa3e3b36a42e335c97eaa658 | |
| parent | 8bc642cf86720bafdf4031a67f19b035cf932fca (diff) | |
| parent | 367a617bd0f8b75caff4d63ee4871d1a327d3a1f (diff) | |
Merge changes from topic "revert-29548976-TRGCOEXKHG" into main
* changes:
Revert "Cache sticky broadcast intents on the client side."
Revert "Include the hardcoded list of sticky broadcasts to cache."
| -rw-r--r-- | core/java/android/app/BroadcastStickyCache.java | 229 | ||||
| -rw-r--r-- | core/java/android/app/ContextImpl.java | 17 | ||||
| -rw-r--r-- | core/java/android/app/TEST_MAPPING | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastController.java | 34 | ||||
| -rw-r--r-- | tests/broadcasts/OWNERS | 2 | ||||
| -rw-r--r-- | tests/broadcasts/unit/Android.bp | 45 | ||||
| -rw-r--r-- | tests/broadcasts/unit/AndroidManifest.xml | 27 | ||||
| -rw-r--r-- | tests/broadcasts/unit/AndroidTest.xml | 29 | ||||
| -rw-r--r-- | tests/broadcasts/unit/TEST_MAPPING | 15 | ||||
| -rw-r--r-- | tests/broadcasts/unit/src/android/app/BroadcastStickyCacheTest.java | 258 |
10 files changed, 7 insertions, 653 deletions
diff --git a/core/java/android/app/BroadcastStickyCache.java b/core/java/android/app/BroadcastStickyCache.java deleted file mode 100644 index d6f061be3b00..000000000000 --- a/core/java/android/app/BroadcastStickyCache.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2024 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.app; - -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbManager; -import android.media.AudioManager; -import android.net.ConnectivityManager; -import android.net.TetheringManager; -import android.net.nsd.NsdManager; -import android.net.wifi.WifiManager; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.SystemProperties; -import android.os.UpdateLock; -import android.telephony.TelephonyManager; -import android.util.ArrayMap; -import android.view.WindowManagerPolicyConstants; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; - -import java.util.ArrayList; - -/** @hide */ -public class BroadcastStickyCache { - - private static final String[] CACHED_BROADCAST_ACTIONS = { - AudioManager.ACTION_HDMI_AUDIO_PLUG, - AudioManager.ACTION_HEADSET_PLUG, - AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED, - AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED, - AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, - AudioManager.RINGER_MODE_CHANGED_ACTION, - ConnectivityManager.CONNECTIVITY_ACTION, - Intent.ACTION_BATTERY_CHANGED, - Intent.ACTION_DEVICE_STORAGE_FULL, - Intent.ACTION_DEVICE_STORAGE_LOW, - Intent.ACTION_SIM_STATE_CHANGED, - NsdManager.ACTION_NSD_STATE_CHANGED, - TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED, - TetheringManager.ACTION_TETHER_STATE_CHANGED, - UpdateLock.UPDATE_LOCK_CHANGED, - UsbManager.ACTION_USB_STATE, - WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED, - WifiManager.NETWORK_STATE_CHANGED_ACTION, - WifiManager.SUPPLICANT_STATE_CHANGED_ACTION, - WifiManager.WIFI_STATE_CHANGED_ACTION, - WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION, - WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED, - "android.net.conn.INET_CONDITION_ACTION" // ConnectivityManager.INET_CONDITION_ACTION - }; - - @GuardedBy("sCachedStickyBroadcasts") - private static final ArrayList<CachedStickyBroadcast> sCachedStickyBroadcasts = - new ArrayList<>(); - - @GuardedBy("sCachedPropertyHandles") - private static final ArrayMap<String, SystemProperties.Handle> sCachedPropertyHandles = - new ArrayMap<>(); - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public static boolean useCache(@Nullable IntentFilter filter) { - if (!shouldCache(filter)) { - return false; - } - synchronized (sCachedStickyBroadcasts) { - final CachedStickyBroadcast cachedStickyBroadcast = getValueUncheckedLocked(filter); - if (cachedStickyBroadcast == null) { - return false; - } - final long version = cachedStickyBroadcast.propertyHandle.getLong(-1 /* def */); - return version > 0 && cachedStickyBroadcast.version == version; - } - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public static void add(@Nullable IntentFilter filter, @Nullable Intent intent) { - if (!shouldCache(filter)) { - return; - } - synchronized (sCachedStickyBroadcasts) { - CachedStickyBroadcast cachedStickyBroadcast = getValueUncheckedLocked(filter); - if (cachedStickyBroadcast == null) { - final String key = getKey(filter.getAction(0)); - final SystemProperties.Handle handle = SystemProperties.find(key); - final long version = handle == null ? -1 : handle.getLong(-1 /* def */); - if (version == -1) { - return; - } - cachedStickyBroadcast = new CachedStickyBroadcast(filter, handle); - sCachedStickyBroadcasts.add(cachedStickyBroadcast); - cachedStickyBroadcast.intent = intent; - cachedStickyBroadcast.version = version; - } else { - cachedStickyBroadcast.intent = intent; - cachedStickyBroadcast.version = cachedStickyBroadcast.propertyHandle - .getLong(-1 /* def */); - } - } - } - - private static boolean shouldCache(@Nullable IntentFilter filter) { - if (!Flags.useStickyBcastCache()) { - return false; - } - if (filter == null || filter.safeCountActions() != 1) { - return false; - } - if (!ArrayUtils.contains(CACHED_BROADCAST_ACTIONS, filter.getAction(0))) { - return false; - } - return true; - } - - @VisibleForTesting - @NonNull - public static String getKey(@NonNull String action) { - return "cache_key.system_server.sticky_bcast." + action; - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - @Nullable - public static Intent getIntentUnchecked(@NonNull IntentFilter filter) { - synchronized (sCachedStickyBroadcasts) { - final CachedStickyBroadcast cachedStickyBroadcast = getValueUncheckedLocked(filter); - return cachedStickyBroadcast.intent; - } - } - - @GuardedBy("sCachedStickyBroadcasts") - @Nullable - private static CachedStickyBroadcast getValueUncheckedLocked(@NonNull IntentFilter filter) { - for (int i = sCachedStickyBroadcasts.size() - 1; i >= 0; --i) { - final CachedStickyBroadcast cachedStickyBroadcast = sCachedStickyBroadcasts.get(i); - if (IntentFilter.filterEquals(filter, cachedStickyBroadcast.filter)) { - return cachedStickyBroadcast; - } - } - return null; - } - - public static void incrementVersion(@NonNull String action) { - if (!shouldIncrementVersion(action)) { - return; - } - final String key = getKey(action); - synchronized (sCachedPropertyHandles) { - SystemProperties.Handle handle = sCachedPropertyHandles.get(key); - final long version; - if (handle == null) { - handle = SystemProperties.find(key); - if (handle != null) { - sCachedPropertyHandles.put(key, handle); - } - } - version = handle == null ? 0 : handle.getLong(0 /* def */); - SystemProperties.set(key, String.valueOf(version + 1)); - if (handle == null) { - sCachedPropertyHandles.put(key, SystemProperties.find(key)); - } - } - } - - public static void incrementVersionIfExists(@NonNull String action) { - if (!shouldIncrementVersion(action)) { - return; - } - final String key = getKey(action); - synchronized (sCachedPropertyHandles) { - final SystemProperties.Handle handle = sCachedPropertyHandles.get(key); - if (handle == null) { - return; - } - final long version = handle.getLong(0 /* def */); - SystemProperties.set(key, String.valueOf(version + 1)); - } - } - - private static boolean shouldIncrementVersion(@NonNull String action) { - if (!Flags.useStickyBcastCache()) { - return false; - } - if (!ArrayUtils.contains(CACHED_BROADCAST_ACTIONS, action)) { - return false; - } - return true; - } - - @VisibleForTesting - public static void clearForTest() { - synchronized (sCachedStickyBroadcasts) { - sCachedStickyBroadcasts.clear(); - } - synchronized (sCachedPropertyHandles) { - sCachedPropertyHandles.clear(); - } - } - - private static final class CachedStickyBroadcast { - @NonNull public final IntentFilter filter; - @Nullable public Intent intent; - @IntRange(from = 0) public long version; - @NonNull public final SystemProperties.Handle propertyHandle; - - CachedStickyBroadcast(@NonNull IntentFilter filter, - @NonNull SystemProperties.Handle propertyHandle) { - this.filter = filter; - this.propertyHandle = propertyHandle; - } - } -} diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 3ae60d71facd..cd56957ed5d1 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1922,19 +1922,10 @@ class ContextImpl extends Context { } } try { - final Intent intent; - if (receiver == null && BroadcastStickyCache.useCache(filter)) { - intent = BroadcastStickyCache.getIntentUnchecked(filter); - } else { - intent = ActivityManager.getService().registerReceiverWithFeature( - mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), - AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, - userId, - flags); - if (receiver == null) { - BroadcastStickyCache.add(filter, intent); - } - } + final Intent intent = ActivityManager.getService().registerReceiverWithFeature( + mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), + AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId, + flags); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); // TODO: determine at registration time if caller is diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING index 637187e01160..5ed1f4e35533 100644 --- a/core/java/android/app/TEST_MAPPING +++ b/core/java/android/app/TEST_MAPPING @@ -177,10 +177,6 @@ { "file_patterns": ["(/|^)AppOpsManager.java"], "name": "CtsAppOpsTestCases" - }, - { - "file_patterns": ["(/|^)BroadcastStickyCache.java"], - "name": "BroadcastUnitTests" } ] } diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java index 8a128582c507..446b3671a94a 100644 --- a/services/core/java/com/android/server/am/BroadcastController.java +++ b/services/core/java/com/android/server/am/BroadcastController.java @@ -57,7 +57,6 @@ import android.app.ApplicationExitInfo; import android.app.ApplicationThreadConstants; import android.app.BackgroundStartPrivileges; import android.app.BroadcastOptions; -import android.app.BroadcastStickyCache; import android.app.IApplicationThread; import android.app.compat.CompatChanges; import android.appwidget.AppWidgetManager; @@ -702,7 +701,6 @@ class BroadcastController { boolean serialized, boolean sticky, int userId) { mService.enforceNotIsolatedCaller("broadcastIntent"); - int result; synchronized (mService) { intent = verifyBroadcastLocked(intent); @@ -724,7 +722,7 @@ class BroadcastController { final long origId = Binder.clearCallingIdentity(); try { - result = broadcastIntentLocked(callerApp, + return broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, callingFeatureId, intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras, requiredPermissions, excludedPermissions, excludedPackages, @@ -735,10 +733,6 @@ class BroadcastController { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } } - if (sticky && result == ActivityManager.BROADCAST_SUCCESS) { - BroadcastStickyCache.incrementVersion(intent.getAction()); - } - return result; } // Not the binder call surface @@ -749,7 +743,6 @@ class BroadcastController { boolean serialized, boolean sticky, int userId, BackgroundStartPrivileges backgroundStartPrivileges, @Nullable int[] broadcastAllowList) { - int result; synchronized (mService) { intent = verifyBroadcastLocked(intent); @@ -757,7 +750,7 @@ class BroadcastController { String[] requiredPermissions = requiredPermission == null ? null : new String[] {requiredPermission}; try { - result = broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, + return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras, requiredPermissions, null, null, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, realCallingPid, userId, @@ -767,10 +760,6 @@ class BroadcastController { Binder.restoreCallingIdentity(origId); } } - if (sticky && result == ActivityManager.BROADCAST_SUCCESS) { - BroadcastStickyCache.incrementVersion(intent.getAction()); - } - return result; } @GuardedBy("mService") @@ -1469,7 +1458,6 @@ class BroadcastController { list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid, callerAppProcessState, resolvedType)); } - BroadcastStickyCache.incrementVersion(intent.getAction()); } } @@ -1736,7 +1724,6 @@ class BroadcastController { Slog.w(TAG, msg); throw new SecurityException(msg); } - final ArrayList<String> changedStickyBroadcasts = new ArrayList<>(); synchronized (mStickyBroadcasts) { ArrayMap<String, ArrayList<StickyBroadcast>> stickies = mStickyBroadcasts.get(userId); if (stickies != null) { @@ -1753,16 +1740,12 @@ class BroadcastController { if (list.size() <= 0) { stickies.remove(intent.getAction()); } - changedStickyBroadcasts.add(intent.getAction()); } if (stickies.size() <= 0) { mStickyBroadcasts.remove(userId); } } } - for (int i = changedStickyBroadcasts.size() - 1; i >= 0; --i) { - BroadcastStickyCache.incrementVersionIfExists(changedStickyBroadcasts.get(i)); - } } void finishReceiver(IBinder caller, int resultCode, String resultData, @@ -1925,9 +1908,7 @@ class BroadcastController { private void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) { mService.mProcessList.sendPackageBroadcastLocked(cmd, packages, userId); - } - - private List<ResolveInfo> collectReceiverComponents( + }private List<ResolveInfo> collectReceiverComponents( Intent intent, String resolvedType, int callingUid, int callingPid, int[] users, int[] broadcastAllowList) { // TODO: come back and remove this assumption to triage all broadcasts @@ -2143,18 +2124,9 @@ class BroadcastController { } void removeStickyBroadcasts(int userId) { - final ArrayList<String> changedStickyBroadcasts = new ArrayList<>(); synchronized (mStickyBroadcasts) { - final ArrayMap<String, ArrayList<StickyBroadcast>> stickies = - mStickyBroadcasts.get(userId); - if (stickies != null) { - changedStickyBroadcasts.addAll(stickies.keySet()); - } mStickyBroadcasts.remove(userId); } - for (int i = changedStickyBroadcasts.size() - 1; i >= 0; --i) { - BroadcastStickyCache.incrementVersionIfExists(changedStickyBroadcasts.get(i)); - } } @NeverCompile diff --git a/tests/broadcasts/OWNERS b/tests/broadcasts/OWNERS deleted file mode 100644 index d2e1f815e8dc..000000000000 --- a/tests/broadcasts/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# Bug component: 316181 -include platform/frameworks/base:/BROADCASTS_OWNERS diff --git a/tests/broadcasts/unit/Android.bp b/tests/broadcasts/unit/Android.bp deleted file mode 100644 index 47166a713580..000000000000 --- a/tests/broadcasts/unit/Android.bp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (C) 2024 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 { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], - default_team: "trendy_team_framework_backstage_power", -} - -android_test { - name: "BroadcastUnitTests", - srcs: ["src/**/*.java"], - defaults: [ - "modules-utils-extended-mockito-rule-defaults", - ], - static_libs: [ - "androidx.test.runner", - "androidx.test.rules", - "androidx.test.ext.junit", - "mockito-target-extended-minus-junit4", - "truth", - "flag-junit", - "android.app.flags-aconfig-java", - ], - certificate: "platform", - platform_apis: true, - test_suites: ["device-tests"], -} diff --git a/tests/broadcasts/unit/AndroidManifest.xml b/tests/broadcasts/unit/AndroidManifest.xml deleted file mode 100644 index e9c5248e4d98..000000000000 --- a/tests/broadcasts/unit/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2024 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.broadcasts.unit" > - - <application android:debuggable="true"> - <uses-library android:name="android.test.runner" /> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.broadcasts.unit" - android:label="Broadcasts Unit Tests"/> -</manifest>
\ No newline at end of file diff --git a/tests/broadcasts/unit/AndroidTest.xml b/tests/broadcasts/unit/AndroidTest.xml deleted file mode 100644 index b91e4783b69e..000000000000 --- a/tests/broadcasts/unit/AndroidTest.xml +++ /dev/null @@ -1,29 +0,0 @@ -<!-- Copyright (C) 2024 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. ---> -<configuration description="Runs Broadcasts tests"> - <option name="test-suite-tag" value="apct" /> - <option name="test-tag" value="BroadcastUnitTests" /> - - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="BroadcastUnitTests.apk" /> - </target_preparer> - - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.broadcasts.unit" /> - <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> - <option name="hidden-api-checks" value="false"/> - </test> -</configuration>
\ No newline at end of file diff --git a/tests/broadcasts/unit/TEST_MAPPING b/tests/broadcasts/unit/TEST_MAPPING deleted file mode 100644 index 8919fdcd7a3f..000000000000 --- a/tests/broadcasts/unit/TEST_MAPPING +++ /dev/null @@ -1,15 +0,0 @@ -{ - "presubmit": [ - { - "name": "BroadcastUnitTests", - "options": [ - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation": "org.junit.Ignore" - } - ] - } - ] -} diff --git a/tests/broadcasts/unit/src/android/app/BroadcastStickyCacheTest.java b/tests/broadcasts/unit/src/android/app/BroadcastStickyCacheTest.java deleted file mode 100644 index b7c412dea999..000000000000 --- a/tests/broadcasts/unit/src/android/app/BroadcastStickyCacheTest.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2024 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.app; - -import static android.content.Intent.ACTION_BATTERY_CHANGED; -import static android.content.Intent.ACTION_DEVICE_STORAGE_LOW; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; - -import android.content.Intent; -import android.content.IntentFilter; -import android.os.BatteryManager; -import android.os.Bundle; -import android.os.SystemProperties; -import android.platform.test.annotations.EnableFlags; -import android.platform.test.flag.junit.SetFlagsRule; -import android.util.ArrayMap; - -import androidx.annotation.GuardedBy; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.modules.utils.testing.ExtendedMockitoRule; - -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; - -@EnableFlags(Flags.FLAG_USE_STICKY_BCAST_CACHE) -@RunWith(AndroidJUnit4.class) -@SmallTest -public class BroadcastStickyCacheTest { - @ClassRule - public static final SetFlagsRule.ClassRule mClassRule = new SetFlagsRule.ClassRule(); - @Rule - public final SetFlagsRule mSetFlagsRule = mClassRule.createSetFlagsRule(); - - @Rule - public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) - .mockStatic(SystemProperties.class) - .build(); - - private static final String PROP_KEY_BATTERY_CHANGED = BroadcastStickyCache.getKey( - ACTION_BATTERY_CHANGED); - - private final TestSystemProps mTestSystemProps = new TestSystemProps(); - - @Before - public void setUp() { - doAnswer(invocation -> { - final String name = invocation.getArgument(0); - final long value = Long.parseLong(invocation.getArgument(1)); - mTestSystemProps.add(name, value); - return null; - }).when(() -> SystemProperties.set(anyString(), anyString())); - doAnswer(invocation -> { - final String name = invocation.getArgument(0); - final TestSystemProps.Handle testHandle = mTestSystemProps.query(name); - if (testHandle == null) { - return null; - } - final SystemProperties.Handle handle = Mockito.mock(SystemProperties.Handle.class); - doAnswer(handleInvocation -> testHandle.getLong(-1)).when(handle).getLong(anyLong()); - return handle; - }).when(() -> SystemProperties.find(anyString())); - } - - @After - public void tearDown() { - mTestSystemProps.clear(); - BroadcastStickyCache.clearForTest(); - } - - @Test - public void testUseCache_nullFilter() { - assertThat(BroadcastStickyCache.useCache(null)).isEqualTo(false); - } - - @Test - public void testUseCache_noActions() { - final IntentFilter filter = new IntentFilter(); - assertThat(BroadcastStickyCache.useCache(filter)).isEqualTo(false); - } - - @Test - public void testUseCache_multipleActions() { - final IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_DEVICE_STORAGE_LOW); - filter.addAction(ACTION_BATTERY_CHANGED); - assertThat(BroadcastStickyCache.useCache(filter)).isEqualTo(false); - } - - @Test - public void testUseCache_valueNotSet() { - final IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED); - assertThat(BroadcastStickyCache.useCache(filter)).isEqualTo(false); - } - - @Test - public void testUseCache() { - final IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED); - final Intent intent = new Intent(ACTION_BATTERY_CHANGED) - .putExtra(BatteryManager.EXTRA_LEVEL, 90); - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - BroadcastStickyCache.add(filter, intent); - assertThat(BroadcastStickyCache.useCache(filter)).isEqualTo(true); - } - - @Test - public void testUseCache_versionMismatch() { - final IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED); - final Intent intent = new Intent(ACTION_BATTERY_CHANGED) - .putExtra(BatteryManager.EXTRA_LEVEL, 90); - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - BroadcastStickyCache.add(filter, intent); - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - - assertThat(BroadcastStickyCache.useCache(filter)).isEqualTo(false); - } - - @Test - public void testAdd() { - final IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED); - Intent intent = new Intent(ACTION_BATTERY_CHANGED) - .putExtra(BatteryManager.EXTRA_LEVEL, 90); - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - BroadcastStickyCache.add(filter, intent); - assertThat(BroadcastStickyCache.useCache(filter)).isEqualTo(true); - Intent actualIntent = BroadcastStickyCache.getIntentUnchecked(filter); - assertThat(actualIntent).isNotNull(); - assertEquals(actualIntent, intent); - - intent = new Intent(ACTION_BATTERY_CHANGED) - .putExtra(BatteryManager.EXTRA_LEVEL, 99); - BroadcastStickyCache.add(filter, intent); - actualIntent = BroadcastStickyCache.getIntentUnchecked(filter); - assertThat(actualIntent).isNotNull(); - assertEquals(actualIntent, intent); - } - - @Test - public void testIncrementVersion_propExists() { - SystemProperties.set(PROP_KEY_BATTERY_CHANGED, String.valueOf(100)); - - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(101); - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(102); - } - - @Test - public void testIncrementVersion_propNotExists() { - // Verify that the property doesn't exist - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(-1); - - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(1); - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(2); - } - - @Test - public void testIncrementVersionIfExists_propExists() { - BroadcastStickyCache.incrementVersion(ACTION_BATTERY_CHANGED); - - BroadcastStickyCache.incrementVersionIfExists(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(2); - BroadcastStickyCache.incrementVersionIfExists(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(3); - } - - @Test - public void testIncrementVersionIfExists_propNotExists() { - // Verify that the property doesn't exist - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(-1); - - BroadcastStickyCache.incrementVersionIfExists(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(-1); - // Verify that property is not added as part of the querying. - BroadcastStickyCache.incrementVersionIfExists(ACTION_BATTERY_CHANGED); - assertThat(mTestSystemProps.get(PROP_KEY_BATTERY_CHANGED, -1 /* def */)).isEqualTo(-1); - } - - private void assertEquals(Intent actualIntent, Intent expectedIntent) { - assertThat(actualIntent.getAction()).isEqualTo(expectedIntent.getAction()); - assertEquals(actualIntent.getExtras(), expectedIntent.getExtras()); - } - - private void assertEquals(Bundle actualExtras, Bundle expectedExtras) { - assertWithMessage("Extras expected=%s, actual=%s", expectedExtras, actualExtras) - .that(actualExtras.kindofEquals(expectedExtras)).isTrue(); - } - - private static final class TestSystemProps { - @GuardedBy("mSysProps") - private final ArrayMap<String, Long> mSysProps = new ArrayMap<>(); - - public void add(String name, long value) { - synchronized (mSysProps) { - mSysProps.put(name, value); - } - } - - public long get(String name, long defaultValue) { - synchronized (mSysProps) { - final int idx = mSysProps.indexOfKey(name); - return idx >= 0 ? mSysProps.valueAt(idx) : defaultValue; - } - } - - public Handle query(String name) { - synchronized (mSysProps) { - return mSysProps.containsKey(name) ? new Handle(name) : null; - } - } - - public void clear() { - synchronized (mSysProps) { - mSysProps.clear(); - } - } - - public class Handle { - private final String mName; - - Handle(String name) { - mName = name; - } - - public long getLong(long defaultValue) { - return get(mName, defaultValue); - } - } - } -} |