Protect invalid entitlement app configuration

There is a protection in Settings that Settings would gray out if
tethering requires entitlement check but the entitlement app is
invalid. Tethering resource is moved from framework to tethering
module, so Settings can not fetch entitlement app name anymore.

In this change, tethering module would check whether entitltement app
package name is exsited if entitlement check is needed. Tethering would
be not supported (Settings tethering option would be hidded) if
entitlement app is not installed.

After moving the protection into tethering module,
TetherUtil#isProvisioningNeeded is no longer needed. Because The
only use case is Settings wants to gray out tethering setting
when entitltement check is needed but entitlement app is invalid.

Bug: 146918263
Test: atest TetheringCoverageTests
Change-Id: I9a5ff5dbc1db3f3be7fcd7146862a16b373507e6
This commit is contained in:
markchien
2020-06-03 12:27:37 +08:00
parent f1b2407490
commit 017bfba0d8
3 changed files with 63 additions and 4 deletions

View File

@@ -18,6 +18,7 @@ package com.android.networkstack.tethering;
import static android.Manifest.permission.NETWORK_SETTINGS; import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.NETWORK_STACK;
import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.usb.UsbManager.USB_CONFIGURED; import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED; import static android.hardware.usb.UsbManager.USB_CONNECTED;
@@ -70,6 +71,7 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.EthernetManager; import android.net.EthernetManager;
@@ -109,7 +111,6 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.ServiceSpecificException; import android.os.ServiceSpecificException;
import android.os.SystemProperties;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
@@ -782,11 +783,30 @@ public class Tethering {
} }
} }
private boolean isProvisioningNeededButUnavailable() {
return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
}
boolean isTetherProvisioningRequired() { boolean isTetherProvisioningRequired() {
final TetheringConfiguration cfg = mConfig; final TetheringConfiguration cfg = mConfig;
return mEntitlementMgr.isTetherProvisioningRequired(cfg); return mEntitlementMgr.isTetherProvisioningRequired(cfg);
} }
private boolean doesEntitlementPackageExist() {
// provisioningApp must contain package and class name.
if (mConfig.provisioningApp.length != 2) {
return false;
}
final PackageManager pm = mContext.getPackageManager();
try {
pm.getPackageInfo(mConfig.provisioningApp[0], GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return true;
}
// TODO: Figure out how to update for local hotspot mode interfaces. // TODO: Figure out how to update for local hotspot mode interfaces.
private void sendTetherStateChangedBroadcast() { private void sendTetherStateChangedBroadcast() {
if (!isTetheringSupported()) return; if (!isTetheringSupported()) return;
@@ -2145,14 +2165,14 @@ public class Tethering {
// gservices could set the secure setting to 1 though to enable it on a build where it // gservices could set the secure setting to 1 though to enable it on a build where it
// had previously been turned off. // had previously been turned off.
boolean isTetheringSupported() { boolean isTetheringSupported() {
final int defaultVal = final int defaultVal = mDeps.isTetheringDenied() ? 0 : 1;
SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(), final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0; Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
final boolean tetherEnabledInSettings = tetherSupported final boolean tetherEnabledInSettings = tetherSupported
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
return tetherEnabledInSettings && hasTetherableConfiguration(); return tetherEnabledInSettings && hasTetherableConfiguration()
&& !isProvisioningNeededButUnavailable();
} }
void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {

View File

@@ -26,6 +26,8 @@ import android.net.util.SharedLog;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.SystemProperties;
import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -150,4 +152,11 @@ public abstract class TetheringDependencies {
* Get a reference to BluetoothAdapter to be used by tethering. * Get a reference to BluetoothAdapter to be used by tethering.
*/ */
public abstract BluetoothAdapter getBluetoothAdapter(); public abstract BluetoothAdapter getBluetoothAdapter();
/**
* Get SystemProperties which indicate whether tethering is denied.
*/
public boolean isTetheringDenied() {
return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true");
}
} }

View File

@@ -16,6 +16,7 @@
package com.android.networkstack.tethering; package com.android.networkstack.tethering;
import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.hardware.usb.UsbManager.USB_CONFIGURED; import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED; import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM; import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
@@ -81,6 +82,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
@@ -204,6 +206,7 @@ public class TetheringTest {
@Mock private EthernetManager mEm; @Mock private EthernetManager mEm;
@Mock private TetheringNotificationUpdater mNotificationUpdater; @Mock private TetheringNotificationUpdater mNotificationUpdater;
@Mock private BpfCoordinator mBpfCoordinator; @Mock private BpfCoordinator mBpfCoordinator;
@Mock private PackageManager mPackageManager;
private final MockIpServerDependencies mIpServerDependencies = private final MockIpServerDependencies mIpServerDependencies =
spy(new MockIpServerDependencies()); spy(new MockIpServerDependencies());
@@ -263,6 +266,11 @@ public class TetheringTest {
return super.getSystemService(name); return super.getSystemService(name);
} }
@Override
public PackageManager getPackageManager() {
return mPackageManager;
}
@Override @Override
public String getSystemServiceName(Class<?> serviceClass) { public String getSystemServiceName(Class<?> serviceClass) {
if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE; if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
@@ -425,6 +433,11 @@ public class TetheringTest {
public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) { public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) {
return mNotificationUpdater; return mNotificationUpdater;
} }
@Override
public boolean isTetheringDenied() {
return false;
}
} }
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4, private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
@@ -1951,6 +1964,23 @@ public class TetheringTest {
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME)); assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
} }
@Test
public void testProvisioningNeededButUnavailable() throws Exception {
assertTrue(mTethering.isTetheringSupported());
verify(mPackageManager, never()).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
setupForRequiredProvisioning();
assertTrue(mTethering.isTetheringSupported());
verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
reset(mPackageManager);
doThrow(PackageManager.NameNotFoundException.class).when(mPackageManager).getPackageInfo(
PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
setupForRequiredProvisioning();
assertFalse(mTethering.isTetheringSupported());
verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
}
// TODO: Test that a request for hotspot mode doesn't interfere with an // TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface. // already operating tethering mode interface.
} }