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

Commit 36c7aa03 authored by Jeremy Klein's avatar Jeremy Klein
Browse files

Expose a simple tethering API which includes provision checks.

This CL exposes startTethering and stopTethering functions which also
encapsulate all provisioning check logic. Right now, only silent checks
are implemented, but UI checks will come in a follow-up CL. GTS tests
and Settings changes are under the same topic ID.

BUG: 26247383
Change-Id: I65f61d899594cb3f9035d8496366af17a57a090f
parent 28950ae5
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -24401,6 +24401,7 @@ package android.net {
    method public boolean isActiveNetworkMetered();
    method public boolean isDefaultNetworkActive();
    method public static deprecated boolean isNetworkTypeValid(int);
    method public boolean isTetheringSupported();
    method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
    method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
    method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -24413,7 +24414,10 @@ package android.net {
    method public deprecated boolean requestRouteToHost(int, int);
    method public deprecated void setNetworkPreference(int);
    method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
    method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
    method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
    method public void stopTethering(int);
    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
    method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
    method public void unregisterNetworkCallback(android.app.PendingIntent);
@@ -24435,6 +24439,9 @@ package android.net {
    field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
    field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
    field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
    field public static final int TETHERING_BLUETOOTH = 2; // 0x2
    field public static final int TETHERING_USB = 1; // 0x1
    field public static final int TETHERING_WIFI = 0; // 0x0
    field public static final int TYPE_BLUETOOTH = 7; // 0x7
    field public static final int TYPE_DUMMY = 8; // 0x8
    field public static final int TYPE_ETHERNET = 9; // 0x9
@@ -24461,6 +24468,12 @@ package android.net {
    method public abstract void onNetworkActive();
  }
  public static abstract class ConnectivityManager.OnStartTetheringCallback {
    ctor public ConnectivityManager.OnStartTetheringCallback();
    method public void onTetheringFailed();
    method public void onTetheringStarted();
  }
  public class Credentials {
    ctor public Credentials(int, int, int);
    method public int getGid();
+169 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.net;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
@@ -27,6 +28,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -37,6 +39,7 @@ import android.os.Message;
import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
@@ -337,6 +340,71 @@ public class ConnectivityManager {
     */
    public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED";

    /**
     * Invalid tethering type.
     * @see #startTethering(int, OnStartTetheringCallback, boolean)
     * @hide
     */
    public static final int TETHERING_INVALID   = -1;

    /**
     * Wifi tethering type.
     * @see #startTethering(int, OnStartTetheringCallback, boolean)
     * @hide
     */
    @SystemApi
    public static final int TETHERING_WIFI      = 0;

    /**
     * USB tethering type.
     * @see #startTethering(int, OnStartTetheringCallback, boolean)
     * @hide
     */
    @SystemApi
    public static final int TETHERING_USB       = 1;

    /**
     * Bluetooth tethering type.
     * @see #startTethering(int, OnStartTetheringCallback, boolean)
     * @hide
     */
    @SystemApi
    public static final int TETHERING_BLUETOOTH = 2;

    /**
     * Extra used for communicating with the TetherService. Includes the type of tethering to
     * enable if any.
     * @hide
     */
    public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";

    /**
     * Extra used for communicating with the TetherService. Includes the type of tethering for
     * which to cancel provisioning.
     * @hide
     */
    public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";

    /**
     * Extra used for communicating with the TetherService. True to schedule a recheck of tether
     * provisioning.
     * @hide
     */
    public static final String EXTRA_SET_ALARM = "extraSetAlarm";

    /**
     * Tells the TetherService to run a provision check now.
     * @hide
     */
    public static final String EXTRA_RUN_PROVISION = "extraRunProvision";

    /**
     * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
     * which will receive provisioning results. Can be left empty.
     * @hide
     */
    public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";

    /**
     * The absence of a connection type.
     * @hide
@@ -1789,6 +1857,11 @@ public class ConnectivityManager {
     * or the ability to modify system settings as determined by
     * {@link android.provider.Settings.System#canWrite}.</p>
     *
     * <p>WARNING: New clients should not use this function. The only usages should be in PanService
     * and WifiStateMachine which need direct access. All other clients should use
     * {@link #startTethering} and {@link #stopTethering} which encapsulate proper provisioning
     * logic.</p>
     *
     * @param iface the interface name to tether.
     * @return error a {@code TETHER_ERROR} value indicating success or failure type
     *
@@ -1810,6 +1883,11 @@ public class ConnectivityManager {
     * or the ability to modify system settings as determined by
     * {@link android.provider.Settings.System#canWrite}.</p>
     *
     * <p>WARNING: New clients should not use this function. The only usages should be in PanService
     * and WifiStateMachine which need direct access. All other clients should use
     * {@link #startTethering} and {@link #stopTethering} which encapsulate proper provisioning
     * logic.</p>
     *
     * @param iface the interface name to untether.
     * @return error a {@code TETHER_ERROR} value indicating success or failure type
     *
@@ -1834,6 +1912,7 @@ public class ConnectivityManager {
     *
     * {@hide}
     */
    @SystemApi
    public boolean isTetheringSupported() {
        try {
            return mService.isTetheringSupported();
@@ -1842,6 +1921,94 @@ public class ConnectivityManager {
        }
    }

    /**
     * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
     * @hide
     */
    @SystemApi
    public static abstract class OnStartTetheringCallback {
        /**
         * Called when tethering has been successfully started.
         */
        public void onTetheringStarted() {};

        /**
         * Called when starting tethering failed.
         */
        public void onTetheringFailed() {};
    }

    /**
     * Convenient overload for
     * {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null
     * handler to run on the current thread's {@link Looper}.
     * @hide
     */
    @SystemApi
    public void startTethering(int type, boolean showProvisioningUi,
            final OnStartTetheringCallback callback) {
        startTethering(type, showProvisioningUi, callback, null);
    }

    /**
     * Runs tether provisioning for the given type if needed and then starts tethering if
     * the check succeeds. If no carrier provisioning is required for tethering, tethering is
     * enabled immediately. If provisioning fails, tethering will not be enabled. It also
     * schedules tether provisioning re-checks if appropriate.
     *
     * @param type The type of tethering to start. Must be one of
     *         {@link ConnectivityManager.TETHERING_WIFI},
     *         {@link ConnectivityManager.TETHERING_USB}, or
     *         {@link ConnectivityManager.TETHERING_BLUETOOTH}.
     * @param showProvisioningUi a boolean indicating to show the provisioning app UI if there
     *         is one. This should be true the first time this function is called and also any time
     *         the user can see this UI. It gives users information from their carrier about the
     *         check failing and how they can sign up for tethering if possible.
     * @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller
     *         of the result of trying to tether.
     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
     * @hide
     */
    @SystemApi
    public void startTethering(int type, boolean showProvisioningUi,
            final OnStartTetheringCallback callback, Handler handler) {
        ResultReceiver wrappedCallback = new ResultReceiver(handler) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                if (resultCode == TETHER_ERROR_NO_ERROR) {
                    callback.onTetheringStarted();
                } else {
                    callback.onTetheringFailed();
                }
            }
        };
        try {
            mService.startTethering(type, wrappedCallback, showProvisioningUi);
        } catch (RemoteException e) {
            Log.e(TAG, "Exception trying to start tethering.", e);
            wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);
        }
    }

    /**
     * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
     * applicable.
     *
     * @param type The type of tethering to stop. Must be one of
     *         {@link ConnectivityManager.TETHERING_WIFI},
     *         {@link ConnectivityManager.TETHERING_USB}, or
     *         {@link ConnectivityManager.TETHERING_BLUETOOTH}.
     * @hide
     */
    @SystemApi
    public void stopTethering(int type) {
        try {
            mService.stopTethering(type);
        } catch (RemoteException e) {
            Log.e(TAG, "Exception trying to stop tethering.", e);
        }
    }

    /**
     * Get the list of regular expressions that define any tetherable
     * USB network interfaces.  If USB tethering is not supported by the
@@ -1949,6 +2116,8 @@ public class ConnectivityManager {
    public static final int TETHER_ERROR_DISABLE_NAT_ERROR    = 9;
    /** {@hide} */
    public static final int TETHER_ERROR_IFACE_CFG_ERROR      = 10;
    /** {@hide} */
    public static final int TETHER_ERROR_PROVISION_FAILED     = 11;

    /**
     * Get a more detailed error code after a Tethering or Untethering
+4 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@ interface IConnectivityManager

    boolean isTetheringSupported();

    void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi);

    void stopTethering(int type);

    String[] getTetherableIfaces();

    String[] getTetheredIfaces();
+0 −14
Original line number Diff line number Diff line
@@ -29,12 +29,6 @@ import android.telephony.CarrierConfigManager;

public class TetherUtil {

    // Types of tethering.
    public static final int TETHERING_INVALID   = -1;
    public static final int TETHERING_WIFI      = 0;
    public static final int TETHERING_USB       = 1;
    public static final int TETHERING_BLUETOOTH = 2;

    // Extras used for communicating with the TetherService.
    public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
    public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
@@ -43,14 +37,6 @@ public class TetherUtil {
     * Tells the service to run a provision check now.
     */
    public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
    /**
     * Enables wifi tethering if the provision check is successful. Used by
     * QS to enable tethering.
     */
    public static final String EXTRA_ENABLE_WIFI_TETHER = "extraEnableWifiTether";

    public static ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
            .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));

    public static boolean setWifiTethering(boolean enable, Context context) {
        final WifiManager wifiManager =
+21 −11
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.UserHandle;
import android.util.Log;

import com.android.settingslib.TetherUtil;
@@ -34,21 +34,18 @@ public class HotspotControllerImpl implements HotspotController {

    private static final String TAG = "HotspotController";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final Intent TETHER_SERVICE_INTENT = new Intent()
            .putExtra(TetherUtil.EXTRA_ADD_TETHER_TYPE, TetherUtil.TETHERING_WIFI)
            .putExtra(TetherUtil.EXTRA_SET_ALARM, true)
            .putExtra(TetherUtil.EXTRA_RUN_PROVISION, true)
            .putExtra(TetherUtil.EXTRA_ENABLE_WIFI_TETHER, true)
            .setComponent(TetherUtil.TETHER_SERVICE);

    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
    private final Receiver mReceiver = new Receiver();
    private final ConnectivityManager mConnectivityManager;
    private final Context mContext;

    private int mHotspotState;

    public HotspotControllerImpl(Context context) {
        mContext = context;
        mConnectivityManager = (ConnectivityManager)context.getSystemService(
                Context.CONNECTIVITY_SERVICE);
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -72,6 +69,7 @@ public class HotspotControllerImpl implements HotspotController {
        return null;
    }

    @Override
    public void addCallback(Callback callback) {
        if (callback == null || mCallbacks.contains(callback)) return;
        if (DEBUG) Log.d(TAG, "addCallback " + callback);
@@ -79,6 +77,7 @@ public class HotspotControllerImpl implements HotspotController {
        mReceiver.setListening(!mCallbacks.isEmpty());
    }

    @Override
    public void removeCallback(Callback callback) {
        if (callback == null) return;
        if (DEBUG) Log.d(TAG, "removeCallback " + callback);
@@ -96,13 +95,24 @@ public class HotspotControllerImpl implements HotspotController {
        return TetherUtil.isTetheringSupported(mContext);
    }

    static final class OnStartTetheringCallback extends
            ConnectivityManager.OnStartTetheringCallback {
        @Override
        public void onTetheringStarted() {}
        @Override
        public void onTetheringFailed() {
          // TODO: Show error.
        }
    }

    @Override
    public void setHotspotEnabled(boolean enabled) {
        // Call provisioning app which is called when enabling Tethering from Settings
        if (enabled && TetherUtil.isProvisioningNeeded(mContext)) {
            mContext.startServiceAsUser(TETHER_SERVICE_INTENT, UserHandle.CURRENT);
        if (enabled) {
            OnStartTetheringCallback callback = new OnStartTetheringCallback();
            mConnectivityManager.startTethering(
                    ConnectivityManager.TETHERING_WIFI, false, callback);
        } else {
            TetherUtil.setWifiTethering(enabled, mContext);
            mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
        }
    }

Loading