From 4c4a1f58c16d05c96dafae1047b44fe6e6a9a8c0 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 25 Mar 2022 21:39:02 +0800 Subject: [PATCH] Restrict secondary users to share Wi-Fi network - Remove "Share" and "Forget" options from the long press menu - Add SafetyNet Logging for security report Bug: 206986392 Test: manual test make RunSettingsRoboTests \ ROBOTEST_FILTER=NetworkProviderSettingsTest Change-Id: Ic434f0583cba557228c72508a501347ffa3141e1 Merged-In: Ic434f0583cba557228c72508a501347ffa3141e1 --- .../network/NetworkProviderSettings.java | 34 +++++- .../network/NetworkProviderSettingsTest.java | 100 +++++++++++++++++- 2 files changed, 127 insertions(+), 7 deletions(-) diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index 35a34d471a8..f7b88930190 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -33,9 +33,11 @@ import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; +import android.os.UserManager; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.EventLog; import android.util.FeatureFlagUtils; import android.util.Log; import android.view.ContextMenu; @@ -199,6 +201,8 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment * by the Test DPC tool in AFW mode. */ protected boolean mIsRestricted; + @VisibleForTesting + boolean mIsAdmin = true; @VisibleForTesting AirplaneModeEnabler mAirplaneModeEnabler; @@ -280,6 +284,13 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment addPreferences(); mIsRestricted = isUiRestricted(); + mIsAdmin = isAdminUser(); + } + + private boolean isAdminUser() { + final UserManager userManager = getSystemService(UserManager.class); + if (userManager == null) return true; + return userManager.isAdminUser(); } private void addPreferences() { @@ -538,7 +549,9 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment } if (mSelectedWifiEntry.canDisconnect()) { - menu.add(Menu.NONE, MENU_ID_SHARE, 0 /* order */, R.string.share); + if (mSelectedWifiEntry.canShare()) { + addShareMenuIfSuitable(menu); + } menu.add(Menu.NONE, MENU_ID_DISCONNECT, 1 /* order */, R.string.wifi_disconnect_button_text); } @@ -546,7 +559,7 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment // "forget" for normal saved network. And "disconnect" for ephemeral network because it // could only be disconnected and be put in blocklists so it won't be used again. if (canForgetNetwork()) { - menu.add(Menu.NONE, MENU_ID_FORGET, 0 /* order */, R.string.forget); + addForgetMenuIfSuitable(menu); } WifiConfiguration config = mSelectedWifiEntry.getWifiConfiguration(); @@ -561,6 +574,23 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment } } + @VisibleForTesting + void addShareMenuIfSuitable(ContextMenu menu) { + if (mIsAdmin) { + menu.add(Menu.NONE, MENU_ID_SHARE, 0 /* order */, R.string.share); + return; + } + Log.w(TAG, "Don't add the Wi-Fi share menu because the user is not an admin."); + EventLog.writeEvent(0x534e4554, "206986392", -1 /* UID */, "User is not an admin"); + } + + @VisibleForTesting + void addForgetMenuIfSuitable(ContextMenu menu) { + if (mIsAdmin) { + menu.add(Menu.NONE, MENU_ID_FORGET, 0 /* order */, R.string.forget); + } + } + private boolean canForgetNetwork() { return mSelectedWifiEntry.canForget() && !WifiUtils.isNetworkLockedDown(getActivity(), mSelectedWifiEntry.getWifiConfiguration()); diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java index 19b044b7abf..38472c5e1c2 100644 --- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java +++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java @@ -15,6 +15,9 @@ */ package com.android.settings.network; +import static com.android.settings.network.NetworkProviderSettings.MENU_ID_DISCONNECT; +import static com.android.settings.network.NetworkProviderSettings.MENU_ID_FORGET; +import static com.android.settings.network.NetworkProviderSettings.MENU_ID_SHARE; import static com.android.settings.wifi.WifiConfigUiBase2.MODE_CONNECT; import static com.android.settings.wifi.WifiConfigUiBase2.MODE_MODIFY; @@ -76,6 +79,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -105,6 +109,8 @@ public class NetworkProviderSettingsTest { @Mock private WifiPickerTracker mMockWifiPickerTracker; @Mock + private WifiEntry mWifiEntry; + @Mock private PreferenceManager mPreferenceManager; @Mock private InternetResetHelper mInternetResetHelper; @@ -113,6 +119,8 @@ public class NetworkProviderSettingsTest { @Mock private LayoutPreference mResetInternetPreference; @Mock + private ContextMenu mContextMenu; + @Mock private MenuItem mMenuItem; @Mock InternetUpdater mInternetUpdater; @@ -317,12 +325,54 @@ public class NetworkProviderSettingsTest { final View view = mock(View.class); when(view.getTag()).thenReturn(connectedWifiEntryPreference); - final ContextMenu menu = mock(ContextMenu.class); - mNetworkProviderSettings.onCreateContextMenu(menu, view, null /* info */); + mNetworkProviderSettings.onCreateContextMenu(mContextMenu, view, null /* info */); - verify(menu).add(anyInt(), eq(NetworkProviderSettings.MENU_ID_FORGET), anyInt(), anyInt()); - verify(menu).add(anyInt(), eq(NetworkProviderSettings.MENU_ID_DISCONNECT), anyInt(), - anyInt()); + verify(mContextMenu).add(anyInt(), eq(MENU_ID_FORGET), anyInt(), anyInt()); + verify(mContextMenu).add(anyInt(), eq(MENU_ID_DISCONNECT), anyInt(), anyInt()); + } + + @Test + public void onCreateContextMenu_canShare_shouldHaveShareMenuForConnectedWifiEntry() { + final FragmentActivity activity = mock(FragmentActivity.class); + when(activity.getApplicationContext()).thenReturn(mContext); + when(mNetworkProviderSettings.getActivity()).thenReturn(activity); + + when(mWifiEntry.canDisconnect()).thenReturn(true); + when(mWifiEntry.canShare()).thenReturn(true); + when(mWifiEntry.canForget()).thenReturn(true); + when(mWifiEntry.isSaved()).thenReturn(true); + when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); + + final LongPressWifiEntryPreference connectedWifiEntryPreference = + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); + final View view = mock(View.class); + when(view.getTag()).thenReturn(connectedWifiEntryPreference); + + mNetworkProviderSettings.onCreateContextMenu(mContextMenu, view, null /* info */); + + verify(mContextMenu).add(anyInt(), eq(MENU_ID_SHARE), anyInt(), anyInt()); + } + + @Test + public void onCreateContextMenu_canNotShare_shouldDisappearShareMenuForConnectedWifiEntry() { + final FragmentActivity activity = mock(FragmentActivity.class); + when(activity.getApplicationContext()).thenReturn(mContext); + when(mNetworkProviderSettings.getActivity()).thenReturn(activity); + + when(mWifiEntry.canDisconnect()).thenReturn(true); + when(mWifiEntry.canShare()).thenReturn(false); + when(mWifiEntry.canForget()).thenReturn(true); + when(mWifiEntry.isSaved()).thenReturn(true); + when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); + + final LongPressWifiEntryPreference connectedWifiEntryPreference = + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); + final View view = mock(View.class); + when(view.getTag()).thenReturn(connectedWifiEntryPreference); + + mNetworkProviderSettings.onCreateContextMenu(mContextMenu, view, null /* info */); + + verify(mContextMenu, never()).add(anyInt(), eq(MENU_ID_SHARE), anyInt(), anyInt()); } @Test @@ -546,6 +596,46 @@ public class NetworkProviderSettingsTest { verify(mAirplaneModeEnabler).stop(); } + @Test + public void addShareMenuIfSuitable_isAdmin_addMenu() { + mNetworkProviderSettings.mIsAdmin = true; + Mockito.reset(mContextMenu); + + mNetworkProviderSettings.addShareMenuIfSuitable(mContextMenu); + + verify(mContextMenu).add(anyInt(), eq(MENU_ID_SHARE), anyInt(), anyInt()); + } + + @Test + public void addShareMenuIfSuitable_isNotAdmin_notAddMenu() { + mNetworkProviderSettings.mIsAdmin = false; + Mockito.reset(mContextMenu); + + mNetworkProviderSettings.addShareMenuIfSuitable(mContextMenu); + + verify(mContextMenu, never()).add(anyInt(), eq(MENU_ID_SHARE), anyInt(), anyInt()); + } + + @Test + public void addForgetMenuIfSuitable_isAdmin_addMenu() { + mNetworkProviderSettings.mIsAdmin = true; + Mockito.reset(mContextMenu); + + mNetworkProviderSettings.addForgetMenuIfSuitable(mContextMenu); + + verify(mContextMenu).add(anyInt(), eq(MENU_ID_FORGET), anyInt(), anyInt()); + } + + @Test + public void addForgetMenuIfSuitable_isNotAdmin_notAddMenu() { + mNetworkProviderSettings.mIsAdmin = false; + Mockito.reset(mContextMenu); + + mNetworkProviderSettings.addForgetMenuIfSuitable(mContextMenu); + + verify(mContextMenu, never()).add(anyInt(), eq(MENU_ID_FORGET), anyInt(), anyInt()); + } + @Implements(PreferenceFragmentCompat.class) public static class ShadowPreferenceFragmentCompat {