Implemented requestNetwork with a PendingIntent.
ConnectivityManager.requestNetwork(NetworkRequest, PendingIntent) was unhidden and implemented. Added ConnectivityManager.removePendingIntentRequest(PendingIntent) as the companion method. Bug: 17356414 Change-Id: I656a1e149cc1292c443ebfe9e61ee3eb5a80f143
This commit is contained in:
@@ -2378,17 +2378,15 @@ public class ConnectivityManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The lookup key for a {@link Network} object included with the intent after
|
* The lookup key for a {@link Network} object included with the intent after
|
||||||
* succesfully finding a network for the applications request. Retrieve it with
|
* successfully finding a network for the applications request. Retrieve it with
|
||||||
* {@link android.content.Intent#getParcelableExtra(String)}.
|
* {@link android.content.Intent#getParcelableExtra(String)}.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
|
public static final String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The lookup key for a {@link NetworkRequest} object included with the intent after
|
* The lookup key for a {@link NetworkRequest} object included with the intent after
|
||||||
* succesfully finding a network for the applications request. Retrieve it with
|
* successfully finding a network for the applications request. Retrieve it with
|
||||||
* {@link android.content.Intent#getParcelableExtra(String)}.
|
* {@link android.content.Intent#getParcelableExtra(String)}.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST =
|
public static final String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST =
|
||||||
"networkRequestNetworkRequest";
|
"networkRequestNetworkRequest";
|
||||||
@@ -2397,7 +2395,7 @@ public class ConnectivityManager {
|
|||||||
/**
|
/**
|
||||||
* Request a network to satisfy a set of {@link NetworkCapabilities}.
|
* Request a network to satisfy a set of {@link NetworkCapabilities}.
|
||||||
*
|
*
|
||||||
* This function behavies identically to the version that takes a NetworkCallback, but instead
|
* This function behaves identically to the version that takes a NetworkCallback, but instead
|
||||||
* of {@link NetworkCallback} a {@link PendingIntent} is used. This means
|
* of {@link NetworkCallback} a {@link PendingIntent} is used. This means
|
||||||
* the request may outlive the calling application and get called back when a suitable
|
* the request may outlive the calling application and get called back when a suitable
|
||||||
* network is found.
|
* network is found.
|
||||||
@@ -2418,20 +2416,45 @@ public class ConnectivityManager {
|
|||||||
* two Intents defined by {@link Intent#filterEquals}), then it will be removed and
|
* two Intents defined by {@link Intent#filterEquals}), then it will be removed and
|
||||||
* replaced by this one, effectively releasing the previous {@link NetworkRequest}.
|
* replaced by this one, effectively releasing the previous {@link NetworkRequest}.
|
||||||
* <p>
|
* <p>
|
||||||
* The request may be released normally by calling {@link #unregisterNetworkCallback}.
|
* The request may be released normally by calling
|
||||||
|
* {@link #releaseNetworkRequest(android.app.PendingIntent)}.
|
||||||
*
|
*
|
||||||
* @param request {@link NetworkRequest} describing this request.
|
* @param request {@link NetworkRequest} describing this request.
|
||||||
* @param operation Action to perform when the network is available (corresponds
|
* @param operation Action to perform when the network is available (corresponds
|
||||||
* to the {@link NetworkCallback#onAvailable} call. Typically
|
* to the {@link NetworkCallback#onAvailable} call. Typically
|
||||||
* comes from {@link PendingIntent#getBroadcast}.
|
* comes from {@link PendingIntent#getBroadcast}. Cannot be null.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public void requestNetwork(NetworkRequest request, PendingIntent operation) {
|
public void requestNetwork(NetworkRequest request, PendingIntent operation) {
|
||||||
|
checkPendingIntent(operation);
|
||||||
try {
|
try {
|
||||||
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
|
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
|
||||||
} catch (RemoteException e) {}
|
} catch (RemoteException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a request made via {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)}
|
||||||
|
* <p>
|
||||||
|
* This method has the same behavior as {@link #unregisterNetworkCallback} with respect to
|
||||||
|
* releasing network resources and disconnecting.
|
||||||
|
*
|
||||||
|
* @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the
|
||||||
|
* PendingIntent passed to
|
||||||
|
* {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)} with the
|
||||||
|
* corresponding NetworkRequest you'd like to remove. Cannot be null.
|
||||||
|
*/
|
||||||
|
public void releaseNetworkRequest(PendingIntent operation) {
|
||||||
|
checkPendingIntent(operation);
|
||||||
|
try {
|
||||||
|
mService.releasePendingNetworkRequest(operation);
|
||||||
|
} catch (RemoteException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPendingIntent(PendingIntent intent) {
|
||||||
|
if (intent == null) {
|
||||||
|
throw new IllegalArgumentException("PendingIntent cannot be null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers to receive notifications about all networks which satisfy the given
|
* Registers to receive notifications about all networks which satisfy the given
|
||||||
* {@link NetworkRequest}. The callbacks will continue to be called until
|
* {@link NetworkRequest}. The callbacks will continue to be called until
|
||||||
@@ -2448,7 +2471,7 @@ public class ConnectivityManager {
|
|||||||
/**
|
/**
|
||||||
* Unregisters callbacks about and possibly releases networks originating from
|
* Unregisters callbacks about and possibly releases networks originating from
|
||||||
* {@link #requestNetwork} and {@link #registerNetworkCallback} calls. If the
|
* {@link #requestNetwork} and {@link #registerNetworkCallback} calls. If the
|
||||||
* given {@code NetworkCallback} had previosuly been used with {@code #requestNetwork},
|
* given {@code NetworkCallback} had previously been used with {@code #requestNetwork},
|
||||||
* any networks that had been connected to only to satisfy that request will be
|
* any networks that had been connected to only to satisfy that request will be
|
||||||
* disconnected.
|
* disconnected.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -156,6 +156,8 @@ interface IConnectivityManager
|
|||||||
NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
|
NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
|
||||||
in PendingIntent operation);
|
in PendingIntent operation);
|
||||||
|
|
||||||
|
void releasePendingNetworkRequest(in PendingIntent operation);
|
||||||
|
|
||||||
NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities,
|
NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities,
|
||||||
in Messenger messenger, in IBinder binder);
|
in Messenger messenger, in IBinder binder);
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,8 @@ import javax.net.ssl.SSLSession;
|
|||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class ConnectivityService extends IConnectivityManager.Stub {
|
public class ConnectivityService extends IConnectivityManager.Stub
|
||||||
|
implements PendingIntent.OnFinished {
|
||||||
private static final String TAG = "ConnectivityService";
|
private static final String TAG = "ConnectivityService";
|
||||||
|
|
||||||
private static final boolean DBG = true;
|
private static final boolean DBG = true;
|
||||||
@@ -382,6 +383,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
*/
|
*/
|
||||||
private static final int EVENT_SYSTEM_READY = 25;
|
private static final int EVENT_SYSTEM_READY = 25;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to add a network request with a pending intent
|
||||||
|
* includes a NetworkRequestInfo
|
||||||
|
*/
|
||||||
|
private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to remove a pending intent and its associated network request.
|
||||||
|
* arg1 = UID of caller
|
||||||
|
* obj = PendingIntent
|
||||||
|
*/
|
||||||
|
private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
|
||||||
|
|
||||||
|
|
||||||
/** Handler used for internal events. */
|
/** Handler used for internal events. */
|
||||||
final private InternalHandler mHandler;
|
final private InternalHandler mHandler;
|
||||||
@@ -395,6 +409,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
private String mNetTransitionWakeLockCausedBy = "";
|
private String mNetTransitionWakeLockCausedBy = "";
|
||||||
private int mNetTransitionWakeLockSerialNumber;
|
private int mNetTransitionWakeLockSerialNumber;
|
||||||
private int mNetTransitionWakeLockTimeout;
|
private int mNetTransitionWakeLockTimeout;
|
||||||
|
private final PowerManager.WakeLock mPendingIntentWakeLock;
|
||||||
|
|
||||||
private InetAddress mDefaultDns;
|
private InetAddress mDefaultDns;
|
||||||
|
|
||||||
@@ -649,6 +664,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||||
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
|
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
|
||||||
com.android.internal.R.integer.config_networkTransitionTimeout);
|
com.android.internal.R.integer.config_networkTransitionTimeout);
|
||||||
|
mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||||
|
|
||||||
mNetTrackers = new NetworkStateTracker[
|
mNetTrackers = new NetworkStateTracker[
|
||||||
ConnectivityManager.MAX_NETWORK_TYPE+1];
|
ConnectivityManager.MAX_NETWORK_TYPE+1];
|
||||||
@@ -2131,11 +2147,40 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this method proves to be too slow then we can maintain a separate
|
||||||
|
// pendingIntent => NetworkRequestInfo map.
|
||||||
|
// This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
|
||||||
|
private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
|
||||||
|
Intent intent = pendingIntent.getIntent();
|
||||||
|
for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
|
||||||
|
PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
|
||||||
|
if (existingPendingIntent != null &&
|
||||||
|
existingPendingIntent.getIntent().filterEquals(intent)) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRegisterNetworkRequestWithIntent(Message msg) {
|
||||||
|
final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
|
||||||
|
|
||||||
|
NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
|
||||||
|
if (existingRequest != null) { // remove the existing request.
|
||||||
|
if (DBG) log("Replacing " + existingRequest.request + " with "
|
||||||
|
+ nri.request + " because their intents matched.");
|
||||||
|
handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
|
||||||
|
}
|
||||||
|
handleRegisterNetworkRequest(msg);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleRegisterNetworkRequest(Message msg) {
|
private void handleRegisterNetworkRequest(Message msg) {
|
||||||
final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
|
final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
|
||||||
final NetworkCapabilities newCap = nri.request.networkCapabilities;
|
final NetworkCapabilities newCap = nri.request.networkCapabilities;
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
|
mNetworkRequests.put(nri.request, nri);
|
||||||
|
|
||||||
// Check for the best currently alive network that satisfies this request
|
// Check for the best currently alive network that satisfies this request
|
||||||
NetworkAgentInfo bestNetwork = null;
|
NetworkAgentInfo bestNetwork = null;
|
||||||
for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
|
for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
|
||||||
@@ -2173,7 +2218,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
|
mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mNetworkRequests.put(nri.request, nri);
|
|
||||||
if (nri.isRequest) {
|
if (nri.isRequest) {
|
||||||
if (DBG) log("sending new NetworkRequest to factories");
|
if (DBG) log("sending new NetworkRequest to factories");
|
||||||
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
|
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
|
||||||
@@ -2183,6 +2228,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
|
||||||
|
int callingUid) {
|
||||||
|
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
|
||||||
|
if (nri != null) {
|
||||||
|
handleReleaseNetworkRequest(nri.request, callingUid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
|
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
|
||||||
NetworkRequestInfo nri = mNetworkRequests.get(request);
|
NetworkRequestInfo nri = mNetworkRequests.get(request);
|
||||||
if (nri != null) {
|
if (nri != null) {
|
||||||
@@ -2218,11 +2271,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintain the illusion. When this request arrived, we might have preteneded
|
// Maintain the illusion. When this request arrived, we might have pretended
|
||||||
// that a network connected to serve it, even though the network was already
|
// that a network connected to serve it, even though the network was already
|
||||||
// connected. Now that this request has gone away, we might have to pretend
|
// connected. Now that this request has gone away, we might have to pretend
|
||||||
// that the network disconnected. LegacyTypeTracker will generate that
|
// that the network disconnected. LegacyTypeTracker will generate that
|
||||||
// phatom disconnect for this type.
|
// phantom disconnect for this type.
|
||||||
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
|
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
|
||||||
if (nai != null) {
|
if (nai != null) {
|
||||||
mNetworkForRequestId.remove(nri.request.requestId);
|
mNetworkForRequestId.remove(nri.request.requestId);
|
||||||
@@ -2253,7 +2306,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
NetworkInfo info;
|
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
|
case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
|
||||||
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
|
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
|
||||||
@@ -2334,6 +2386,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
handleRegisterNetworkRequest(msg);
|
handleRegisterNetworkRequest(msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
|
||||||
|
handleRegisterNetworkRequestWithIntent(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
|
||||||
|
handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case EVENT_RELEASE_NETWORK_REQUEST: {
|
case EVENT_RELEASE_NETWORK_REQUEST: {
|
||||||
handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
|
handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
|
||||||
break;
|
break;
|
||||||
@@ -3347,12 +3407,23 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
static final boolean LISTEN = false;
|
static final boolean LISTEN = false;
|
||||||
|
|
||||||
final NetworkRequest request;
|
final NetworkRequest request;
|
||||||
IBinder mBinder;
|
final PendingIntent mPendingIntent;
|
||||||
|
private final IBinder mBinder;
|
||||||
final int mPid;
|
final int mPid;
|
||||||
final int mUid;
|
final int mUid;
|
||||||
final Messenger messenger;
|
final Messenger messenger;
|
||||||
final boolean isRequest;
|
final boolean isRequest;
|
||||||
|
|
||||||
|
NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) {
|
||||||
|
request = r;
|
||||||
|
mPendingIntent = pi;
|
||||||
|
messenger = null;
|
||||||
|
mBinder = null;
|
||||||
|
mPid = getCallingPid();
|
||||||
|
mUid = getCallingUid();
|
||||||
|
this.isRequest = isRequest;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
|
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
|
||||||
super();
|
super();
|
||||||
messenger = m;
|
messenger = m;
|
||||||
@@ -3361,6 +3432,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
mPid = getCallingPid();
|
mPid = getCallingPid();
|
||||||
mUid = getCallingUid();
|
mUid = getCallingUid();
|
||||||
this.isRequest = isRequest;
|
this.isRequest = isRequest;
|
||||||
|
mPendingIntent = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mBinder.linkToDeath(this, 0);
|
mBinder.linkToDeath(this, 0);
|
||||||
@@ -3370,7 +3442,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void unlinkDeathRecipient() {
|
void unlinkDeathRecipient() {
|
||||||
mBinder.unlinkToDeath(this, 0);
|
if (mBinder != null) {
|
||||||
|
mBinder.unlinkToDeath(this, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
@@ -3381,40 +3455,22 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
|
return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
|
||||||
mPid + " for " + request;
|
mPid + " for " + request +
|
||||||
|
(mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
|
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
|
||||||
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
|
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
|
||||||
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
|
||||||
== false) {
|
|
||||||
enforceConnectivityInternalPermission();
|
|
||||||
} else {
|
|
||||||
enforceChangePermission();
|
|
||||||
}
|
|
||||||
|
|
||||||
networkCapabilities = new NetworkCapabilities(networkCapabilities);
|
networkCapabilities = new NetworkCapabilities(networkCapabilities);
|
||||||
|
enforceNetworkRequestPermissions(networkCapabilities);
|
||||||
// if UID is restricted, don't allow them to bring up metered APNs
|
enforceMeteredApnPolicy(networkCapabilities);
|
||||||
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
|
|
||||||
== false) {
|
|
||||||
final int uidRules;
|
|
||||||
final int uid = Binder.getCallingUid();
|
|
||||||
synchronized(mRulesLock) {
|
|
||||||
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
|
|
||||||
}
|
|
||||||
if ((uidRules & RULE_REJECT_METERED) != 0) {
|
|
||||||
// we could silently fail or we can filter the available nets to only give
|
|
||||||
// them those they have access to. Chose the more useful
|
|
||||||
networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
|
if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
|
||||||
throw new IllegalArgumentException("Bad timeout specified");
|
throw new IllegalArgumentException("Bad timeout specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
|
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
|
||||||
nextNetworkRequestId());
|
nextNetworkRequestId());
|
||||||
if (DBG) log("requestNetwork for " + networkRequest);
|
if (DBG) log("requestNetwork for " + networkRequest);
|
||||||
@@ -3429,11 +3485,54 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
return networkRequest;
|
return networkRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
|
||||||
|
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
||||||
|
== false) {
|
||||||
|
enforceConnectivityInternalPermission();
|
||||||
|
} else {
|
||||||
|
enforceChangePermission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
|
||||||
|
// if UID is restricted, don't allow them to bring up metered APNs
|
||||||
|
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
|
||||||
|
== false) {
|
||||||
|
final int uidRules;
|
||||||
|
final int uid = Binder.getCallingUid();
|
||||||
|
synchronized(mRulesLock) {
|
||||||
|
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
|
||||||
|
}
|
||||||
|
if ((uidRules & RULE_REJECT_METERED) != 0) {
|
||||||
|
// we could silently fail or we can filter the available nets to only give
|
||||||
|
// them those they have access to. Chose the more useful
|
||||||
|
networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
|
public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
|
||||||
PendingIntent operation) {
|
PendingIntent operation) {
|
||||||
// TODO
|
checkNotNull(operation, "PendingIntent cannot be null.");
|
||||||
return null;
|
networkCapabilities = new NetworkCapabilities(networkCapabilities);
|
||||||
|
enforceNetworkRequestPermissions(networkCapabilities);
|
||||||
|
enforceMeteredApnPolicy(networkCapabilities);
|
||||||
|
|
||||||
|
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
|
||||||
|
nextNetworkRequestId());
|
||||||
|
if (DBG) log("pendingRequest for " + networkRequest + " to trigger " + operation);
|
||||||
|
NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
|
||||||
|
NetworkRequestInfo.REQUEST);
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
|
||||||
|
nri));
|
||||||
|
return networkRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releasePendingNetworkRequest(PendingIntent operation) {
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
|
||||||
|
getCallingUid(), 0, operation));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -3727,6 +3826,39 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
|
||||||
|
int notificationType) {
|
||||||
|
if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK, nri.request);
|
||||||
|
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK_REQUEST,
|
||||||
|
networkAgent.network);
|
||||||
|
sendIntent(nri.mPendingIntent, intent);
|
||||||
|
}
|
||||||
|
// else not handled
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendIntent(PendingIntent pendingIntent, Intent intent) {
|
||||||
|
mPendingIntentWakeLock.acquire();
|
||||||
|
try {
|
||||||
|
if (DBG) log("Sending " + pendingIntent);
|
||||||
|
pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
|
||||||
|
} catch (PendingIntent.CanceledException e) {
|
||||||
|
if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
|
||||||
|
mPendingIntentWakeLock.release();
|
||||||
|
releasePendingNetworkRequest(pendingIntent);
|
||||||
|
}
|
||||||
|
// ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
|
||||||
|
String resultData, Bundle resultExtras) {
|
||||||
|
if (DBG) log("Finished sending " + pendingIntent);
|
||||||
|
mPendingIntentWakeLock.release();
|
||||||
|
releasePendingNetworkRequest(pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
private void callCallbackForRequest(NetworkRequestInfo nri,
|
private void callCallbackForRequest(NetworkRequestInfo nri,
|
||||||
NetworkAgentInfo networkAgent, int notificationType) {
|
NetworkAgentInfo networkAgent, int notificationType) {
|
||||||
if (nri.messenger == null) return; // Default request has no msgr
|
if (nri.messenger == null) return; // Default request has no msgr
|
||||||
@@ -4137,7 +4269,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
// } else if (nai.networkMonitor.isEvaluating()) {
|
// } else if (nai.networkMonitor.isEvaluating()) {
|
||||||
// notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType);
|
// notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType);
|
||||||
// }
|
// }
|
||||||
callCallbackForRequest(nri, nai, notifyType);
|
if (nri.mPendingIntent == null) {
|
||||||
|
callCallbackForRequest(nri, nai, notifyType);
|
||||||
|
} else {
|
||||||
|
sendPendingIntentForRequest(nri, nai, notifyType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
|
private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
|
||||||
@@ -4196,7 +4332,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
|
NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
|
||||||
NetworkRequestInfo nri = mNetworkRequests.get(nr);
|
NetworkRequestInfo nri = mNetworkRequests.get(nr);
|
||||||
if (VDBG) log(" sending notification for " + nr);
|
if (VDBG) log(" sending notification for " + nr);
|
||||||
callCallbackForRequest(nri, networkAgent, notifyType);
|
if (nri.mPendingIntent == null) {
|
||||||
|
callCallbackForRequest(nri, networkAgent, notifyType);
|
||||||
|
} else {
|
||||||
|
sendPendingIntentForRequest(nri, networkAgent, notifyType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user