diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index f47ada6ae5..f807924e75 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2581,6 +2581,7 @@ public class ConnectivityManager { } /** {@hide} */ + @SystemApi public static final int TETHER_ERROR_NO_ERROR = 0; /** {@hide} */ public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; @@ -2603,9 +2604,13 @@ public class ConnectivityManager { /** {@hide} */ public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; /** {@hide} */ + @SystemApi public static final int TETHER_ERROR_PROVISION_FAILED = 11; /** {@hide} */ public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; + /** {@hide} */ + @SystemApi + public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; /** * Get a more detailed error code after a Tethering or Untethering @@ -2627,6 +2632,65 @@ public class ConnectivityManager { } } + /** + * Callback for use with {@link #getLatestTetheringEntitlementValue} to find out whether + * entitlement succeeded. + * @hide + */ + @SystemApi + public abstract static class TetheringEntitlementValueListener { + /** + * Called to notify entitlement result. + * + * @param resultCode a int value of entitlement result. It may be one of + * {@link #TETHER_ERROR_NO_ERROR}, + * {@link #TETHER_ERROR_PROVISION_FAILED}, or + * {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}. + */ + public void onEntitlementResult(int resultCode) {} + } + + /** + * Get the last value of the entitlement check on this downstream. If the cached value is + * {@link #TETHER_ERROR_NO_ERROR} or showEntitlementUi argument is false, it just return the + * cached value. Otherwise, a UI-based entitlement check would be performed. It is not + * guaranteed that the UI-based entitlement check will complete in any specific time period + * and may in fact never complete. Any successful entitlement check the platform performs for + * any reason will update the cached value. + * + * @param type the downstream type of tethering. Must be one of + * {@link #TETHERING_WIFI}, + * {@link #TETHERING_USB}, or + * {@link #TETHERING_BLUETOOTH}. + * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check. + * @param listener an {@link TetheringEntitlementValueListener} which will be called to notify + * the caller of the result of entitlement check. The listener may be called zero or + * one time. + * @param handler {@link Handler} to specify the thread upon which the listener will be invoked. + * {@hide} + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void getLatestTetheringEntitlementValue(int type, boolean showEntitlementUi, + @NonNull final TetheringEntitlementValueListener listener, @Nullable Handler handler) { + Preconditions.checkNotNull(listener, "TetheringEntitlementValueListener cannot be null."); + ResultReceiver wrappedListener = new ResultReceiver(handler) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + listener.onEntitlementResult(resultCode); + } + }; + + try { + String pkgName = mContext.getOpPackageName(); + Log.i(TAG, "getLatestTetheringEntitlementValue:" + pkgName); + mService.getLatestTetheringEntitlementValue(type, wrappedListener, + showEntitlementUi, pkgName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Report network connectivity status. This is currently used only * to alter status bar UI. diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index fd7360fd4c..78fafebc4f 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -197,4 +197,7 @@ interface IConnectivityManager int getConnectionOwnerUid(in ConnectionInfo connectionInfo); boolean isCallerCurrentAlwaysOnVpnApp(); boolean isCallerCurrentAlwaysOnVpnLockdownApp(); + + void getLatestTetheringEntitlementValue(int type, in ResultReceiver receiver, + boolean showEntitlementUi, String callerPkg); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 9892bfa501..08e49034aa 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3643,6 +3643,20 @@ public class ConnectivityService extends IConnectivityManager.Stub mTethering.stopTethering(type); } + /** + * Get the latest value of the tethering entitlement check. + * + * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns + * out some such apps are observed to abuse this API, change to per-UID limits on this API + * if it's really needed. + */ + @Override + public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver, + boolean showEntitlementUi, String callerPkg) { + ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); + mTethering.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi); + } + // Called when we lose the default network and have no replacement yet. // This will automatically be cleared after X seconds or a new default network // becomes CONNECTED, whichever happens first. The timer is started by the