Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b519638 authored by markchien's avatar markchien
Browse files

Only apply entitlement check to cellular upstream

Instead of doing a tethering entitlement check whenever we turn
on tethering, provisioning result should only affect mobile
upstream. List behavior changes below:

1. Change tether entitlement check from pre-flight check to
run-time check.
2. Only run entitlement check when upstream is mobile.
3. Move schedule entitlement re-check logic from Settings to
framework.
4. Run all entitlement thing in TetherMaster thread to avoid
multi-thread problem.

Test: -atest FrameworksNetTests
      -build, flash, booted
bug: 111490073
Change-Id: Ic2980b4d6864d6f7287816c43eb6cf7a5cdec541
Merged-in: Ic2980b4d6864d6f7287816c43eb6cf7a5cdec541
parent 963136ce
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -608,6 +608,9 @@

    <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL" />

    <!-- For tether entitlement recheck-->
    <protected-broadcast
        android:name="com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" />
    <!-- ====================================================================== -->
    <!--                          RUNTIME PERMISSIONS                           -->
    <!-- ====================================================================== -->
+23 −72
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -230,8 +229,11 @@ public class Tethering extends BaseNetworkObserver {

        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
        mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM,
                mLog, systemProperties);
        // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream
        // permission is changed according to entitlement check result.
        mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM, mLog,
                TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED, systemProperties);

        mCarrierConfigChange = new VersionedBroadcastListener(
                "CarrierConfigChangeListener", mContext, mHandler, filter,
                (Intent ignored) -> {
@@ -363,55 +365,28 @@ public class Tethering extends BaseNetworkObserver {
    }

    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
        mEntitlementMgr.startTethering(type);
        if (!mEntitlementMgr.isTetherProvisioningRequired()) {
            enableTetheringInternal(type, true, receiver);
            return;
        }

        final ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
        if (showProvisioningUi) {
            mEntitlementMgr.runUiTetherProvisioningAndEnable(type, proxyReceiver);
        } else {
            mEntitlementMgr.runSilentTetherProvisioningAndEnable(type, proxyReceiver);
        }
        mEntitlementMgr.startProvisioningIfNeeded(type, showProvisioningUi);
        enableTetheringInternal(type, true /* enabled */, receiver);
    }

    public void stopTethering(int type) {
        enableTetheringInternal(type, false, null);
        mEntitlementMgr.stopTethering(type);
        if (mEntitlementMgr.isTetherProvisioningRequired()) {
            // There are lurking bugs where the notion of "provisioning required" or
            // "tethering supported" may change without notifying tethering properly, then
            // tethering can't shutdown correctly.
            // TODO: cancel re-check all the time
            if (mDeps.isTetheringSupported()) {
                mEntitlementMgr.cancelTetherProvisioningRechecks(type);
            }
        }
        enableTetheringInternal(type, false /* disabled */, null);
        mEntitlementMgr.stopProvisioningIfNeeded(type);
    }

    /**
     * Enables or disables tethering for the given type. This should only be called once
     * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
     * for the specified interface.
     * Enables or disables tethering for the given type. If provisioning is required, it will
     * schedule provisioning rechecks for the specified interface.
     */
    private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
        boolean isProvisioningRequired = enable && mEntitlementMgr.isTetherProvisioningRequired();
        int result;
        switch (type) {
            case TETHERING_WIFI:
                result = setWifiTethering(enable);
                if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) {
                    mEntitlementMgr.scheduleProvisioningRechecks(type);
                }
                sendTetherResult(receiver, result);
                break;
            case TETHERING_USB:
                result = setUsbTethering(enable);
                if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) {
                    mEntitlementMgr.scheduleProvisioningRechecks(type);
                }
                sendTetherResult(receiver, result);
                break;
            case TETHERING_BLUETOOTH:
@@ -469,46 +444,11 @@ public class Tethering extends BaseNetworkObserver {
                        ? TETHER_ERROR_NO_ERROR
                        : TETHER_ERROR_MASTER_ERROR;
                sendTetherResult(receiver, result);
                if (enable && mEntitlementMgr.isTetherProvisioningRequired()) {
                    mEntitlementMgr.scheduleProvisioningRechecks(TETHERING_BLUETOOTH);
                }
                adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
            }
        }, BluetoothProfile.PAN);
    }

    /**
     * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result
     * is successful before firing back up to the wrapped receiver.
     *
     * @param type The type of tethering being enabled.
     * @param receiver A ResultReceiver which will be called back with an int resultCode.
     * @return The proxy receiver.
     */
    private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) {
        ResultReceiver rr = new ResultReceiver(null) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                // If provisioning is successful, enable tethering, otherwise just send the error.
                if (resultCode == TETHER_ERROR_NO_ERROR) {
                    enableTetheringInternal(type, true, receiver);
                } else {
                    sendTetherResult(receiver, resultCode);
                }
                mEntitlementMgr.updateEntitlementCacheValue(type, resultCode);
            }
        };

        // The following is necessary to avoid unmarshalling issues when sending the receiver
        // across processes.
        Parcel parcel = Parcel.obtain();
        rr.writeToParcel(parcel,0);
        parcel.setDataPosition(0);
        ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
        parcel.recycle();
        return receiverForSending;
    }

    public int tether(String iface) {
        return tether(iface, IpServer.STATE_TETHERED);
    }
@@ -787,6 +727,7 @@ public class Tethering extends BaseNetworkObserver {
                if (!usbConnected && mRndisEnabled) {
                    // Turn off tethering if it was enabled and there is a disconnect.
                    tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
                    mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_USB);
                } else if (usbConfigured && rndisEnabled) {
                    // Tether if rndis is enabled and usb is configured.
                    tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB);
@@ -813,6 +754,7 @@ public class Tethering extends BaseNetworkObserver {
                    case WifiManager.WIFI_AP_STATE_FAILED:
                    default:
                        disableWifiIpServingLocked(ifname, curState);
                        mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
                        break;
                }
            }
@@ -1090,6 +1032,8 @@ public class Tethering extends BaseNetworkObserver {
        // we treated the error and want now to clear it
        static final int CMD_CLEAR_ERROR                        = BASE_MASTER + 6;
        static final int EVENT_IFACE_UPDATE_LINKPROPERTIES      = BASE_MASTER + 7;
        // Events from EntitlementManager to choose upstream again.
        static final int EVENT_UPSTREAM_PERMISSION_CHANGED      = BASE_MASTER + 8;

        private final State mInitialState;
        private final State mTetherModeAliveState;
@@ -1504,6 +1448,7 @@ public class Tethering extends BaseNetworkObserver {
                        }
                        break;
                    }
                    case EVENT_UPSTREAM_PERMISSION_CHANGED:
                    case CMD_UPSTREAM_CHANGED:
                        updateUpstreamWanted();
                        if (!mUpstreamWanted) break;
@@ -1694,7 +1639,8 @@ public class Tethering extends BaseNetworkObserver {
    }

    public void systemReady() {
        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest());
        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(),
                mEntitlementMgr);
    }

    /** Get the latest value of the tethering entitlement check. */
@@ -1755,6 +1701,11 @@ public class Tethering extends BaseNetworkObserver {
        cfg.dump(pw);
        pw.decreaseIndent();

        pw.println("Entitlement:");
        pw.increaseIndent();
        mEntitlementMgr.dump(pw);
        pw.decreaseIndent();

        synchronized (mPublicSync) {
            pw.println("Tether state:");
            pw.increaseIndent();
+388 −78

File changed.

Preview size limit exceeded, changes collapsed.

+13 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static com.android.internal.R.array.config_tether_upstream_types;
import static com.android.internal.R.array.config_tether_usb_regexs;
import static com.android.internal.R.array.config_tether_wifi_regexs;
import static com.android.internal.R.bool.config_tether_upstream_automatic;
import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period;
import static com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui;

import android.content.ContentResolver;
@@ -94,6 +95,7 @@ public class TetheringConfiguration {

    public final String[] provisioningApp;
    public final String provisioningAppNoUi;
    public final int provisioningCheckPeriod;

    public final int subId;

@@ -121,6 +123,9 @@ public class TetheringConfiguration {

        provisioningApp = getResourceStringArray(res, config_mobile_hotspot_provision_app);
        provisioningAppNoUi = getProvisioningAppNoUi(res);
        provisioningCheckPeriod = getResourceInteger(res,
                config_mobile_hotspot_provision_check_period,
                0 /* No periodic re-check */);

        configLog.log(toString());
    }
@@ -311,6 +316,14 @@ public class TetheringConfiguration {
        }
    }

    private static int getResourceInteger(Resources res, int resId, int defaultValue) {
        try {
            return res.getInteger(resId);
        } catch (Resources.NotFoundException e404) {
            return defaultValue;
        }
    }

    private static boolean getEnableLegacyDhcpServer(Context ctx) {
        final ContentResolver cr = ctx.getContentResolver();
        final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
+2 −2
Original line number Diff line number Diff line
@@ -83,8 +83,8 @@ public class TetheringDependencies {
     * Get a reference to the EntitlementManager to be used by tethering.
     */
    public EntitlementManager getEntitlementManager(Context ctx, StateMachine target,
            SharedLog log, MockableSystemProperties systemProperties) {
        return new EntitlementManager(ctx, target, log, systemProperties);
            SharedLog log, int what, MockableSystemProperties systemProperties) {
        return new EntitlementManager(ctx, target, log, what, systemProperties);
    }

    /**
Loading