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

Commit 0301cd95 authored by Jeremy Klein's avatar Jeremy Klein Committed by Android (Google) Code Review
Browse files

Merge "Expose a simple tethering API which includes provision checks."

parents 50cd6361 36c7aa03
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -24485,6 +24485,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);
@@ -24497,7 +24498,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);
@@ -24519,6 +24523,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
@@ -24545,6 +24552,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