diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index 743c7f9815a..f59dc60d6e0 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -26,13 +26,16 @@ import android.app.PendingIntent; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.net.wifi.WifiManager; +import android.os.Binder; import android.os.Bundle; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.drawable.IconCompat; @@ -49,8 +52,8 @@ import com.android.settings.network.WifiSwitchPreferenceController; import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.slices.SliceBuilderUtils; +import com.android.settings.wifi.AppStateChangeWifiStateBridge; import com.android.settings.wifi.WifiDialogActivity; -import com.android.settings.wifi.WifiSettings; import com.android.settings.wifi.WifiUtils; import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.wifitrackerlib.WifiEntry; @@ -67,6 +70,7 @@ public class WifiSlice implements CustomSliceable { @VisibleForTesting static final int DEFAULT_EXPANDED_ROW_COUNT = 3; + private static final String TAG = "WifiSlice"; protected final Context mContext; protected final WifiManager mWifiManager; @@ -83,6 +87,12 @@ public class WifiSlice implements CustomSliceable { @Override public Slice getSlice() { + // If external calling package doesn't have Wi-Fi permission. + if (!Utils.isSettingsIntelligence(mContext) && !isPermissionGranted(mContext)) { + Log.i(TAG, "No wifi permissions to control wifi slice."); + return null; + } + final boolean isWifiEnabled = isWifiEnabled(); ListBuilder listBuilder = getListBuilder(isWifiEnabled, null /* wifiSliceItem */); if (!isWifiEnabled) { @@ -120,6 +130,30 @@ public class WifiSlice implements CustomSliceable { return listBuilder.build(); } + private static boolean isPermissionGranted(Context settingsContext) { + final int callingUid = Binder.getCallingUid(); + final String callingPackage = settingsContext.getPackageManager() + .getPackagesForUid(callingUid)[0]; + + Context packageContext; + try { + packageContext = settingsContext.createPackageContext(callingPackage, 0); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Cannot create Context for package: " + callingPackage); + return false; + } + + // If app doesn't have related Wi-Fi permission, they shouldn't show Wi-Fi slice. + final boolean hasPermission = packageContext.checkPermission( + android.Manifest.permission.CHANGE_WIFI_STATE, Binder.getCallingPid(), + callingUid) == PackageManager.PERMISSION_GRANTED; + AppStateChangeWifiStateBridge.WifiSettingsState state = + new AppStateChangeWifiStateBridge(settingsContext, null, null) + .getWifiSettingsInfo(callingPackage, callingUid); + + return hasPermission && state.isPermissible(); + } + protected boolean isApRowCollapsed() { return false; } @@ -175,7 +209,7 @@ public class WifiSlice implements CustomSliceable { tint = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal); } else { tint = Utils.getDisabled(mContext, Utils.getColorAttrDefaultColor(mContext, - android.R.attr.colorControlNormal)); + android.R.attr.colorControlNormal)); } final Drawable drawable = mContext.getDrawable( @@ -275,7 +309,7 @@ public class WifiSlice implements CustomSliceable { final String key = WifiSwitchPreferenceController.KEY; final Intent intent = SliceBuilderUtils.buildSearchResultPageIntent(mContext, className, - key, screenTitle, SettingsEnums.DIALOG_WIFI_AP_EDIT, this) + key, screenTitle, SettingsEnums.DIALOG_WIFI_AP_EDIT, this) .setClassName(mContext.getPackageName(), SubSettings.class.getName()) .setData(contentUri); diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiSlice.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiSlice.java new file mode 100644 index 00000000000..ed583a4f0fe --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiSlice.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 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.settings.testutils.shadow; + +import android.content.Context; + +import com.android.settings.wifi.slice.WifiSlice; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(WifiSlice.class) +public class ShadowWifiSlice { + + private static boolean sIsWifiPermissible; + + @Implementation + protected static boolean isPermissionGranted(Context settingsContext) { + return sIsWifiPermissible; + } + + public static void setWifiPermissible(boolean isWifiPermissible) { + sIsWifiPermissible = isWifiPermissible; + } +} diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java index f31c216d260..52dcb5282da 100644 --- a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java +++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java @@ -24,9 +24,11 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; +import android.content.pm.PackageManager; import android.net.Network; import android.net.NetworkCapabilities; import android.net.wifi.WifiInfo; @@ -44,6 +46,7 @@ import com.android.settings.slices.CustomSliceRegistry; import com.android.settings.slices.SlicesFeatureProviderImpl; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowConnectivityManager; +import com.android.settings.testutils.shadow.ShadowWifiSlice; import org.junit.Before; import org.junit.Test; @@ -53,17 +56,20 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowBinder; import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(shadows = ShadowConnectivityManager.class) +@Config(shadows = {ShadowConnectivityManager.class, ShadowWifiSlice.class}) public class ContextualWifiSliceTest { private static final String SSID = "123"; @Mock private WifiManager mWifiManager; @Mock + private PackageManager mPackageManager; + @Mock private WifiInfo mWifiInfo; @Mock private Network mNetwork; @@ -88,10 +94,16 @@ public class ContextualWifiSliceTest { doReturn(mWifiInfo).when(mWifiManager).getConnectionInfo(); doReturn(SSID).when(mWifiInfo).getSSID(); doReturn(mNetwork).when(mWifiManager).getCurrentNetwork(); + when(mContext.getPackageManager()).thenReturn(mPackageManager); // Set-up specs for SliceMetadata. SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + final String siPackageName = + mContext.getString(R.string.config_settingsintelligence_package_name); + ShadowBinder.setCallingUid(1); + when(mPackageManager.getPackagesForUid(1)).thenReturn(new String[]{siPackageName}); + ShadowWifiSlice.setWifiPermissible(true); mWifiSlice = new ContextualWifiSlice(mContext); } diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java index b4a8b05f648..5b7a7d6c33f 100644 --- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java +++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java @@ -31,21 +31,20 @@ import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.Uri; import android.net.wifi.WifiManager; -import androidx.core.graphics.drawable.IconCompat; import androidx.slice.Slice; import androidx.slice.SliceItem; -import androidx.slice.SliceMetadata; import androidx.slice.SliceProvider; -import androidx.slice.core.SliceAction; import androidx.slice.core.SliceQuery; import androidx.slice.widget.SliceLiveData; import com.android.settings.R; import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.testutils.SliceTester; +import com.android.settings.testutils.shadow.ShadowWifiSlice; import com.android.wifitrackerlib.WifiEntry; import com.android.wifitrackerlib.WifiEntry.ConnectedState; @@ -59,24 +58,32 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowBinder; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(shadows = WifiSliceTest.ShadowSliceBackgroundWorker.class) +@Config(shadows = { + WifiSliceTest.ShadowSliceBackgroundWorker.class, + ShadowWifiSlice.class}) public class WifiSliceTest { private static final String AP1_NAME = "ap1"; private static final String AP2_NAME = "ap2"; private static final String AP3_NAME = "ap3"; + private static final int USER_ID = 1; @Mock private WifiManager mWifiManager; + @Mock + private PackageManager mPackageManager; + private Context mContext; private ContentResolver mResolver; private WifiSlice mWifiSlice; + private String mSIPackageName; @Before public void setUp() { @@ -86,27 +93,46 @@ public class WifiSliceTest { doReturn(mResolver).when(mContext).getContentResolver(); doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class); doReturn(WifiManager.WIFI_STATE_ENABLED).when(mWifiManager).getWifiState(); + when(mContext.getPackageManager()).thenReturn(mPackageManager); // Set-up specs for SliceMetadata. SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + mSIPackageName = mContext.getString(R.string.config_settingsintelligence_package_name); + ShadowBinder.setCallingUid(USER_ID); + when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{mSIPackageName}); + ShadowWifiSlice.setWifiPermissible(true); mWifiSlice = new WifiSlice(mContext); } @Test - public void getWifiSlice_shouldHaveTitleAndToggle() { + public void getWifiSlice_fromSIPackage_shouldHaveTitleAndToggle() { + when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{mSIPackageName}); + ShadowWifiSlice.setWifiPermissible(false); + final Slice wifiSlice = mWifiSlice.getSlice(); - final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice); - assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.wifi_settings)); + assertThat(wifiSlice).isNotNull(); + } - final List toggles = metadata.getToggles(); - assertThat(toggles).hasSize(1); + @Test + public void getWifiSlice_notFromSIPackageAndWithWifiPermission_shouldHaveTitleAndToggle() { + when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{"com.test"}); + ShadowWifiSlice.setWifiPermissible(true); - final SliceAction primaryAction = metadata.getPrimaryAction(); - final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext, - R.drawable.ic_settings_wireless); - assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString()); + final Slice wifiSlice = mWifiSlice.getSlice(); + + assertThat(wifiSlice).isNotNull(); + } + + @Test + public void getWifiSlice_notFromSIPackageAndWithoutWifiPermission_shouldNoSlice() { + when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{"com.test"}); + ShadowWifiSlice.setWifiPermissible(false); + + final Slice wifiSlice = mWifiSlice.getSlice(); + + assertThat(wifiSlice).isNull(); } @Test