From 71d39b9c2654fcff007f32df0ac833dbc4283536 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Tue, 26 Apr 2022 05:23:37 +0800 Subject: [PATCH] Create WifiPermissionChecker in SettingsLib - Get the launched package name from ActivityManager - Add method to check ACCESS_WIFI_STATE permission - Add method to check ACCESS_FINE_LOCATION permission Bug: 187176859 Test: manual test make RunSettingsLibRoboTests \ ROBOTEST_FILTER=WifiPermissionCheckerTest Change-Id: Ia5de60b88fc97ef532941c0c10ebf069d4216134 --- .../wifi/WifiPermissionChecker.java | 98 ++++++++++++++++ .../wifi/WifiPermissionCheckerTest.java | 111 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 packages/SettingsLib/src/com/android/settingslib/wifi/WifiPermissionChecker.java create mode 100644 packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiPermissionCheckerTest.java diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiPermissionChecker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiPermissionChecker.java new file mode 100644 index 0000000000000..2fe6e4695b3c6 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiPermissionChecker.java @@ -0,0 +1,98 @@ +/* + * 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.settingslib.wifi; + +import static android.Manifest.permission.ACCESS_FINE_LOCATION; +import static android.Manifest.permission.ACCESS_WIFI_STATE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.IActivityManager; +import android.content.pm.PackageManager; +import android.os.RemoteException; +import android.text.TextUtils; +import android.util.Log; + +/** + * Helper class to check Wi-Fi permissions. + */ +public class WifiPermissionChecker { + + private static final String TAG = "WifiPermChecker"; + + private IActivityManager mActivityManager; + private PackageManager mPackageManager; + private String mLaunchedPackage; + + public WifiPermissionChecker(Activity activity) { + this(activity, ActivityManager.getService()); + } + + public WifiPermissionChecker(Activity activity, IActivityManager activityManager) { + mActivityManager = activityManager; + mPackageManager = activity.getPackageManager(); + mLaunchedPackage = getLaunchedFromPackage(activity); + } + + /** + * Returns the launched package name + */ + public String getLaunchedPackage() { + return mLaunchedPackage; + } + + /** + * Returns whether the launched package can access Wi-Fi information + */ + public boolean canAccessWifiState() { + return checkPermission(ACCESS_WIFI_STATE); + } + + /** + * Returns whether the launched package can access precise location + */ + public boolean canAccessFineLocation() { + return checkPermission(ACCESS_FINE_LOCATION); + } + + private boolean checkPermission(String permission) { + if (mPackageManager == null || TextUtils.isEmpty(mLaunchedPackage)) { + Log.e(TAG, "Failed to check package permission!" + + " {PackageManager:" + mPackageManager + + ", LaunchedPackage:" + mLaunchedPackage + "}"); + return false; + } + + if (mPackageManager.checkPermission(permission, mLaunchedPackage) == PERMISSION_GRANTED) { + return true; + } + + Log.w(TAG, "The launched package does not have the required permission!" + + " {LaunchedPackage:" + mLaunchedPackage + ", Permission:" + permission + "}"); + return false; + } + + private String getLaunchedFromPackage(Activity activity) { + try { + return mActivityManager.getLaunchedFromPackage(activity.getActivityToken()); + } catch (RemoteException e) { + Log.e(TAG, "Can not get the launched package from activity manager!"); + return null; + } + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiPermissionCheckerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiPermissionCheckerTest.java new file mode 100644 index 0000000000000..ec84141360e4d --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiPermissionCheckerTest.java @@ -0,0 +1,111 @@ +/* + * 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.settingslib.wifi; + +import static android.Manifest.permission.ACCESS_FINE_LOCATION; +import static android.Manifest.permission.ACCESS_WIFI_STATE; +import static android.content.pm.PackageManager.PERMISSION_DENIED; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.app.IActivityManager; +import android.content.pm.PackageManager; +import android.os.RemoteException; + +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 WifiPermissionCheckerTest { + + static final String LAUNCHED_PACKAGE = "TestPackage"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + PackageManager mPackageManager; + @Mock + IActivityManager mActivityManager; + @Mock + Activity mActivity; + + WifiPermissionChecker mWifiPermissionChecker; + + @Before + public void setUp() { + when(mActivity.getPackageManager()).thenReturn(mPackageManager); + fakeGetLaunchedFromPackage(LAUNCHED_PACKAGE); + + mWifiPermissionChecker = new WifiPermissionChecker(mActivity, mActivityManager); + } + + @Test + public void getLaunchedPackage_returnLaunchedFromPackage() { + assertThat(mWifiPermissionChecker.getLaunchedPackage()).isEqualTo(LAUNCHED_PACKAGE); + } + + @Test + public void canAccessWifiState_noPermission_returnFalse() { + when(mPackageManager.checkPermission(ACCESS_WIFI_STATE, LAUNCHED_PACKAGE)) + .thenReturn(PERMISSION_DENIED); + + assertThat(mWifiPermissionChecker.canAccessWifiState()).isFalse(); + } + + @Test + public void canAccessWifiState_hasPermission_returnTrue() { + when(mPackageManager.checkPermission(ACCESS_WIFI_STATE, LAUNCHED_PACKAGE)) + .thenReturn(PERMISSION_GRANTED); + + assertThat(mWifiPermissionChecker.canAccessWifiState()).isTrue(); + } + + @Test + public void canAccessFineLocation_noPermission_returnFalse() { + when(mPackageManager.checkPermission(ACCESS_FINE_LOCATION, LAUNCHED_PACKAGE)) + .thenReturn(PERMISSION_DENIED); + + assertThat(mWifiPermissionChecker.canAccessFineLocation()).isFalse(); + } + + @Test + public void canAccessFineLocation_hasPermission_returnTrue() { + when(mPackageManager.checkPermission(ACCESS_FINE_LOCATION, LAUNCHED_PACKAGE)) + .thenReturn(PERMISSION_GRANTED); + + assertThat(mWifiPermissionChecker.canAccessFineLocation()).isTrue(); + } + + void fakeGetLaunchedFromPackage(String packageName) { + try { + when(mActivityManager.getLaunchedFromPackage(any())).thenReturn(packageName); + } catch (RemoteException e) { + // Do nothing + } + } +}