Snap for 4560043 from 26466e44b704fb279af2247fafb86ac7bf0bdc3d to pi-release
Change-Id: I3b7e9c308d09587faf7a4be8956620ebd61db1c1
This commit is contained in:
@@ -131,6 +131,17 @@ public class NetworkStatsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public Bucket querySummaryForDevice(NetworkTemplate template,
|
||||||
|
long startTime, long endTime) throws SecurityException, RemoteException {
|
||||||
|
Bucket bucket = null;
|
||||||
|
NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
||||||
|
bucket = stats.getDeviceSummaryForNetwork();
|
||||||
|
|
||||||
|
stats.close();
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query network usage statistics summaries. Result is summarised data usage for the whole
|
* Query network usage statistics summaries. Result is summarised data usage for the whole
|
||||||
* device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
|
* device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
|
||||||
@@ -163,12 +174,7 @@ public class NetworkStatsManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bucket bucket = null;
|
return querySummaryForDevice(template, startTime, endTime);
|
||||||
NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
|
|
||||||
bucket = stats.getDeviceSummaryForNetwork();
|
|
||||||
|
|
||||||
stats.close();
|
|
||||||
return bucket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -340,6 +346,37 @@ public class NetworkStatsManager {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public void registerUsageCallback(NetworkTemplate template, int networkType,
|
||||||
|
long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
|
||||||
|
checkNotNull(callback, "UsageCallback cannot be null");
|
||||||
|
|
||||||
|
final Looper looper;
|
||||||
|
if (handler == null) {
|
||||||
|
looper = Looper.myLooper();
|
||||||
|
} else {
|
||||||
|
looper = handler.getLooper();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
|
||||||
|
template, thresholdBytes);
|
||||||
|
try {
|
||||||
|
CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
|
||||||
|
template.getSubscriberId(), callback);
|
||||||
|
callback.request = mService.registerUsageCallback(
|
||||||
|
mContext.getOpPackageName(), request, new Messenger(callbackHandler),
|
||||||
|
new Binder());
|
||||||
|
if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
|
||||||
|
|
||||||
|
if (callback.request == null) {
|
||||||
|
Log.e(TAG, "Request from callback is null; should not happen");
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
if (DBG) Log.d(TAG, "Remote exception when registering callback");
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers to receive notifications about data usage on specified networks.
|
* Registers to receive notifications about data usage on specified networks.
|
||||||
*
|
*
|
||||||
@@ -368,15 +405,7 @@ public class NetworkStatsManager {
|
|||||||
*/
|
*/
|
||||||
public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
|
public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
|
||||||
UsageCallback callback, @Nullable Handler handler) {
|
UsageCallback callback, @Nullable Handler handler) {
|
||||||
checkNotNull(callback, "UsageCallback cannot be null");
|
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
||||||
|
|
||||||
final Looper looper;
|
|
||||||
if (handler == null) {
|
|
||||||
looper = Looper.myLooper();
|
|
||||||
} else {
|
|
||||||
looper = handler.getLooper();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Log.d(TAG, "registerUsageCallback called with: {"
|
Log.d(TAG, "registerUsageCallback called with: {"
|
||||||
+ " networkType=" + networkType
|
+ " networkType=" + networkType
|
||||||
@@ -384,25 +413,7 @@ public class NetworkStatsManager {
|
|||||||
+ " thresholdBytes=" + thresholdBytes
|
+ " thresholdBytes=" + thresholdBytes
|
||||||
+ " }");
|
+ " }");
|
||||||
}
|
}
|
||||||
|
registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
|
||||||
NetworkTemplate template = createTemplate(networkType, subscriberId);
|
|
||||||
DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
|
|
||||||
template, thresholdBytes);
|
|
||||||
try {
|
|
||||||
CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
|
|
||||||
subscriberId, callback);
|
|
||||||
callback.request = mService.registerUsageCallback(
|
|
||||||
mContext.getOpPackageName(), request, new Messenger(callbackHandler),
|
|
||||||
new Binder());
|
|
||||||
if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
|
|
||||||
|
|
||||||
if (callback.request == null) {
|
|
||||||
Log.e(TAG, "Request from callback is null; should not happen");
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
if (DBG) Log.d(TAG, "Remote exception when registering callback");
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ interface IIpSecService
|
|||||||
|
|
||||||
void closeUdpEncapsulationSocket(int resourceId);
|
void closeUdpEncapsulationSocket(int resourceId);
|
||||||
|
|
||||||
IpSecTransformResponse createTransportModeTransform(in IpSecConfig c, in IBinder binder);
|
IpSecTransformResponse createTransform(in IpSecConfig c, in IBinder binder);
|
||||||
|
|
||||||
void deleteTransportModeTransform(int transformId);
|
void deleteTransform(int transformId);
|
||||||
|
|
||||||
void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId);
|
void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId);
|
||||||
|
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
try {
|
||||||
IIpSecService svc = getIpSecService();
|
IIpSecService svc = getIpSecService();
|
||||||
IpSecTransformResponse result =
|
IpSecTransformResponse result = svc.createTransform(mConfig, new Binder());
|
||||||
svc.createTransportModeTransform(mConfig, new Binder());
|
|
||||||
int status = result.status;
|
int status = result.status;
|
||||||
checkResultStatus(status);
|
checkResultStatus(status);
|
||||||
mResourceId = result.resourceId;
|
mResourceId = result.resourceId;
|
||||||
@@ -170,7 +169,7 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
* still want to clear out the transform.
|
* still want to clear out the transform.
|
||||||
*/
|
*/
|
||||||
IIpSecService svc = getIpSecService();
|
IIpSecService svc = getIpSecService();
|
||||||
svc.deleteTransportModeTransform(mResourceId);
|
svc.deleteTransform(mResourceId);
|
||||||
stopKeepalive();
|
stopKeepalive();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowAsRuntimeException();
|
throw e.rethrowAsRuntimeException();
|
||||||
|
|||||||
@@ -160,13 +160,6 @@ public class NetworkStats implements Parcelable {
|
|||||||
rxBytes, rxPackets, txBytes, txPackets, operations);
|
rxBytes, rxPackets, txBytes, txPackets, operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix the the telephony code to pass DEFAULT_NETWORK_YES and remove this constructor.
|
|
||||||
public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
|
|
||||||
long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
|
|
||||||
this(iface, uid, set, tag, metered, roaming, DEFAULT_NETWORK_YES, rxBytes, rxPackets,
|
|
||||||
txBytes, txPackets, operations);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
|
public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
|
||||||
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
|
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
|
||||||
long operations) {
|
long operations) {
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
|
|||||||
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
|
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
|
||||||
import static android.net.ConnectivityManager.TYPE_WIMAX;
|
import static android.net.ConnectivityManager.TYPE_WIMAX;
|
||||||
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
|
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
|
||||||
|
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
|
||||||
|
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
|
||||||
|
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
|
||||||
|
import static android.net.NetworkStats.METERED_ALL;
|
||||||
|
import static android.net.NetworkStats.METERED_NO;
|
||||||
|
import static android.net.NetworkStats.METERED_YES;
|
||||||
|
import static android.net.NetworkStats.ROAMING_ALL;
|
||||||
|
import static android.net.NetworkStats.ROAMING_NO;
|
||||||
|
import static android.net.NetworkStats.ROAMING_YES;
|
||||||
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
|
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
|
||||||
import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
|
import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
|
||||||
import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
|
import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
|
||||||
@@ -191,16 +200,30 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
|
|
||||||
private final String mNetworkId;
|
private final String mNetworkId;
|
||||||
|
|
||||||
|
// Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
|
||||||
|
private final int mMetered;
|
||||||
|
private final int mRoaming;
|
||||||
|
private final int mDefaultNetwork;
|
||||||
|
|
||||||
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
|
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
|
||||||
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
|
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
|
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
|
||||||
String networkId) {
|
String networkId) {
|
||||||
|
this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
|
||||||
|
DEFAULT_NETWORK_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
|
||||||
|
String networkId, int metered, int roaming, int defaultNetwork) {
|
||||||
mMatchRule = matchRule;
|
mMatchRule = matchRule;
|
||||||
mSubscriberId = subscriberId;
|
mSubscriberId = subscriberId;
|
||||||
mMatchSubscriberIds = matchSubscriberIds;
|
mMatchSubscriberIds = matchSubscriberIds;
|
||||||
mNetworkId = networkId;
|
mNetworkId = networkId;
|
||||||
|
mMetered = metered;
|
||||||
|
mRoaming = roaming;
|
||||||
|
mDefaultNetwork = defaultNetwork;
|
||||||
|
|
||||||
if (!isKnownMatchRule(matchRule)) {
|
if (!isKnownMatchRule(matchRule)) {
|
||||||
Log.e(TAG, "Unknown network template rule " + matchRule
|
Log.e(TAG, "Unknown network template rule " + matchRule
|
||||||
@@ -213,6 +236,9 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
mSubscriberId = in.readString();
|
mSubscriberId = in.readString();
|
||||||
mMatchSubscriberIds = in.createStringArray();
|
mMatchSubscriberIds = in.createStringArray();
|
||||||
mNetworkId = in.readString();
|
mNetworkId = in.readString();
|
||||||
|
mMetered = in.readInt();
|
||||||
|
mRoaming = in.readInt();
|
||||||
|
mDefaultNetwork = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -221,6 +247,9 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
dest.writeString(mSubscriberId);
|
dest.writeString(mSubscriberId);
|
||||||
dest.writeStringArray(mMatchSubscriberIds);
|
dest.writeStringArray(mMatchSubscriberIds);
|
||||||
dest.writeString(mNetworkId);
|
dest.writeString(mNetworkId);
|
||||||
|
dest.writeInt(mMetered);
|
||||||
|
dest.writeInt(mRoaming);
|
||||||
|
dest.writeInt(mDefaultNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -243,12 +272,23 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
if (mNetworkId != null) {
|
if (mNetworkId != null) {
|
||||||
builder.append(", networkId=").append(mNetworkId);
|
builder.append(", networkId=").append(mNetworkId);
|
||||||
}
|
}
|
||||||
|
if (mMetered != METERED_ALL) {
|
||||||
|
builder.append(", metered=").append(NetworkStats.meteredToString(mMetered));
|
||||||
|
}
|
||||||
|
if (mRoaming != ROAMING_ALL) {
|
||||||
|
builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming));
|
||||||
|
}
|
||||||
|
if (mDefaultNetwork != DEFAULT_NETWORK_ALL) {
|
||||||
|
builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
|
||||||
|
mDefaultNetwork));
|
||||||
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(mMatchRule, mSubscriberId, mNetworkId);
|
return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
|
||||||
|
mDefaultNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -257,7 +297,10 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
final NetworkTemplate other = (NetworkTemplate) obj;
|
final NetworkTemplate other = (NetworkTemplate) obj;
|
||||||
return mMatchRule == other.mMatchRule
|
return mMatchRule == other.mMatchRule
|
||||||
&& Objects.equals(mSubscriberId, other.mSubscriberId)
|
&& Objects.equals(mSubscriberId, other.mSubscriberId)
|
||||||
&& Objects.equals(mNetworkId, other.mNetworkId);
|
&& Objects.equals(mNetworkId, other.mNetworkId)
|
||||||
|
&& mMetered == other.mMetered
|
||||||
|
&& mRoaming == other.mRoaming
|
||||||
|
&& mDefaultNetwork == other.mDefaultNetwork;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -300,6 +343,10 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
* Test if given {@link NetworkIdentity} matches this template.
|
* Test if given {@link NetworkIdentity} matches this template.
|
||||||
*/
|
*/
|
||||||
public boolean matches(NetworkIdentity ident) {
|
public boolean matches(NetworkIdentity ident) {
|
||||||
|
if (!matchesMetered(ident)) return false;
|
||||||
|
if (!matchesRoaming(ident)) return false;
|
||||||
|
if (!matchesDefaultNetwork(ident)) return false;
|
||||||
|
|
||||||
switch (mMatchRule) {
|
switch (mMatchRule) {
|
||||||
case MATCH_MOBILE_ALL:
|
case MATCH_MOBILE_ALL:
|
||||||
return matchesMobile(ident);
|
return matchesMobile(ident);
|
||||||
@@ -326,6 +373,24 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean matchesMetered(NetworkIdentity ident) {
|
||||||
|
return (mMetered == METERED_ALL)
|
||||||
|
|| (mMetered == METERED_YES && ident.mMetered)
|
||||||
|
|| (mMetered == METERED_NO && !ident.mMetered);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesRoaming(NetworkIdentity ident) {
|
||||||
|
return (mRoaming == ROAMING_ALL)
|
||||||
|
|| (mRoaming == ROAMING_YES && ident.mRoaming)
|
||||||
|
|| (mRoaming == ROAMING_NO && !ident.mRoaming);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesDefaultNetwork(NetworkIdentity ident) {
|
||||||
|
return (mDefaultNetwork == DEFAULT_NETWORK_ALL)
|
||||||
|
|| (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork)
|
||||||
|
|| (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean matchesSubscriberId(String subscriberId) {
|
public boolean matchesSubscriberId(String subscriberId) {
|
||||||
return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
|
return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
* resources.
|
* resources.
|
||||||
*
|
*
|
||||||
* <p>References to the IResource object may be held by other RefcountedResource objects,
|
* <p>References to the IResource object may be held by other RefcountedResource objects,
|
||||||
* and as such, the kernel resources and quota may not be cleaned up.
|
* and as such, the underlying resources and quota may not be cleaned up.
|
||||||
*/
|
*/
|
||||||
void invalidate() throws RemoteException;
|
void invalidate() throws RemoteException;
|
||||||
|
|
||||||
@@ -298,7 +298,12 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Very simple counting class that looks much like a counting semaphore */
|
/**
|
||||||
|
* Very simple counting class that looks much like a counting semaphore
|
||||||
|
*
|
||||||
|
* <p>This class is not thread-safe, and expects that that users of this class will ensure
|
||||||
|
* synchronization and thread safety by holding the IpSecService.this instance lock.
|
||||||
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static class ResourceTracker {
|
static class ResourceTracker {
|
||||||
private final int mMax;
|
private final int mMax;
|
||||||
@@ -341,26 +346,38 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final class UserRecord {
|
static final class UserRecord {
|
||||||
/* Type names */
|
|
||||||
public static final String TYPENAME_SPI = "SecurityParameterIndex";
|
|
||||||
public static final String TYPENAME_TRANSFORM = "IpSecTransform";
|
|
||||||
public static final String TYPENAME_ENCAP_SOCKET = "UdpEncapSocket";
|
|
||||||
|
|
||||||
/* Maximum number of each type of resource that a single UID may possess */
|
/* Maximum number of each type of resource that a single UID may possess */
|
||||||
public static final int MAX_NUM_ENCAP_SOCKETS = 2;
|
public static final int MAX_NUM_ENCAP_SOCKETS = 2;
|
||||||
public static final int MAX_NUM_TRANSFORMS = 4;
|
public static final int MAX_NUM_TRANSFORMS = 4;
|
||||||
public static final int MAX_NUM_SPIS = 8;
|
public static final int MAX_NUM_SPIS = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing
|
||||||
|
* and explicit (user) reference management.
|
||||||
|
*
|
||||||
|
* <p>These are stored in separate arrays to improve debuggability and dump output clarity.
|
||||||
|
*
|
||||||
|
* <p>Resources are removed from this array when the user releases their explicit reference
|
||||||
|
* by calling one of the releaseResource() methods.
|
||||||
|
*/
|
||||||
final RefcountedResourceArray<SpiRecord> mSpiRecords =
|
final RefcountedResourceArray<SpiRecord> mSpiRecords =
|
||||||
new RefcountedResourceArray<>(TYPENAME_SPI);
|
new RefcountedResourceArray<>(SpiRecord.class.getSimpleName());
|
||||||
final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS);
|
|
||||||
|
|
||||||
final RefcountedResourceArray<TransformRecord> mTransformRecords =
|
final RefcountedResourceArray<TransformRecord> mTransformRecords =
|
||||||
new RefcountedResourceArray<>(TYPENAME_TRANSFORM);
|
new RefcountedResourceArray<>(TransformRecord.class.getSimpleName());
|
||||||
final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS);
|
|
||||||
|
|
||||||
final RefcountedResourceArray<EncapSocketRecord> mEncapSocketRecords =
|
final RefcountedResourceArray<EncapSocketRecord> mEncapSocketRecords =
|
||||||
new RefcountedResourceArray<>(TYPENAME_ENCAP_SOCKET);
|
new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trackers for quotas for each of the OwnedResource types.
|
||||||
|
*
|
||||||
|
* <p>These trackers are separate from the resource arrays, since they are incremented and
|
||||||
|
* decremented at different points in time. Specifically, quota is only returned upon final
|
||||||
|
* resource deallocation (after all explicit and implicit references are released). Note
|
||||||
|
* that it is possible that calls to releaseResource() will not return the used quota if
|
||||||
|
* there are other resources that depend on (are parents of) the resource being released.
|
||||||
|
*/
|
||||||
|
final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS);
|
||||||
|
final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS);
|
||||||
final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
|
final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
|
||||||
|
|
||||||
void removeSpiRecord(int resourceId) {
|
void removeSpiRecord(int resourceId) {
|
||||||
@@ -395,11 +412,15 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is not thread-safe, and expects that that users of this class will ensure
|
||||||
|
* synchronization and thread safety by holding the IpSecService.this instance lock.
|
||||||
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final class UserResourceTracker {
|
static final class UserResourceTracker {
|
||||||
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
|
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
|
||||||
|
|
||||||
/** Never-fail getter that populates the list of UIDs as-needed */
|
/** Lazy-initialization/getter that populates or retrieves the UserRecord as needed */
|
||||||
public UserRecord getUserRecord(int uid) {
|
public UserRecord getUserRecord(int uid) {
|
||||||
checkCallerUid(uid);
|
checkCallerUid(uid);
|
||||||
|
|
||||||
@@ -428,18 +449,20 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
@VisibleForTesting final UserResourceTracker mUserResourceTracker = new UserResourceTracker();
|
@VisibleForTesting final UserResourceTracker mUserResourceTracker = new UserResourceTracker();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The KernelResourceRecord class provides a facility to cleanly and reliably track system
|
* The OwnedResourceRecord class provides a facility to cleanly and reliably track system
|
||||||
* resources. It relies on a provided resourceId that should uniquely identify the kernel
|
* resources. It relies on a provided resourceId that should uniquely identify the kernel
|
||||||
* resource. To use this class, the user should implement the invalidate() and
|
* resource. To use this class, the user should implement the invalidate() and
|
||||||
* freeUnderlyingResources() methods that are responsible for cleaning up IpSecService resource
|
* freeUnderlyingResources() methods that are responsible for cleaning up IpSecService resource
|
||||||
* tracking arrays and kernel resources, respectively
|
* tracking arrays and kernel resources, respectively.
|
||||||
|
*
|
||||||
|
* <p>This class associates kernel resources with the UID that owns and controls them.
|
||||||
*/
|
*/
|
||||||
private abstract class KernelResourceRecord implements IResource {
|
private abstract class OwnedResourceRecord implements IResource {
|
||||||
final int pid;
|
final int pid;
|
||||||
final int uid;
|
final int uid;
|
||||||
protected final int mResourceId;
|
protected final int mResourceId;
|
||||||
|
|
||||||
KernelResourceRecord(int resourceId) {
|
OwnedResourceRecord(int resourceId) {
|
||||||
super();
|
super();
|
||||||
if (resourceId == INVALID_RESOURCE_ID) {
|
if (resourceId == INVALID_RESOURCE_ID) {
|
||||||
throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
|
throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
|
||||||
@@ -479,8 +502,6 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Move this to right after RefcountedResource. With this here, Gerrit was showing many
|
|
||||||
// more things as changed.
|
|
||||||
/**
|
/**
|
||||||
* Thin wrapper over SparseArray to ensure resources exist, and simplify generic typing.
|
* Thin wrapper over SparseArray to ensure resources exist, and simplify generic typing.
|
||||||
*
|
*
|
||||||
@@ -534,7 +555,12 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class TransformRecord extends KernelResourceRecord {
|
/**
|
||||||
|
* Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is
|
||||||
|
* created, the SpiRecord that originally tracked the SAs will reliquish the
|
||||||
|
* responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag.
|
||||||
|
*/
|
||||||
|
private final class TransformRecord extends OwnedResourceRecord {
|
||||||
private final IpSecConfig mConfig;
|
private final IpSecConfig mConfig;
|
||||||
private final SpiRecord mSpi;
|
private final SpiRecord mSpi;
|
||||||
private final EncapSocketRecord mSocket;
|
private final EncapSocketRecord mSocket;
|
||||||
@@ -603,7 +629,12 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SpiRecord extends KernelResourceRecord {
|
/**
|
||||||
|
* Tracks a single SA in the kernel, and manages cleanup paths. Once used in a Transform, the
|
||||||
|
* responsibility for cleaning up underlying resources will be passed to the TransformRecord
|
||||||
|
* object
|
||||||
|
*/
|
||||||
|
private final class SpiRecord extends OwnedResourceRecord {
|
||||||
private final String mSourceAddress;
|
private final String mSourceAddress;
|
||||||
private final String mDestinationAddress;
|
private final String mDestinationAddress;
|
||||||
private int mSpi;
|
private int mSpi;
|
||||||
@@ -692,7 +723,14 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class EncapSocketRecord extends KernelResourceRecord {
|
/**
|
||||||
|
* Tracks a UDP encap socket, and manages cleanup paths
|
||||||
|
*
|
||||||
|
* <p>While this class does not manage non-kernel resources, race conditions around socket
|
||||||
|
* binding require that the service creates the encap socket, binds it and applies the socket
|
||||||
|
* policy before handing it to a user.
|
||||||
|
*/
|
||||||
|
private final class EncapSocketRecord extends OwnedResourceRecord {
|
||||||
private FileDescriptor mSocket;
|
private FileDescriptor mSocket;
|
||||||
private final int mPort;
|
private final int mPort;
|
||||||
|
|
||||||
@@ -1105,16 +1143,14 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
* receive data.
|
* receive data.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized IpSecTransformResponse createTransportModeTransform(
|
public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder)
|
||||||
IpSecConfig c, IBinder binder) throws RemoteException {
|
throws RemoteException {
|
||||||
checkIpSecConfig(c);
|
checkIpSecConfig(c);
|
||||||
checkNotNull(binder, "Null Binder passed to createTransportModeTransform");
|
checkNotNull(binder, "Null Binder passed to createTransform");
|
||||||
final int resourceId = mNextResourceId++;
|
final int resourceId = mNextResourceId++;
|
||||||
|
|
||||||
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
||||||
|
List<RefcountedResource> dependencies = new ArrayList<>();
|
||||||
// Avoid resizing by creating a dependency array of min-size 2 (1 UDP encap + 1 SPI)
|
|
||||||
List<RefcountedResource> dependencies = new ArrayList<>(2);
|
|
||||||
|
|
||||||
if (!userRecord.mTransformQuotaTracker.isAvailable()) {
|
if (!userRecord.mTransformQuotaTracker.isAvailable()) {
|
||||||
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
|
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
|
||||||
@@ -1186,7 +1222,7 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
* other reasons.
|
* other reasons.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void deleteTransportModeTransform(int resourceId) throws RemoteException {
|
public synchronized void deleteTransform(int resourceId) throws RemoteException {
|
||||||
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
||||||
releaseResource(userRecord.mTransformRecords, resourceId);
|
releaseResource(userRecord.mTransformRecords, resourceId);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user