From 40211be96aea4d924dd9607ae8b5ac4cacc21eab Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 24 Dec 2021 09:34:21 +0800 Subject: [PATCH] Add new class for WiFi restractions caching - Create a singleton class for Wi-Fi restricted caching. - Manages mapping between user ID and corresponding singleton object. - Add new isConfigWifiAllowed() function. Bug: 202017876 Test: manual test make RunSettingsLibRoboTests ROBOTEST_FILTER=WifiRestrictionsCacheTest Change-Id: Ieaa90f170cf679ec00cc752e5af173d151296c89 --- .../wifi/WifiRestrictionsCache.java | 131 +++++++++++++ .../wifi/WifiRestrictionsCacheTest.java | 172 ++++++++++++++++++ 2 files changed, 303 insertions(+) create mode 100644 packages/SettingsLib/src/com/android/settingslib/wifi/WifiRestrictionsCache.java create mode 100644 packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiRestrictionsCacheTest.java diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiRestrictionsCache.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiRestrictionsCache.java new file mode 100644 index 0000000000000..7ffae4094addc --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiRestrictionsCache.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.wifi; + +import static android.os.UserManager.DISALLOW_CONFIG_WIFI; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.Bundle; +import android.os.UserManager; +import android.util.SparseArray; + +import androidx.annotation.VisibleForTesting; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is a singleton class for Wi-Fi restrictions caching. + */ +public class WifiRestrictionsCache { + private static final String TAG = "WifiResCache"; + + /** + * Manages mapping between user ID and corresponding singleton {@link WifiRestrictionsCache} + * object. + */ + @VisibleForTesting + protected static final SparseArray sInstances = new SparseArray<>(); + + @VisibleForTesting + protected UserManager mUserManager; + @VisibleForTesting + protected Bundle mUserRestrictions; + @VisibleForTesting + protected final Map mRestrictions = new HashMap<>(); + + /** + * @return an instance of {@link WifiRestrictionsCache} object. + */ + @NonNull + public static WifiRestrictionsCache getInstance(@NonNull Context context) { + final int requestUserId = context.getUserId(); + WifiRestrictionsCache cache; + synchronized (sInstances) { + // We have same user context as request. + if (sInstances.indexOfKey(requestUserId) >= 0) { + return sInstances.get(requestUserId); + } + // Request by a new user context. + cache = new WifiRestrictionsCache(context); + sInstances.put(context.getUserId(), cache); + } + return cache; + } + + /** + * Removes all the instances. + */ + public static void clearInstance() { + synchronized (sInstances) { + for (int i = 0; i < sInstances.size(); i++) { + int key = sInstances.keyAt(i); + WifiRestrictionsCache cache = sInstances.get(key); + cache.clearRestrictions(); + sInstances.remove(key); + } + sInstances.clear(); + } + } + + /** + * Constructor to create a singleton class for Wi-Fi restrictions cache. + * + * @param context The Context this is associated with. + */ + protected WifiRestrictionsCache(@NonNull Context context) { + mUserManager = context.getSystemService(UserManager.class); + if (mUserManager != null) { + mUserRestrictions = mUserManager.getUserRestrictions(); + } + } + + /** + * @return the boolean value of the restrictions + */ + public Boolean getRestriction(String key) { + if (mUserRestrictions == null) { + return false; + } + Boolean restriction; + synchronized (mRestrictions) { + if (mRestrictions.containsKey(key)) { + return mRestrictions.get(key); + } + restriction = mUserRestrictions.getBoolean(key); + mRestrictions.put(key, restriction); + } + return restriction; + } + + /** + * Removes all the restrictions. + */ + public void clearRestrictions() { + synchronized (mRestrictions) { + mRestrictions.clear(); + } + } + + /** + * @return Whether the user is allowed to config Wi-Fi. + */ + public Boolean isConfigWifiAllowed() { + return !getRestriction(DISALLOW_CONFIG_WIFI); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiRestrictionsCacheTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiRestrictionsCacheTest.java new file mode 100644 index 0000000000000..404e0e88c34f2 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiRestrictionsCacheTest.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.wifi; + +import static android.os.UserManager.DISALLOW_CONFIG_WIFI; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.Bundle; +import android.os.UserManager; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class WifiRestrictionsCacheTest { + + private static final int USER_OWNER = 0; + private static final int USER_1 = 1; + private static final int USER_2 = 2; + private static final int USER_3 = 3; + private static final int USER_GUEST = 10; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + UserManager mUserManager; + @Mock + Bundle mUserRestrictionsOwner; + @Mock + Bundle mUserRestrictionsGuest; + + private Context mContext; + private WifiRestrictionsCache mWifiRestrictionsCacheOwner; + private WifiRestrictionsCache mWifiRestrictionsCacheGuest; + + @Before + public void setUp() { + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + + when(mContext.getUserId()).thenReturn(USER_OWNER); + when(mUserManager.getUserRestrictions()).thenReturn(mUserRestrictionsOwner); + when(mUserRestrictionsOwner.getBoolean(anyString())).thenReturn(false); + mWifiRestrictionsCacheOwner = WifiRestrictionsCache.getInstance(mContext); + + when(mContext.getUserId()).thenReturn(USER_GUEST); + when(mUserManager.getUserRestrictions()).thenReturn(mUserRestrictionsGuest); + when(mUserRestrictionsGuest.getBoolean(anyString())).thenReturn(true); + mWifiRestrictionsCacheGuest = WifiRestrictionsCache.getInstance(mContext); + } + + @After + public void tearDown() { + WifiRestrictionsCache.clearInstance(); + } + + @Test + public void getInstance_sameUserId_sameInstance() { + when(mContext.getUserId()).thenReturn(USER_OWNER); + WifiRestrictionsCache instance1 = WifiRestrictionsCache.getInstance(mContext); + + WifiRestrictionsCache instance2 = WifiRestrictionsCache.getInstance(mContext); + + assertThat(instance1).isEqualTo(instance2); + } + + @Test + public void getInstance_diffUserId_diffInstance() { + when(mContext.getUserId()).thenReturn(USER_OWNER); + WifiRestrictionsCache instance1 = WifiRestrictionsCache.getInstance(mContext); + + when(mContext.getUserId()).thenReturn(USER_GUEST); + WifiRestrictionsCache instance2 = WifiRestrictionsCache.getInstance(mContext); + + assertThat(instance1).isNotEqualTo(instance2); + } + + @Test + public void clearInstance_instanceShouldBeEmpty() { + WifiRestrictionsCache.clearInstance(); + + assertThat(WifiRestrictionsCache.sInstances.size()).isEqualTo(0); + } + + @Test + public void getRestriction_firstTime_getFromSystem() { + Bundle userRestrictions = mock(Bundle.class); + WifiRestrictionsCache wifiRestrictionsCache = mockInstance(USER_1, userRestrictions); + + wifiRestrictionsCache.getRestriction(DISALLOW_CONFIG_WIFI); + + verify(userRestrictions).getBoolean(DISALLOW_CONFIG_WIFI); + } + + @Test + public void getRestriction_secondTime_notGetFromSystem() { + Bundle userRestrictions = mock(Bundle.class); + WifiRestrictionsCache wifiRestrictionsCache = mockInstance(USER_2, userRestrictions); + // First time to get the restriction value + wifiRestrictionsCache.getRestriction(DISALLOW_CONFIG_WIFI); + reset(userRestrictions); + + // Second time to get the restriction value + wifiRestrictionsCache.getRestriction(DISALLOW_CONFIG_WIFI); + + verify(userRestrictions, never()).getBoolean(DISALLOW_CONFIG_WIFI); + } + + @Test + public void clearRestrictions_shouldGetRestrictionFromSystemAgain() { + Bundle userRestrictions = mock(Bundle.class); + WifiRestrictionsCache wifiRestrictionsCache = mockInstance(USER_3, userRestrictions); + // First time to get the restriction value + wifiRestrictionsCache.getRestriction(DISALLOW_CONFIG_WIFI); + reset(userRestrictions); + + // Clear the cache and then second time to get the restriction value + wifiRestrictionsCache.clearRestrictions(); + wifiRestrictionsCache.getRestriction(DISALLOW_CONFIG_WIFI); + + verify(userRestrictions).getBoolean(DISALLOW_CONFIG_WIFI); + } + + @Test + public void isConfigWifiAllowed_ownerUser_returnTrue() { + assertThat(mWifiRestrictionsCacheOwner.isConfigWifiAllowed()).isTrue(); + } + + @Test + public void isConfigWifiAllowed_guestUser_returnFalse() { + assertThat(mWifiRestrictionsCacheGuest.isConfigWifiAllowed()).isFalse(); + } + + private WifiRestrictionsCache mockInstance(int userId, Bundle userRestrictions) { + when(mContext.getUserId()).thenReturn(userId); + when(mUserManager.getUserRestrictions()).thenReturn(userRestrictions); + return WifiRestrictionsCache.getInstance(mContext); + } +}