Expose quota status for active network.

Create API to expose quota status derived from underlying network
policy.  This is designed to support applications making informed
decisions when performing network requests.

Fix bug with random stats generation, and write policy when changing
restrict background data flag.  Deprecate EXTRA_NETWORK_INFO, since
it varies based on UID.

Bug: 4517283, 5088603
Change-Id: Ic6893a8967f69937e466be226ba7bb86ef5a5d2d
This commit is contained in:
Jeff Sharkey
2011-08-02 17:22:34 -07:00
parent 34e1fb1ee2
commit f0ceede8ff
9 changed files with 238 additions and 9 deletions

View File

@ -16,6 +16,7 @@
package com.android.server.net;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
@ -75,9 +76,11 @@ import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.NetworkIdentity;
import android.net.NetworkPolicy;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@ -1054,6 +1057,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
synchronized (mRulesLock) {
mRestrictBackground = restrictBackground;
updateRulesForRestrictBackgroundLocked();
writePolicyLocked();
}
}
@ -1066,6 +1070,68 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
for (NetworkPolicy policy : mNetworkPolicy.values()) {
if (policy.template.matches(ident)) {
return policy;
}
}
return null;
}
@Override
public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
// only returns usage summary, so we don't require caller to have
// READ_NETWORK_USAGE_HISTORY.
final long token = Binder.clearCallingIdentity();
try {
return getNetworkQuotaInfoUnchecked(state);
} finally {
Binder.restoreCallingIdentity(token);
}
}
private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
final NetworkPolicy policy;
synchronized (mRulesLock) {
policy = findPolicyForNetworkLocked(ident);
}
if (policy == null) {
// missing policy means we can't derive useful quota info
return null;
}
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
// find total bytes used under policy
long totalBytes = 0;
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
policy.template, start, end);
final NetworkStats.Entry entry = stats.getValues(0, null);
totalBytes = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
}
// report soft and hard limits under policy
final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
: NetworkQuotaInfo.NO_LIMIT;
final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
: NetworkQuotaInfo.NO_LIMIT;
return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
}
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
mContext.enforceCallingOrSelfPermission(DUMP, TAG);