Map network identity using ConnectivityService. am: 21062e7c7e

Original change: undetermined

Change-Id: If25f03553cafc21a4a799ee961eb5d5ecb773d97
This commit is contained in:
Jeff Sharkey
2021-05-31 04:23:12 +00:00
committed by Automerger Merge Worker
5 changed files with 174 additions and 43 deletions

View File

@@ -256,10 +256,61 @@ public class ConnectivityManager {
private final IConnectivityManager mService;
static public boolean isNetworkTypeValid(int networkType) {
public static boolean isNetworkTypeValid(int networkType) {
return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
}
/** {@hide} */
public static String getNetworkTypeName(int type) {
switch (type) {
case TYPE_MOBILE:
return "MOBILE";
case TYPE_WIFI:
return "WIFI";
case TYPE_MOBILE_MMS:
return "MOBILE_MMS";
case TYPE_MOBILE_SUPL:
return "MOBILE_SUPL";
case TYPE_MOBILE_DUN:
return "MOBILE_DUN";
case TYPE_MOBILE_HIPRI:
return "MOBILE_HIPRI";
case TYPE_WIMAX:
return "WIMAX";
case TYPE_BLUETOOTH:
return "BLUETOOTH";
case TYPE_DUMMY:
return "DUMMY";
case TYPE_ETHERNET:
return "ETHERNET";
case TYPE_MOBILE_FOTA:
return "MOBILE_FOTA";
case TYPE_MOBILE_IMS:
return "MOBILE_IMS";
case TYPE_MOBILE_CBS:
return "MOBILE_CBS";
default:
return Integer.toString(type);
}
}
/** {@hide} */
public static boolean isNetworkTypeMobile(int networkType) {
switch (networkType) {
case TYPE_MOBILE:
case TYPE_MOBILE_MMS:
case TYPE_MOBILE_SUPL:
case TYPE_MOBILE_DUN:
case TYPE_MOBILE_HIPRI:
case TYPE_MOBILE_FOTA:
case TYPE_MOBILE_IMS:
case TYPE_MOBILE_CBS:
return true;
default:
return false;
}
}
public void setNetworkPreference(int preference) {
try {
mService.setNetworkPreference(preference);

View File

@@ -18,6 +18,7 @@ package android.net;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkState;
import android.net.ProxyProperties;
import android.os.IBinder;
@@ -40,6 +41,8 @@ interface IConnectivityManager
LinkProperties getActiveLinkProperties();
LinkProperties getLinkProperties(int networkType);
NetworkState[] getAllNetworkState();
boolean setRadios(boolean onOff);
boolean setRadio(int networkType, boolean turnOn);

View File

@@ -0,0 +1,68 @@
/*
* 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;
/**
* Snapshot of network state.
*
* @hide
*/
public class NetworkState implements Parcelable {
public final NetworkInfo networkInfo;
public final LinkProperties linkProperties;
public final LinkCapabilities linkCapabilities;
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
LinkCapabilities linkCapabilities) {
this.networkInfo = networkInfo;
this.linkProperties = linkProperties;
this.linkCapabilities = linkCapabilities;
}
public NetworkState(Parcel in) {
networkInfo = in.readParcelable(null);
linkProperties = in.readParcelable(null);
linkCapabilities = in.readParcelable(null);
}
/** {@inheritDoc} */
public int describeContents() {
return 0;
}
/** {@inheritDoc} */
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(networkInfo, flags);
out.writeParcelable(linkProperties, flags);
out.writeParcelable(linkCapabilities, flags);
}
public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() {
public NetworkState createFromParcel(Parcel in) {
return new NetworkState(in);
}
public NetworkState[] newArray(int size) {
return new NetworkState[size];
}
};
}

View File

@@ -16,8 +16,6 @@
package android.net;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkStatsHistory.UID_ALL;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -51,7 +49,7 @@ public class NetworkStatsHistoryTest extends TestCase {
public void testRecordSingleBucket() throws Exception {
final long BUCKET_SIZE = HOUR_IN_MILLIS;
stats = buildStats(BUCKET_SIZE);
stats = new NetworkStatsHistory(BUCKET_SIZE);
// record data into narrow window to get single bucket
stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L);
@@ -62,7 +60,7 @@ public class NetworkStatsHistoryTest extends TestCase {
public void testRecordEqualBuckets() throws Exception {
final long bucketDuration = HOUR_IN_MILLIS;
stats = buildStats(bucketDuration);
stats = new NetworkStatsHistory(bucketDuration);
// split equally across two buckets
final long recordStart = TEST_START + (bucketDuration / 2);
@@ -75,7 +73,7 @@ public class NetworkStatsHistoryTest extends TestCase {
public void testRecordTouchingBuckets() throws Exception {
final long BUCKET_SIZE = 15 * MINUTE_IN_MILLIS;
stats = buildStats(BUCKET_SIZE);
stats = new NetworkStatsHistory(BUCKET_SIZE);
// split almost completely into middle bucket, but with a few minutes
// overlap into neighboring buckets. total record is 20 minutes.
@@ -94,7 +92,7 @@ public class NetworkStatsHistoryTest extends TestCase {
public void testRecordGapBuckets() throws Exception {
final long BUCKET_SIZE = HOUR_IN_MILLIS;
stats = buildStats(BUCKET_SIZE);
stats = new NetworkStatsHistory(BUCKET_SIZE);
// record some data today and next week with large gap
final long firstStart = TEST_START;
@@ -122,7 +120,7 @@ public class NetworkStatsHistoryTest extends TestCase {
public void testRecordOverlapBuckets() throws Exception {
final long BUCKET_SIZE = HOUR_IN_MILLIS;
stats = buildStats(BUCKET_SIZE);
stats = new NetworkStatsHistory(BUCKET_SIZE);
// record some data in one bucket, and another overlapping buckets
stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 256L, 256L);
@@ -137,7 +135,7 @@ public class NetworkStatsHistoryTest extends TestCase {
public void testRemove() throws Exception {
final long BUCKET_SIZE = HOUR_IN_MILLIS;
stats = buildStats(BUCKET_SIZE);
stats = new NetworkStatsHistory(BUCKET_SIZE);
// record some data across 24 buckets
stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L);
@@ -171,7 +169,7 @@ public class NetworkStatsHistoryTest extends TestCase {
// fuzzing with random events, looking for crashes
final Random r = new Random();
for (int i = 0; i < 500; i++) {
stats = buildStats(r.nextLong());
stats = new NetworkStatsHistory(r.nextLong());
for (int j = 0; j < 10000; j++) {
if (r.nextBoolean()) {
// add range
@@ -191,10 +189,6 @@ public class NetworkStatsHistoryTest extends TestCase {
}
}
private static NetworkStatsHistory buildStats(long bucketSize) {
return new NetworkStatsHistory(TYPE_MOBILE, null, UID_ALL, bucketSize);
}
private static void assertConsistent(NetworkStatsHistory stats) {
// verify timestamps are monotonic
for (int i = 1; i < stats.bucketCount; i++) {

View File

@@ -16,6 +16,7 @@
package com.android.server;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
@@ -38,6 +39,7 @@ import android.net.MobileDataStateTracker;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkState;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.net.Proxy;
@@ -65,6 +67,7 @@ import android.util.SparseIntArray;
import com.android.internal.telephony.Phone;
import com.android.server.connectivity.Tethering;
import com.google.android.collect.Lists;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -563,25 +566,32 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
private boolean isNetworkBlocked(NetworkInfo info, int uid) {
synchronized (mUidRules) {
return isNetworkBlockedLocked(info, uid);
// TODO: expand definition of "paid" network to cover tethered or
// paid hotspot use cases.
final boolean networkIsPaid = info.getType() != ConnectivityManager.TYPE_WIFI;
final int uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
if (networkIsPaid && (uidRules & RULE_REJECT_PAID) != 0) {
return true;
}
// no restrictive rules; network is visible
return false;
}
}
/**
* Check if UID is blocked from using the given {@link NetworkInfo}.
* Return a filtered version of the given {@link NetworkInfo}, potentially
* marked {@link DetailedState#BLOCKED} based on
* {@link #isNetworkBlocked(NetworkInfo, int)}.
*/
private boolean isNetworkBlockedLocked(NetworkInfo info, int uid) {
// TODO: expand definition of "paid" network to cover tethered or paid
// hotspot use cases.
final boolean networkIsPaid = info.getType() != ConnectivityManager.TYPE_WIFI;
final int uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
if (networkIsPaid && (uidRules & RULE_REJECT_PAID) != 0) {
return true;
private NetworkInfo filterNetworkInfo(NetworkInfo info, int uid) {
if (isNetworkBlocked(info, uid)) {
// network is blocked; clone and override state
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
}
// no restrictive rules; network is visible
return false;
return info;
}
/**
@@ -616,12 +626,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (isNetworkTypeValid(networkType)) {
final NetworkStateTracker tracker = mNetTrackers[networkType];
if (tracker != null) {
info = tracker.getNetworkInfo();
if (isNetworkBlocked(info, uid)) {
// network is blocked; clone and override state
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
}
info = filterNetworkInfo(tracker.getNetworkInfo(), uid);
}
}
return info;
@@ -631,22 +636,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
public NetworkInfo[] getAllNetworkInfo() {
enforceAccessPermission();
final int uid = Binder.getCallingUid();
final NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
int i = 0;
final ArrayList<NetworkInfo> result = Lists.newArrayList();
synchronized (mUidRules) {
for (NetworkStateTracker tracker : mNetTrackers) {
if (tracker != null) {
NetworkInfo info = tracker.getNetworkInfo();
if (isNetworkBlockedLocked(info, uid)) {
// network is blocked; clone and override state
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
}
result[i++] = info;
result.add(filterNetworkInfo(tracker.getNetworkInfo(), uid));
}
}
}
return result;
return result.toArray(new NetworkInfo[result.size()]);
}
/**
@@ -674,6 +672,23 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return null;
}
@Override
public NetworkState[] getAllNetworkState() {
enforceAccessPermission();
final int uid = Binder.getCallingUid();
final ArrayList<NetworkState> result = Lists.newArrayList();
synchronized (mUidRules) {
for (NetworkStateTracker tracker : mNetTrackers) {
if (tracker != null) {
final NetworkInfo info = filterNetworkInfo(tracker.getNetworkInfo(), uid);
result.add(new NetworkState(
info, tracker.getLinkProperties(), tracker.getLinkCapabilities()));
}
}
}
return result.toArray(new NetworkState[result.size()]);
}
public boolean setRadios(boolean turnOn) {
boolean result = true;
enforceChangePermission();