diff options
| -rw-r--r-- | api/current.txt | 13 | ||||
| -rw-r--r-- | core/java/android/net/ConnectivityManager.java | 29 | ||||
| -rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 3 | ||||
| -rw-r--r-- | core/java/android/net/INetworkPolicyManager.aidl | 8 | ||||
| -rw-r--r-- | core/java/android/net/NetworkQuotaInfo.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/net/NetworkQuotaInfo.java | 79 | ||||
| -rw-r--r-- | core/java/android/net/NetworkStatsHistory.java | 5 | ||||
| -rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 25 | ||||
| -rw-r--r-- | services/java/com/android/server/net/NetworkPolicyManagerService.java | 66 |
9 files changed, 238 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt index 7cb3bfb75fbc..ba040564d4ee 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11118,6 +11118,7 @@ package android.net { public class ConnectivityManager { method public android.net.NetworkInfo getActiveNetworkInfo(); + method public android.net.NetworkQuotaInfo getActiveNetworkQuotaInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo(); method public boolean getBackgroundDataSetting(); method public android.net.NetworkInfo getNetworkInfo(int); @@ -11132,7 +11133,7 @@ package android.net { field public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1 field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo"; field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover"; - field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo"; + field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo"; field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity"; field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork"; field public static final java.lang.String EXTRA_REASON = "reason"; @@ -11277,6 +11278,16 @@ package android.net { enum_constant public static final android.net.NetworkInfo.State UNKNOWN; } + public class NetworkQuotaInfo implements android.os.Parcelable { + method public int describeContents(); + method public long getEstimatedBytes(); + method public long getHardLimitBytes(); + method public long getSoftLimitBytes(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final long NO_LIMIT = -1L; // 0xffffffffffffffffL + } + public class ParseException extends java.lang.RuntimeException { field public java.lang.String response; } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a564d9771f7b..eb9cd213dd8e 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -16,10 +16,11 @@ package android.net; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.os.Binder; -import android.os.ParcelFileDescriptor; import android.os.RemoteException; import java.net.InetAddress; @@ -67,11 +68,19 @@ public class ConnectivityManager { * is set to {@code true} if there are no connected networks at all. */ public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + /** * The lookup key for a {@link NetworkInfo} object. Retrieve with * {@link android.content.Intent#getParcelableExtra(String)}. + * + * @deprecated Since {@link NetworkInfo} can vary based on UID, applications + * should always obtain network information through + * {@link #getActiveNetworkInfo()} or + * {@link #getAllNetworkInfo()}. */ + @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo"; + /** * The lookup key for a boolean that indicates whether a connect event * is for a network to which the connectivity manager was failing over @@ -515,6 +524,19 @@ public class ConnectivityManager { } /** + * Return quota status for the current active network, or {@code null} if no + * network is active. Quota status can change rapidly, so these values + * shouldn't be cached. + */ + public NetworkQuotaInfo getActiveNetworkQuotaInfo() { + try { + return mService.getActiveNetworkQuotaInfo(); + } catch (RemoteException e) { + return null; + } + } + + /** * Gets the value of the setting for enabling Mobile data. * * @return Whether mobile data is enabled. @@ -546,10 +568,7 @@ public class ConnectivityManager { * {@hide} */ public ConnectivityManager(IConnectivityManager service) { - if (service == null) { - throw new IllegalArgumentException("missing IConnectivityManager"); - } - mService = service; + mService = checkNotNull(service, "missing IConnectivityManager"); } /** diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index b1d99a4abe42..f3912005a667 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.LinkProperties; import android.net.NetworkInfo; +import android.net.NetworkQuotaInfo; import android.net.NetworkState; import android.net.ProxyProperties; import android.os.IBinder; @@ -47,6 +48,8 @@ interface IConnectivityManager NetworkState[] getAllNetworkState(); + NetworkQuotaInfo getActiveNetworkQuotaInfo(); + boolean setRadios(boolean onOff); boolean setRadio(int networkType, boolean turnOn); diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 3e07b0a0a8f9..633c38e0c66d 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -18,6 +18,8 @@ package android.net; import android.net.INetworkPolicyListener; import android.net.NetworkPolicy; +import android.net.NetworkQuotaInfo; +import android.net.NetworkState; import android.net.NetworkTemplate; /** @@ -27,6 +29,7 @@ import android.net.NetworkTemplate; */ interface INetworkPolicyManager { + /** Control UID policies. */ void setUidPolicy(int uid, int policy); int getUidPolicy(int uid); @@ -35,12 +38,17 @@ interface INetworkPolicyManager { void registerListener(INetworkPolicyListener listener); void unregisterListener(INetworkPolicyListener listener); + /** Control network policies atomically. */ void setNetworkPolicies(in NetworkPolicy[] policies); NetworkPolicy[] getNetworkPolicies(); + /** Snooze limit on policy matching given template. */ void snoozePolicy(in NetworkTemplate template); + /** Control if background data is restricted system-wide. */ void setRestrictBackground(boolean restrictBackground); boolean getRestrictBackground(); + NetworkQuotaInfo getNetworkQuotaInfo(in NetworkState state); + } diff --git a/core/java/android/net/NetworkQuotaInfo.aidl b/core/java/android/net/NetworkQuotaInfo.aidl new file mode 100644 index 000000000000..98a02c4bf998 --- /dev/null +++ b/core/java/android/net/NetworkQuotaInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable NetworkQuotaInfo; diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java new file mode 100644 index 000000000000..b85f92594440 --- /dev/null +++ b/core/java/android/net/NetworkQuotaInfo.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Information about quota status on a specific network. + */ +public class NetworkQuotaInfo implements Parcelable { + private final long mEstimatedBytes; + private final long mSoftLimitBytes; + private final long mHardLimitBytes; + + public static final long NO_LIMIT = -1; + + /** {@hide} */ + public NetworkQuotaInfo(long estimatedBytes, long softLimitBytes, long hardLimitBytes) { + mEstimatedBytes = estimatedBytes; + mSoftLimitBytes = softLimitBytes; + mHardLimitBytes = hardLimitBytes; + } + + /** {@hide} */ + public NetworkQuotaInfo(Parcel in) { + mEstimatedBytes = in.readLong(); + mSoftLimitBytes = in.readLong(); + mHardLimitBytes = in.readLong(); + } + + public long getEstimatedBytes() { + return mEstimatedBytes; + } + + public long getSoftLimitBytes() { + return mSoftLimitBytes; + } + + public long getHardLimitBytes() { + return mHardLimitBytes; + } + + /** {@inheritDoc} */ + public int describeContents() { + return 0; + } + + /** {@inheritDoc} */ + public void writeToParcel(Parcel out, int flags) { + out.writeLong(mEstimatedBytes); + out.writeLong(mSoftLimitBytes); + out.writeLong(mHardLimitBytes); + } + + public static final Creator<NetworkQuotaInfo> CREATOR = new Creator<NetworkQuotaInfo>() { + public NetworkQuotaInfo createFromParcel(Parcel in) { + return new NetworkQuotaInfo(in); + } + + public NetworkQuotaInfo[] newArray(int size) { + return new NetworkQuotaInfo[size]; + } + }; +} diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 4ffabb15b631..7a4b811763aa 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -405,11 +405,10 @@ public class NetworkStatsHistory implements Parcelable { final long curEnd = randomLong(r, curStart, end); entry.rxBytes = randomLong(r, 0, rx); entry.txBytes = randomLong(r, 0, tx); - - recordData(curStart, curEnd, entry); - rx -= entry.rxBytes; tx -= entry.txBytes; + + recordData(curStart, curEnd, entry); } } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 2a724d46c7d3..c1d1f7503070 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -40,6 +40,7 @@ import android.net.MobileDataStateTracker; import android.net.NetworkConfig; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; +import android.net.NetworkQuotaInfo; import android.net.NetworkState; import android.net.NetworkStateTracker; import android.net.NetworkUtils; @@ -737,6 +738,30 @@ public class ConnectivityService extends IConnectivityManager.Stub { return result.toArray(new NetworkState[result.size()]); } + private NetworkState getNetworkStateUnchecked(int networkType) { + if (isNetworkTypeValid(networkType)) { + final NetworkStateTracker tracker = mNetTrackers[networkType]; + if (tracker != null) { + return new NetworkState(tracker.getNetworkInfo(), tracker.getLinkProperties(), + tracker.getLinkCapabilities()); + } + } + return null; + } + + @Override + public NetworkQuotaInfo getActiveNetworkQuotaInfo() { + enforceAccessPermission(); + final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork); + if (state != null) { + try { + return mPolicyManager.getNetworkQuotaInfo(state); + } catch (RemoteException e) { + } + } + return null; + } + public boolean setRadios(boolean turnOn) { boolean result = true; enforceChangePermission(); diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 756cd004e4ff..a07525502003 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -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); |