Merge sc-qpr1 to aosp-master - DO NOT MERGE
Merged-In: I90ca5ccbf686a975f479c2488ff34f82af12946a
Merged-In: I128f5ed6c1bad350ea449bba5da21123de3ea31b
Change-Id: Ib18c8042f735dceeee5e6ab9f1c963cf630913a6
diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/core/java/android/net/InternalNetworkManagementException.aidl
new file mode 100644
index 0000000..dcce706
--- /dev/null
+++ b/core/java/android/net/InternalNetworkManagementException.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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 InternalNetworkManagementException;
\ No newline at end of file
diff --git a/core/java/android/net/InternalNetworkManagementException.java b/core/java/android/net/InternalNetworkManagementException.java
new file mode 100644
index 0000000..7f4e403
--- /dev/null
+++ b/core/java/android/net/InternalNetworkManagementException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public final class InternalNetworkManagementException
+ extends RuntimeException implements Parcelable {
+
+ /* @hide */
+ public InternalNetworkManagementException(@NonNull final Throwable t) {
+ super(t);
+ }
+
+ private InternalNetworkManagementException(@NonNull final Parcel source) {
+ super(source.readString());
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(getCause().getMessage());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR =
+ new Parcelable.Creator<InternalNetworkManagementException>() {
+ @Override
+ public InternalNetworkManagementException[] newArray(int size) {
+ return new InternalNetworkManagementException[size];
+ }
+
+ @Override
+ public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) {
+ return new InternalNetworkManagementException(source);
+ }
+ };
+}
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/core/java/android/net/InternalNetworkUpdateRequest.aidl
new file mode 100644
index 0000000..da00cb9
--- /dev/null
+++ b/core/java/android/net/InternalNetworkUpdateRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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 InternalNetworkUpdateRequest;
\ No newline at end of file
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/core/java/android/net/InternalNetworkUpdateRequest.java
new file mode 100644
index 0000000..6f09383
--- /dev/null
+++ b/core/java/android/net/InternalNetworkUpdateRequest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** @hide */
+public final class InternalNetworkUpdateRequest implements Parcelable {
+ @NonNull
+ private final StaticIpConfiguration mIpConfig;
+ @Nullable
+ private final NetworkCapabilities mNetworkCapabilities;
+
+ @NonNull
+ public StaticIpConfiguration getIpConfig() {
+ return new StaticIpConfiguration(mIpConfig);
+ }
+
+ @NonNull
+ public NetworkCapabilities getNetworkCapabilities() {
+ return mNetworkCapabilities == null
+ ? null : new NetworkCapabilities(mNetworkCapabilities);
+ }
+
+ /** @hide */
+ public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
+ @Nullable final NetworkCapabilities networkCapabilities) {
+ Objects.requireNonNull(ipConfig);
+ mIpConfig = new StaticIpConfiguration(ipConfig);
+ if (null == networkCapabilities) {
+ mNetworkCapabilities = null;
+ } else {
+ mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
+ }
+ }
+
+ private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
+ Objects.requireNonNull(source);
+ mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
+ mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
+ }
+
+ @Override
+ public String toString() {
+ return "InternalNetworkUpdateRequest{"
+ + "mIpConfig=" + mIpConfig
+ + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o;
+
+ return Objects.equals(that.getIpConfig(), mIpConfig)
+ && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIpConfig, mNetworkCapabilities);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mIpConfig.writeToParcel(dest, flags);
+ mNetworkCapabilities.writeToParcel(dest, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR =
+ new Parcelable.Creator<InternalNetworkUpdateRequest>() {
+ @Override
+ public InternalNetworkUpdateRequest[] newArray(int size) {
+ return new InternalNetworkUpdateRequest[size];
+ }
+
+ @Override
+ public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
+ return new InternalNetworkUpdateRequest(source);
+ }
+ };
+}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
deleted file mode 100644
index 762816d..0000000
--- a/core/java/android/net/NetworkTemplate.java
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
- * 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 static android.net.ConnectivityManager.TYPE_BLUETOOTH;
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_PROXY;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
-import static android.net.ConnectivityManager.TYPE_WIMAX;
-import static android.net.NetworkIdentity.OEM_NONE;
-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.sanitizeSsid;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Annotation.NetworkType;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.BackupUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Predicate used to match {@link NetworkIdentity}, usually when collecting
- * statistics. (It should probably have been named {@code NetworkPredicate}.)
- *
- * @hide
- */
-public class NetworkTemplate implements Parcelable {
- private static final String TAG = "NetworkTemplate";
-
- /**
- * Current Version of the Backup Serializer.
- */
- private static final int BACKUP_VERSION = 1;
-
- public static final int MATCH_MOBILE = 1;
- public static final int MATCH_WIFI = 4;
- public static final int MATCH_ETHERNET = 5;
- public static final int MATCH_MOBILE_WILDCARD = 6;
- public static final int MATCH_WIFI_WILDCARD = 7;
- public static final int MATCH_BLUETOOTH = 8;
- public static final int MATCH_PROXY = 9;
- public static final int MATCH_CARRIER = 10;
-
- /**
- * Value of the match rule of the subscriberId to match networks with specific subscriberId.
- */
- public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0;
- /**
- * Value of the match rule of the subscriberId to match networks with any subscriberId which
- * includes null and non-null.
- */
- public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1;
-
- /**
- * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that
- * should be fixed), so it's not possible to want to match null vs
- * non-null. Therefore it's fine to use null as a sentinel for Network ID.
- */
- public static final String WIFI_NETWORKID_ALL = null;
-
- /**
- * Include all network types when filtering. This is meant to merge in with the
- * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
- *
- * @hide
- */
- public static final int NETWORK_TYPE_ALL = -1;
- /**
- * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
- * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
- * with NR state as connected. This should not be overlapped with any of the
- * {@code TelephonyManager.NETWORK_TYPE_*} constants.
- *
- * @hide
- */
- public static final int NETWORK_TYPE_5G_NSA = -2;
-
- /**
- * Value to match both OEM managed and unmanaged networks (all networks).
- * @hide
- */
- public static final int OEM_MANAGED_ALL = -1;
- /**
- * Value to match networks which are not OEM managed.
- * @hide
- */
- public static final int OEM_MANAGED_NO = OEM_NONE;
- /**
- * Value to match any OEM managed network.
- * @hide
- */
- public static final int OEM_MANAGED_YES = -2;
-
- private static boolean isKnownMatchRule(final int rule) {
- switch (rule) {
- case MATCH_MOBILE:
- case MATCH_WIFI:
- case MATCH_ETHERNET:
- case MATCH_MOBILE_WILDCARD:
- case MATCH_WIFI_WILDCARD:
- case MATCH_BLUETOOTH:
- case MATCH_PROXY:
- case MATCH_CARRIER:
- return true;
-
- default:
- return false;
- }
- }
-
- private static boolean sForceAllNetworkTypes = false;
-
- /**
- * Results in matching against all mobile network types.
- *
- * <p>See {@link #matchesMobile} and {@link matchesMobileWildcard}.
- */
- @VisibleForTesting
- public static void forceAllNetworkTypes() {
- sForceAllNetworkTypes = true;
- }
-
- /** Resets the affect of {@link #forceAllNetworkTypes}. */
- @VisibleForTesting
- public static void resetForceAllNetworkTypes() {
- sForceAllNetworkTypes = false;
- }
-
- /**
- * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
- * the given IMSI.
- */
- @UnsupportedAppUsage
- public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
- return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
- }
-
- /**
- * Template to match cellular networks with the given IMSI and {@code ratType}.
- * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
- * See {@code TelephonyManager.NETWORK_TYPE_*}.
- */
- public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
- @NetworkType int ratType) {
- if (TextUtils.isEmpty(subscriberId)) {
- return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_EXACT);
- }
- return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_EXACT);
- }
-
- /**
- * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
- * regardless of IMSI.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static NetworkTemplate buildTemplateMobileWildcard() {
- return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
- }
-
- /**
- * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
- * regardless of SSID.
- */
- @UnsupportedAppUsage
- public static NetworkTemplate buildTemplateWifiWildcard() {
- // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL
- // and SUBSCRIBER_ID_MATCH_RULE_ALL.
- return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
- }
-
- @Deprecated
- @UnsupportedAppUsage
- public static NetworkTemplate buildTemplateWifi() {
- return buildTemplateWifiWildcard();
- }
-
- /**
- * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
- * given SSID.
- */
- public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) {
- Objects.requireNonNull(networkId);
- return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */,
- new String[] { null } /* matchSubscriberIds */,
- networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_ALL);
- }
-
- /**
- * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID,
- * and IMSI.
- *
- * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID.
- */
- public static NetworkTemplate buildTemplateWifi(@Nullable String networkId,
- @Nullable String subscriberId) {
- return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId },
- networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_EXACT);
- }
-
- /**
- * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
- * networks together.
- */
- @UnsupportedAppUsage
- public static NetworkTemplate buildTemplateEthernet() {
- return new NetworkTemplate(MATCH_ETHERNET, null, null);
- }
-
- /**
- * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
- * networks together.
- */
- public static NetworkTemplate buildTemplateBluetooth() {
- return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
- }
-
- /**
- * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
- * networks together.
- */
- public static NetworkTemplate buildTemplateProxy() {
- return new NetworkTemplate(MATCH_PROXY, null, null);
- }
-
- /**
- * Template to match all metered carrier networks with the given IMSI.
- */
- public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
- Objects.requireNonNull(subscriberId);
- return new NetworkTemplate(MATCH_CARRIER, subscriberId,
- new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_EXACT);
- }
-
- private final int mMatchRule;
- private final String mSubscriberId;
-
- /**
- * Ugh, templates are designed to target a single subscriber, but we might
- * need to match several "merged" subscribers. These are the subscribers
- * that should be considered to match this template.
- * <p>
- * Since the merge set is dynamic, it should <em>not</em> be persisted or
- * used for determining equality.
- */
- private final String[] mMatchSubscriberIds;
-
- 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;
- private final int mSubType;
- private final int mSubscriberIdMatchRule;
-
- // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
- private final int mOemManaged;
-
- private void checkValidSubscriberIdMatchRule() {
- switch (mMatchRule) {
- case MATCH_MOBILE:
- case MATCH_CARRIER:
- // MOBILE and CARRIER templates must always specify a subscriber ID.
- if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
- throw new IllegalArgumentException("Invalid SubscriberIdMatchRule"
- + "on match rule: " + getMatchRuleName(mMatchRule));
- }
- return;
- default:
- return;
- }
- }
-
- @UnsupportedAppUsage
- public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
- this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
- }
-
- public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId) {
- this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
- SUBSCRIBER_ID_MATCH_RULE_EXACT);
- }
-
- // TODO: Remove it after updating all of the caller.
- public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId, int metered, int roaming, int defaultNetwork, int subType,
- int oemManaged) {
- this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming,
- defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT);
- }
-
- public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId, int metered, int roaming, int defaultNetwork, int subType,
- int oemManaged, int subscriberIdMatchRule) {
- mMatchRule = matchRule;
- mSubscriberId = subscriberId;
- // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when
- // mSubscriberId is null
- mMatchSubscriberIds = matchSubscriberIds;
- mNetworkId = networkId;
- mMetered = metered;
- mRoaming = roaming;
- mDefaultNetwork = defaultNetwork;
- mSubType = subType;
- mOemManaged = oemManaged;
- mSubscriberIdMatchRule = subscriberIdMatchRule;
- checkValidSubscriberIdMatchRule();
- if (!isKnownMatchRule(matchRule)) {
- Log.e(TAG, "Unknown network template rule " + matchRule
- + " will not match any identity.");
- }
- }
-
- private NetworkTemplate(Parcel in) {
- mMatchRule = in.readInt();
- mSubscriberId = in.readString();
- mMatchSubscriberIds = in.createStringArray();
- mNetworkId = in.readString();
- mMetered = in.readInt();
- mRoaming = in.readInt();
- mDefaultNetwork = in.readInt();
- mSubType = in.readInt();
- mOemManaged = in.readInt();
- mSubscriberIdMatchRule = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mMatchRule);
- dest.writeString(mSubscriberId);
- dest.writeStringArray(mMatchSubscriberIds);
- dest.writeString(mNetworkId);
- dest.writeInt(mMetered);
- dest.writeInt(mRoaming);
- dest.writeInt(mDefaultNetwork);
- dest.writeInt(mSubType);
- dest.writeInt(mOemManaged);
- dest.writeInt(mSubscriberIdMatchRule);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
- builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
- if (mSubscriberId != null) {
- builder.append(", subscriberId=").append(
- NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
- }
- if (mMatchSubscriberIds != null) {
- builder.append(", matchSubscriberIds=").append(
- Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds)));
- }
- if (mNetworkId != null) {
- 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));
- }
- if (mSubType != NETWORK_TYPE_ALL) {
- builder.append(", subType=").append(mSubType);
- }
- if (mOemManaged != OEM_MANAGED_ALL) {
- builder.append(", oemManaged=").append(mOemManaged);
- }
- builder.append(", subscriberIdMatchRule=")
- .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule));
- return builder.toString();
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
- mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (obj instanceof NetworkTemplate) {
- final NetworkTemplate other = (NetworkTemplate) obj;
- return mMatchRule == other.mMatchRule
- && Objects.equals(mSubscriberId, other.mSubscriberId)
- && Objects.equals(mNetworkId, other.mNetworkId)
- && mMetered == other.mMetered
- && mRoaming == other.mRoaming
- && mDefaultNetwork == other.mDefaultNetwork
- && mSubType == other.mSubType
- && mOemManaged == other.mOemManaged
- && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule;
- }
- return false;
- }
-
- private String subscriberIdMatchRuleToString(int rule) {
- switch (rule) {
- case SUBSCRIBER_ID_MATCH_RULE_EXACT:
- return "EXACT_MATCH";
- case SUBSCRIBER_ID_MATCH_RULE_ALL:
- return "ALL";
- default:
- return "Unknown rule " + rule;
- }
- }
-
- public boolean isMatchRuleMobile() {
- switch (mMatchRule) {
- case MATCH_MOBILE:
- case MATCH_MOBILE_WILDCARD:
- return true;
- default:
- return false;
- }
- }
-
- public boolean isPersistable() {
- switch (mMatchRule) {
- case MATCH_MOBILE_WILDCARD:
- case MATCH_WIFI_WILDCARD:
- return false;
- case MATCH_CARRIER:
- return mSubscriberId != null;
- case MATCH_WIFI:
- if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
- && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
- return false;
- }
- return true;
- default:
- return true;
- }
- }
-
- @UnsupportedAppUsage
- public int getMatchRule() {
- return mMatchRule;
- }
-
- @UnsupportedAppUsage
- public String getSubscriberId() {
- return mSubscriberId;
- }
-
- public String getNetworkId() {
- return mNetworkId;
- }
-
- public int getSubscriberIdMatchRule() {
- return mSubscriberIdMatchRule;
- }
-
- public int getMeteredness() {
- return mMetered;
- }
-
- /**
- * Test if given {@link NetworkIdentity} matches this template.
- */
- public boolean matches(NetworkIdentity ident) {
- if (!matchesMetered(ident)) return false;
- if (!matchesRoaming(ident)) return false;
- if (!matchesDefaultNetwork(ident)) return false;
- if (!matchesOemNetwork(ident)) return false;
-
- switch (mMatchRule) {
- case MATCH_MOBILE:
- return matchesMobile(ident);
- case MATCH_WIFI:
- return matchesWifi(ident);
- case MATCH_ETHERNET:
- return matchesEthernet(ident);
- case MATCH_MOBILE_WILDCARD:
- return matchesMobileWildcard(ident);
- case MATCH_WIFI_WILDCARD:
- return matchesWifiWildcard(ident);
- case MATCH_BLUETOOTH:
- return matchesBluetooth(ident);
- case MATCH_PROXY:
- return matchesProxy(ident);
- case MATCH_CARRIER:
- return matchesCarrier(ident);
- default:
- // We have no idea what kind of network template we are, so we
- // just claim not to match anything.
- return false;
- }
- }
-
- 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);
- }
-
- private boolean matchesOemNetwork(NetworkIdentity ident) {
- return (mOemManaged == OEM_MANAGED_ALL)
- || (mOemManaged == OEM_MANAGED_YES
- && ident.mOemManaged != OEM_NONE)
- || (mOemManaged == ident.mOemManaged);
- }
-
- private boolean matchesCollapsedRatType(NetworkIdentity ident) {
- return mSubType == NETWORK_TYPE_ALL
- || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
- }
-
- /**
- * Check if this template matches {@code subscriberId}. Returns true if this
- * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a
- * {@code mMatchSubscriberIds} array that contains {@code subscriberId}.
- */
- public boolean matchesSubscriberId(@Nullable String subscriberId) {
- return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL
- || ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
- }
-
- /**
- * Check if network with matching SSID. Returns true when the SSID matches, or when
- * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}.
- */
- private boolean matchesWifiNetworkId(@Nullable String networkId) {
- return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
- || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId));
- }
-
- /**
- * Check if mobile network with matching IMSI.
- */
- private boolean matchesMobile(NetworkIdentity ident) {
- if (ident.mType == TYPE_WIMAX) {
- // TODO: consider matching against WiMAX subscriber identity
- return true;
- } else {
- // Only metered mobile network would be matched regardless of metered filter.
- // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
- // TODO: Respect metered filter and remove mMetered condition.
- return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
- && !ArrayUtils.isEmpty(mMatchSubscriberIds)
- && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
- && matchesCollapsedRatType(ident);
- }
- }
-
- /**
- * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
- * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
- *
- * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
- */
- // TODO: 1. Consider move this to TelephonyManager if used by other modules.
- // 2. Consider make this configurable.
- // 3. Use TelephonyManager APIs when available.
- public static int getCollapsedRatType(int ratType) {
- switch (ratType) {
- case TelephonyManager.NETWORK_TYPE_GPRS:
- case TelephonyManager.NETWORK_TYPE_GSM:
- case TelephonyManager.NETWORK_TYPE_EDGE:
- case TelephonyManager.NETWORK_TYPE_IDEN:
- case TelephonyManager.NETWORK_TYPE_CDMA:
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- return TelephonyManager.NETWORK_TYPE_GSM;
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- case TelephonyManager.NETWORK_TYPE_UMTS:
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
- return TelephonyManager.NETWORK_TYPE_UMTS;
- case TelephonyManager.NETWORK_TYPE_LTE:
- case TelephonyManager.NETWORK_TYPE_IWLAN:
- return TelephonyManager.NETWORK_TYPE_LTE;
- case TelephonyManager.NETWORK_TYPE_NR:
- return TelephonyManager.NETWORK_TYPE_NR;
- // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
- case NetworkTemplate.NETWORK_TYPE_5G_NSA:
- return NetworkTemplate.NETWORK_TYPE_5G_NSA;
- default:
- return TelephonyManager.NETWORK_TYPE_UNKNOWN;
- }
- }
-
- /**
- * Return all supported collapsed RAT types that could be returned by
- * {@link #getCollapsedRatType(int)}.
- */
- @NonNull
- public static final int[] getAllCollapsedRatTypes() {
- final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
- final HashSet<Integer> collapsedRatTypes = new HashSet<>();
- for (final int ratType : ratTypes) {
- collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
- }
- // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
- // it is not in TelephonyManager#NETWORK_TYPE_* constants.
- // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
- collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA));
- // Ensure that unknown type is returned.
- collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
- return toIntArray(collapsedRatTypes);
- }
-
- @NonNull
- private static int[] toIntArray(@NonNull Collection<Integer> list) {
- final int[] array = new int[list.size()];
- int i = 0;
- for (final Integer item : list) {
- array[i++] = item;
- }
- return array;
- }
-
- /**
- * Check if matches Wi-Fi network template.
- */
- private boolean matchesWifi(NetworkIdentity ident) {
- switch (ident.mType) {
- case TYPE_WIFI:
- return matchesSubscriberId(ident.mSubscriberId)
- && matchesWifiNetworkId(ident.mNetworkId);
- default:
- return false;
- }
- }
-
- /**
- * Check if matches Ethernet network template.
- */
- private boolean matchesEthernet(NetworkIdentity ident) {
- if (ident.mType == TYPE_ETHERNET) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if matches carrier network. The carrier networks means it includes the subscriberId.
- */
- private boolean matchesCarrier(NetworkIdentity ident) {
- return ident.mSubscriberId != null
- && !ArrayUtils.isEmpty(mMatchSubscriberIds)
- && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
- }
-
- private boolean matchesMobileWildcard(NetworkIdentity ident) {
- if (ident.mType == TYPE_WIMAX) {
- return true;
- } else {
- return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
- && matchesCollapsedRatType(ident);
- }
- }
-
- private boolean matchesWifiWildcard(NetworkIdentity ident) {
- switch (ident.mType) {
- case TYPE_WIFI:
- case TYPE_WIFI_P2P:
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Check if matches Bluetooth network template.
- */
- private boolean matchesBluetooth(NetworkIdentity ident) {
- if (ident.mType == TYPE_BLUETOOTH) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if matches Proxy network template.
- */
- private boolean matchesProxy(NetworkIdentity ident) {
- return ident.mType == TYPE_PROXY;
- }
-
- private static String getMatchRuleName(int matchRule) {
- switch (matchRule) {
- case MATCH_MOBILE:
- return "MOBILE";
- case MATCH_WIFI:
- return "WIFI";
- case MATCH_ETHERNET:
- return "ETHERNET";
- case MATCH_MOBILE_WILDCARD:
- return "MOBILE_WILDCARD";
- case MATCH_WIFI_WILDCARD:
- return "WIFI_WILDCARD";
- case MATCH_BLUETOOTH:
- return "BLUETOOTH";
- case MATCH_PROXY:
- return "PROXY";
- case MATCH_CARRIER:
- return "CARRIER";
- default:
- return "UNKNOWN(" + matchRule + ")";
- }
- }
-
- /**
- * Examine the given template and normalize it.
- * We pick the "lowest" merged subscriber as the primary
- * for key purposes, and expand the template to match all other merged
- * subscribers.
- * <p>
- * For example, given an incoming template matching B, and the currently
- * active merge set [A,B], we'd return a new template that primarily matches
- * A, but also matches B.
- * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
- */
- @UnsupportedAppUsage
- public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
- return normalize(template, Arrays.<String[]>asList(merged));
- }
-
- /**
- * Examine the given template and normalize it.
- * We pick the "lowest" merged subscriber as the primary
- * for key purposes, and expand the template to match all other merged
- * subscribers.
- *
- * There can be multiple merged subscriberIds for multi-SIM devices.
- *
- * <p>
- * For example, given an incoming template matching B, and the currently
- * active merge set [A,B], we'd return a new template that primarily matches
- * A, but also matches B.
- */
- public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
- // Now there are several types of network which uses SubscriberId to store network
- // information. For instances:
- // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
- // The TYPE_CARRIER means that the network associate to specific carrier network.
-
- if (template.mSubscriberId == null) return template;
-
- for (String[] merged : mergedList) {
- if (ArrayUtils.contains(merged, template.mSubscriberId)) {
- // Requested template subscriber is part of the merge group; return
- // a template that matches all merged subscribers.
- return new NetworkTemplate(template.mMatchRule, merged[0], merged,
- template.mNetworkId);
- }
- }
-
- return template;
- }
-
- @UnsupportedAppUsage
- public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
- @Override
- public NetworkTemplate createFromParcel(Parcel in) {
- return new NetworkTemplate(in);
- }
-
- @Override
- public NetworkTemplate[] newArray(int size) {
- return new NetworkTemplate[size];
- }
- };
-
- public byte[] getBytesForBackup() throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- DataOutputStream out = new DataOutputStream(baos);
-
- out.writeInt(BACKUP_VERSION);
-
- out.writeInt(mMatchRule);
- BackupUtils.writeString(out, mSubscriberId);
- BackupUtils.writeString(out, mNetworkId);
-
- return baos.toByteArray();
- }
-
- public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
- throws IOException, BackupUtils.BadVersionException {
- int version = in.readInt();
- if (version < 1 || version > BACKUP_VERSION) {
- throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
- }
-
- int matchRule = in.readInt();
- String subscriberId = BackupUtils.readString(in);
- String networkId = BackupUtils.readString(in);
-
- if (!isKnownMatchRule(matchRule)) {
- throw new BackupUtils.BadVersionException(
- "Restored network template contains unknown match rule " + matchRule);
- }
-
- return new NetworkTemplate(matchRule, subscriberId, networkId);
- }
-}
diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp
new file mode 100644
index 0000000..0bda923
--- /dev/null
+++ b/framework-t/Sources.bp
@@ -0,0 +1,157 @@
+//
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// NetworkStats related libraries.
+
+filegroup {
+ name: "framework-connectivity-netstats-internal-sources",
+ srcs: [
+ "src/android/app/usage/*.java",
+ "src/android/net/DataUsage*.*",
+ "src/android/net/INetworkStats*.*",
+ "src/android/net/NetworkIdentity*.java",
+ "src/android/net/NetworkStateSnapshot.*",
+ "src/android/net/NetworkStats*.*",
+ "src/android/net/NetworkTemplate.*",
+ "src/android/net/TrafficStats.java",
+ "src/android/net/UnderlyingNetworkInfo.*",
+ "src/android/net/netstats/**/*.*",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+filegroup {
+ name: "framework-connectivity-netstats-aidl-export-sources",
+ srcs: [
+ "aidl-export/android/net/NetworkStats.aidl",
+ "aidl-export/android/net/NetworkTemplate.aidl",
+ ],
+ path: "aidl-export",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+filegroup {
+ name: "framework-connectivity-netstats-sources",
+ srcs: [
+ ":framework-connectivity-netstats-internal-sources",
+ ":framework-connectivity-netstats-aidl-export-sources",
+ ],
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// Nsd related libraries.
+
+filegroup {
+ name: "framework-connectivity-nsd-internal-sources",
+ srcs: [
+ "src/android/net/nsd/*.aidl",
+ "src/android/net/nsd/*.java",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+filegroup {
+ name: "framework-connectivity-nsd-aidl-export-sources",
+ srcs: [
+ "aidl-export/android/net/nsd/*.aidl",
+ ],
+ path: "aidl-export",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+filegroup {
+ name: "framework-connectivity-nsd-sources",
+ srcs: [
+ ":framework-connectivity-nsd-internal-sources",
+ ":framework-connectivity-nsd-aidl-export-sources",
+ ],
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// IpSec related libraries.
+
+filegroup {
+ name: "framework-connectivity-ipsec-sources",
+ srcs: [
+ "src/android/net/IIpSecService.aidl",
+ "src/android/net/IpSec*.*",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// Ethernet related libraries.
+
+filegroup {
+ name: "framework-connectivity-ethernet-sources",
+ srcs: [
+ "src/android/net/EthernetManager.java",
+ "src/android/net/EthernetNetworkSpecifier.java",
+ "src/android/net/IEthernetManager.aidl",
+ "src/android/net/IEthernetServiceListener.aidl",
+ "src/android/net/ITetheredInterfaceCallback.aidl",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// Connectivity-T common libraries.
+
+filegroup {
+ name: "framework-connectivity-tiramisu-internal-sources",
+ srcs: [
+ "src/android/net/ConnectivityFrameworkInitializerTiramisu.java",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+filegroup {
+ name: "framework-connectivity-tiramisu-sources",
+ srcs: [
+ ":framework-connectivity-ethernet-sources",
+ ":framework-connectivity-ipsec-sources",
+ ":framework-connectivity-netstats-sources",
+ ":framework-connectivity-nsd-sources",
+ ":framework-connectivity-tiramisu-internal-sources",
+ ],
+ visibility: ["//frameworks/base"],
+}
diff --git a/core/java/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java
similarity index 98%
rename from core/java/android/app/usage/NetworkStats.java
rename to framework-t/src/android/app/usage/NetworkStats.java
index 216a4a0..f684a4d 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/framework-t/src/android/app/usage/NetworkStats.java
@@ -24,13 +24,15 @@
import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.RemoteException;
-import android.util.IntArray;
import android.util.Log;
+import com.android.net.module.util.CollectionUtils;
+
import dalvik.system.CloseGuard;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
/**
* Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
@@ -568,7 +570,7 @@
// the filtering logic below can be removed.
int[] uids = mSession.getRelevantUids();
// Filtering of uids with empty history.
- IntArray filteredUids = new IntArray(uids.length);
+ final ArrayList<Integer> filteredUids = new ArrayList<>();
for (int uid : uids) {
try {
NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
@@ -581,7 +583,7 @@
Log.w(TAG, "Error while getting history of uid " + uid, e);
}
}
- mUids = filteredUids.toArray();
+ mUids = CollectionUtils.toIntArray(filteredUids);
mUidOrUidIndex = -1;
stepHistory();
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
similarity index 91%
rename from core/java/android/app/usage/NetworkStatsManager.java
rename to framework-t/src/android/app/usage/NetworkStatsManager.java
index 8a6c85d..a316b8a 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -45,11 +45,8 @@
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.DataUnit;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -121,7 +118,7 @@
* is reached.
* @hide
*/
- public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
+ public static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
private final Context mContext;
private final INetworkStatsService mService;
@@ -135,21 +132,13 @@
private int mFlags;
- /**
- * {@hide}
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public NetworkStatsManager(Context context) throws ServiceNotFoundException {
- this(context, INetworkStatsService.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
- }
-
/** @hide */
@VisibleForTesting
public NetworkStatsManager(Context context, INetworkStatsService service) {
mContext = context;
mService = service;
setPollOnOpen(true);
+ setAugmentWithSubscriptionPlan(true);
}
/** @hide */
@@ -181,16 +170,44 @@
}
}
- /** @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,
- mService);
- bucket = stats.getDeviceSummaryForNetwork();
-
- stats.close();
- return bucket;
+ /**
+ * 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
+ * roaming. This means the bucket's start and end timestamp will be the same as the
+ * 'startTime' and 'endTime' arguments. State is going to be
+ * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
+ * tag {@link NetworkStats.Bucket#TAG_NONE},
+ * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
+ * metered {@link NetworkStats.Bucket#METERED_ALL},
+ * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @return Bucket Summarised data usage.
+ *
+ * @hide
+ */
+ @NonNull
+ @WorkerThread
+ // @SystemApi(client = MODULE_LIBRARIES)
+ public Bucket querySummaryForDevice(@NonNull NetworkTemplate template,
+ long startTime, long endTime) {
+ try {
+ NetworkStats stats =
+ new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+ Bucket bucket = stats.getDeviceSummaryForNetwork();
+ stats.close();
+ return bucket;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return null; // To make the compiler happy.
}
/**
@@ -334,14 +351,37 @@
return querySummary(template, startTime, endTime);
}
- /** @hide */
- public NetworkStats querySummary(NetworkTemplate template, long startTime,
- long endTime) throws SecurityException, RemoteException {
- NetworkStats result;
- result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startSummaryEnumeration();
-
- return result;
+ /**
+ * Query network usage statistics summaries.
+ *
+ * The results will only include traffic made by UIDs belonging to the calling user profile.
+ * The results are aggregated over time, so that all buckets will have the same start and
+ * end timestamps as the passed arguments. Not aggregated over state, uid, default network,
+ * metered, or roaming.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @return Statistics which is described above.
+ * @hide
+ */
+ @Nullable
+ // @SystemApi(client = MODULE_LIBRARIES)
+ @WorkerThread
+ public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
+ long endTime) throws SecurityException {
+ try {
+ NetworkStats result =
+ new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+ result.startSummaryEnumeration();
+ return result;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return null; // To make the compiler happy.
}
/**
diff --git a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
new file mode 100644
index 0000000..630f902
--- /dev/null
+++ b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 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.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
+
+/**
+ * Class for performing registration for Connectivity services which are exposed via updatable APIs
+ * since Android T.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class ConnectivityFrameworkInitializerTiramisu {
+ private ConnectivityFrameworkInitializerTiramisu() {}
+
+ /**
+ * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to
+ * {@link Context}, so that {@link Context#getSystemService} can return them.
+ *
+ * @throws IllegalStateException if this is called anywhere besides
+ * {@link SystemServiceRegistry}.
+ */
+ public static void registerServiceWrappers() {
+ SystemServiceRegistry.registerContextAwareService(
+ Context.NSD_SERVICE,
+ NsdManager.class,
+ (context, serviceBinder) -> {
+ INsdManager service = INsdManager.Stub.asInterface(serviceBinder);
+ return new NsdManager(context, service);
+ }
+ );
+ }
+}
diff --git a/core/java/android/net/DataUsageRequest.aidl b/framework-t/src/android/net/DataUsageRequest.aidl
similarity index 100%
rename from core/java/android/net/DataUsageRequest.aidl
rename to framework-t/src/android/net/DataUsageRequest.aidl
diff --git a/core/java/android/net/DataUsageRequest.java b/framework-t/src/android/net/DataUsageRequest.java
similarity index 100%
rename from core/java/android/net/DataUsageRequest.java
rename to framework-t/src/android/net/DataUsageRequest.java
diff --git a/core/java/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java
similarity index 76%
rename from core/java/android/net/EthernetManager.java
rename to framework-t/src/android/net/EthernetManager.java
index 7cd63ef..ece54df 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/framework-t/src/android/net/EthernetManager.java
@@ -16,7 +16,9 @@
package android.net;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -32,6 +34,7 @@
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
/**
* A class representing the IP configuration of the Ethernet network.
@@ -315,4 +318,83 @@
}
return new TetheredInterfaceRequest(mService, cbInternal);
}
+
+ private static final class InternalNetworkManagementListener
+ extends IInternalNetworkManagementListener.Stub {
+ @NonNull
+ private final Executor mExecutor;
+ @NonNull
+ private final BiConsumer<Network, InternalNetworkManagementException> mListener;
+
+ InternalNetworkManagementListener(
+ @NonNull final Executor executor,
+ @NonNull final BiConsumer<Network, InternalNetworkManagementException> listener) {
+ Objects.requireNonNull(executor, "Pass a non-null executor");
+ Objects.requireNonNull(listener, "Pass a non-null listener");
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onComplete(
+ @Nullable final Network network,
+ @Nullable final InternalNetworkManagementException e) {
+ mExecutor.execute(() -> mListener.accept(network, e));
+ }
+ }
+
+ private InternalNetworkManagementListener getInternalNetworkManagementListener(
+ @Nullable final Executor executor,
+ @Nullable final BiConsumer<Network, InternalNetworkManagementException> listener) {
+ if (null != listener) {
+ Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
+ }
+ final InternalNetworkManagementListener proxy;
+ if (null == listener) {
+ proxy = null;
+ } else {
+ proxy = new InternalNetworkManagementListener(executor, listener);
+ }
+ return proxy;
+ }
+
+ private void updateConfiguration(
+ @NonNull String iface,
+ @NonNull InternalNetworkUpdateRequest request,
+ @Nullable @CallbackExecutor Executor executor,
+ @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+ final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
+ executor, listener);
+ try {
+ mService.updateConfiguration(iface, request, proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private void connectNetwork(
+ @NonNull String iface,
+ @Nullable @CallbackExecutor Executor executor,
+ @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+ final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
+ executor, listener);
+ try {
+ mService.connectNetwork(iface, proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private void disconnectNetwork(
+ @NonNull String iface,
+ @Nullable @CallbackExecutor Executor executor,
+ @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+ final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
+ executor, listener);
+ try {
+ mService.disconnectNetwork(iface, proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java
similarity index 100%
rename from core/java/android/net/EthernetNetworkSpecifier.java
rename to framework-t/src/android/net/EthernetNetworkSpecifier.java
diff --git a/core/java/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl
similarity index 77%
rename from core/java/android/net/IEthernetManager.aidl
rename to framework-t/src/android/net/IEthernetManager.aidl
index e058e5a..e688bea 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/framework-t/src/android/net/IEthernetManager.aidl
@@ -18,6 +18,8 @@
import android.net.IpConfiguration;
import android.net.IEthernetServiceListener;
+import android.net.IInternalNetworkManagementListener;
+import android.net.InternalNetworkUpdateRequest;
import android.net.ITetheredInterfaceCallback;
/**
@@ -36,4 +38,8 @@
void setIncludeTestInterfaces(boolean include);
void requestTetheredInterface(in ITetheredInterfaceCallback callback);
void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
+ void updateConfiguration(String iface, in InternalNetworkUpdateRequest request,
+ in IInternalNetworkManagementListener listener);
+ void connectNetwork(String iface, in IInternalNetworkManagementListener listener);
+ void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener);
}
diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/framework-t/src/android/net/IEthernetServiceListener.aidl
similarity index 100%
rename from core/java/android/net/IEthernetServiceListener.aidl
rename to framework-t/src/android/net/IEthernetServiceListener.aidl
diff --git a/core/java/android/net/IIpSecService.aidl b/framework-t/src/android/net/IIpSecService.aidl
similarity index 100%
rename from core/java/android/net/IIpSecService.aidl
rename to framework-t/src/android/net/IIpSecService.aidl
diff --git a/core/java/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl
similarity index 100%
rename from core/java/android/net/INetworkStatsService.aidl
rename to framework-t/src/android/net/INetworkStatsService.aidl
diff --git a/core/java/android/net/INetworkStatsSession.aidl b/framework-t/src/android/net/INetworkStatsSession.aidl
similarity index 80%
rename from core/java/android/net/INetworkStatsSession.aidl
rename to framework-t/src/android/net/INetworkStatsSession.aidl
index f13f2cb..dfedf66 100644
--- a/core/java/android/net/INetworkStatsSession.aidl
+++ b/framework-t/src/android/net/INetworkStatsSession.aidl
@@ -33,7 +33,17 @@
@UnsupportedAppUsage
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
- /** Return network layer usage summary per UID for traffic that matches template. */
+ /**
+ * Return network layer usage summary per UID for traffic that matches template.
+ *
+ * <p>The resulting {@code NetworkStats#getElapsedRealtime()} contains time delta between
+ * {@code start} and {@code end}.
+ *
+ * @param template - a predicate to filter netstats.
+ * @param start - start of the range, timestamp in milliseconds since the epoch.
+ * @param end - end of the range, timestamp in milliseconds since the epoch.
+ * @param includeTags - includes data usage tags if true.
+ */
@UnsupportedAppUsage
NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
/** Return historical network layer stats for specific UID traffic that matches template. */
diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
similarity index 100%
rename from core/java/android/net/ITetheredInterfaceCallback.aidl
rename to framework-t/src/android/net/ITetheredInterfaceCallback.aidl
diff --git a/core/java/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java
similarity index 96%
rename from core/java/android/net/IpSecAlgorithm.java
rename to framework-t/src/android/net/IpSecAlgorithm.java
index 7ef5bac..a84e7a9 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/framework-t/src/android/net/IpSecAlgorithm.java
@@ -23,7 +23,6 @@
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.HexDump;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -232,11 +231,10 @@
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO);
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO);
- // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined
- ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S);
}
private static final Set<String> ENABLED_ALGOS =
@@ -298,7 +296,7 @@
return mTruncLenBits;
}
- /* Parcelable Implementation */
+ /** Parcelable Implementation */
public int describeContents() {
return 0;
}
@@ -470,20 +468,12 @@
}
}
- // Because encryption keys are sensitive and userdebug builds are used by large user pools
- // such as beta testers, we only allow sensitive info such as keys on eng builds.
- private static boolean isUnsafeBuild() {
- return Build.IS_DEBUGGABLE && Build.IS_ENG;
- }
-
@Override
@NonNull
public String toString() {
return new StringBuilder()
.append("{mName=")
.append(mName)
- .append(", mKey=")
- .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>")
.append(", mTruncLenBits=")
.append(mTruncLenBits)
.append("}")
diff --git a/core/java/android/net/IpSecConfig.aidl b/framework-t/src/android/net/IpSecConfig.aidl
similarity index 100%
rename from core/java/android/net/IpSecConfig.aidl
rename to framework-t/src/android/net/IpSecConfig.aidl
diff --git a/core/java/android/net/IpSecConfig.java b/framework-t/src/android/net/IpSecConfig.java
similarity index 100%
rename from core/java/android/net/IpSecConfig.java
rename to framework-t/src/android/net/IpSecConfig.java
diff --git a/core/java/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java
similarity index 98%
rename from core/java/android/net/IpSecManager.java
rename to framework-t/src/android/net/IpSecManager.java
index c106807..0d15dff 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/framework-t/src/android/net/IpSecManager.java
@@ -17,8 +17,6 @@
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -46,6 +44,7 @@
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
+import java.util.Objects;
/**
* This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
@@ -86,6 +85,7 @@
*
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public static final int DIRECTION_FWD = 2;
/**
@@ -99,9 +99,9 @@
/** @hide */
public interface Status {
- public static final int OK = 0;
- public static final int RESOURCE_UNAVAILABLE = 1;
- public static final int SPI_UNAVAILABLE = 2;
+ int OK = 0;
+ int RESOURCE_UNAVAILABLE = 1;
+ int SPI_UNAVAILABLE = 2;
}
/** @hide */
@@ -276,7 +276,7 @@
* @param destinationAddress the destination address for traffic bearing the requested SPI.
* For inbound traffic, the destination should be an address currently assigned on-device.
* @return the reserved SecurityParameterIndex
- * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+ * @throws ResourceUnavailableException indicating that too many SPIs are
* currently allocated for this user
*/
@NonNull
@@ -307,9 +307,9 @@
* @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See
* RFC 4303 Section 2.1.
* @return the reserved SecurityParameterIndex
- * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+ * @throws ResourceUnavailableException indicating that too many SPIs are
* currently allocated for this user
- * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
+ * @throws SpiUnavailableException indicating that the requested SPI could not be
* reserved
*/
@NonNull
@@ -988,7 +988,7 @@
*/
public IpSecManager(Context ctx, IIpSecService service) {
mContext = ctx;
- mService = checkNotNull(service, "missing service");
+ mService = Objects.requireNonNull(service, "missing service");
}
private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) {
diff --git a/core/java/android/net/IpSecSpiResponse.aidl b/framework-t/src/android/net/IpSecSpiResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecSpiResponse.aidl
rename to framework-t/src/android/net/IpSecSpiResponse.aidl
diff --git a/core/java/android/net/IpSecSpiResponse.java b/framework-t/src/android/net/IpSecSpiResponse.java
similarity index 100%
rename from core/java/android/net/IpSecSpiResponse.java
rename to framework-t/src/android/net/IpSecSpiResponse.java
diff --git a/core/java/android/net/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java
similarity index 96%
rename from core/java/android/net/IpSecTransform.java
rename to framework-t/src/android/net/IpSecTransform.java
index b48c1fd..36199a0 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/framework-t/src/android/net/IpSecTransform.java
@@ -33,7 +33,6 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
@@ -41,6 +40,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
+import java.util.Objects;
/**
* This class represents a transform, which roughly corresponds to an IPsec Security Association.
@@ -255,7 +255,7 @@
@NonNull
public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
- Preconditions.checkNotNull(algo);
+ Objects.requireNonNull(algo);
mConfig.setEncryption(algo);
return this;
}
@@ -270,7 +270,7 @@
@NonNull
public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
- Preconditions.checkNotNull(algo);
+ Objects.requireNonNull(algo);
mConfig.setAuthentication(algo);
return this;
}
@@ -290,7 +290,7 @@
*/
@NonNull
public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
- Preconditions.checkNotNull(algo);
+ Objects.requireNonNull(algo);
mConfig.setAuthenticatedEncryption(algo);
return this;
}
@@ -311,7 +311,7 @@
@NonNull
public IpSecTransform.Builder setIpv4Encapsulation(
@NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
- Preconditions.checkNotNull(localSocket);
+ Objects.requireNonNull(localSocket);
mConfig.setEncapType(ENCAP_ESPINUDP);
if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
@@ -348,8 +348,8 @@
@NonNull IpSecManager.SecurityParameterIndex spi)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- Preconditions.checkNotNull(sourceAddress);
- Preconditions.checkNotNull(spi);
+ Objects.requireNonNull(sourceAddress);
+ Objects.requireNonNull(spi);
if (spi.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid SecurityParameterIndex");
}
@@ -387,8 +387,8 @@
@NonNull IpSecManager.SecurityParameterIndex spi)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- Preconditions.checkNotNull(sourceAddress);
- Preconditions.checkNotNull(spi);
+ Objects.requireNonNull(sourceAddress);
+ Objects.requireNonNull(spi);
if (spi.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid SecurityParameterIndex");
}
@@ -404,7 +404,7 @@
* @param context current context
*/
public Builder(@NonNull Context context) {
- Preconditions.checkNotNull(context);
+ Objects.requireNonNull(context);
mContext = context;
mConfig = new IpSecConfig();
}
diff --git a/core/java/android/net/IpSecTransformResponse.aidl b/framework-t/src/android/net/IpSecTransformResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecTransformResponse.aidl
rename to framework-t/src/android/net/IpSecTransformResponse.aidl
diff --git a/core/java/android/net/IpSecTransformResponse.java b/framework-t/src/android/net/IpSecTransformResponse.java
similarity index 95%
rename from core/java/android/net/IpSecTransformResponse.java
rename to framework-t/src/android/net/IpSecTransformResponse.java
index a384889..363f316 100644
--- a/core/java/android/net/IpSecTransformResponse.java
+++ b/framework-t/src/android/net/IpSecTransformResponse.java
@@ -60,7 +60,8 @@
resourceId = in.readInt();
}
- public static final @android.annotation.NonNull Parcelable.Creator<IpSecTransformResponse> CREATOR =
+ @android.annotation.NonNull
+ public static final Parcelable.Creator<IpSecTransformResponse> CREATOR =
new Parcelable.Creator<IpSecTransformResponse>() {
public IpSecTransformResponse createFromParcel(Parcel in) {
return new IpSecTransformResponse(in);
diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.aidl b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecTunnelInterfaceResponse.aidl
rename to framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
similarity index 95%
rename from core/java/android/net/IpSecTunnelInterfaceResponse.java
rename to framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
index e3411e0..127e30a 100644
--- a/core/java/android/net/IpSecTunnelInterfaceResponse.java
+++ b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
@@ -65,7 +65,8 @@
interfaceName = in.readString();
}
- public static final @android.annotation.NonNull Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
+ @android.annotation.NonNull
+ public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
return new IpSecTunnelInterfaceResponse(in);
diff --git a/core/java/android/net/IpSecUdpEncapResponse.aidl b/framework-t/src/android/net/IpSecUdpEncapResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecUdpEncapResponse.aidl
rename to framework-t/src/android/net/IpSecUdpEncapResponse.aidl
diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/framework-t/src/android/net/IpSecUdpEncapResponse.java
similarity index 96%
rename from core/java/android/net/IpSecUdpEncapResponse.java
rename to framework-t/src/android/net/IpSecUdpEncapResponse.java
index 4e7ba9b..732cf19 100644
--- a/core/java/android/net/IpSecUdpEncapResponse.java
+++ b/framework-t/src/android/net/IpSecUdpEncapResponse.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+
import java.io.FileDescriptor;
import java.io.IOException;
@@ -83,7 +84,8 @@
fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
}
- public static final @android.annotation.NonNull Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
+ @android.annotation.NonNull
+ public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
new Parcelable.Creator<IpSecUdpEncapResponse>() {
public IpSecUdpEncapResponse createFromParcel(Parcel in) {
return new IpSecUdpEncapResponse(in);
diff --git a/core/java/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java
similarity index 82%
rename from core/java/android/net/NetworkIdentity.java
rename to framework-t/src/android/net/NetworkIdentity.java
index 3bde6fa..8f1115e 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/framework-t/src/android/net/NetworkIdentity.java
@@ -21,13 +21,14 @@
import android.annotation.Nullable;
import android.content.Context;
import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
import android.service.NetworkIdentityProto;
import android.telephony.Annotation.NetworkType;
import android.util.proto.ProtoOutputStream;
+import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.NetworkIdentityUtils;
+import java.util.ArrayList;
import java.util.Objects;
/**
@@ -121,11 +122,37 @@
}
builder.append(", metered=").append(mMetered);
builder.append(", defaultNetwork=").append(mDefaultNetwork);
- // TODO(180557699): Print a human readable string for OEM managed state.
- builder.append(", oemManaged=").append(mOemManaged);
+ builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
return builder.append("}").toString();
}
+ /**
+ * Get the human readable representation of a bitfield representing the OEM managed state of a
+ * network.
+ */
+ static String getOemManagedNames(int oemManaged) {
+ if (oemManaged == OEM_NONE) {
+ return "OEM_NONE";
+ }
+ final int[] bitPositions = NetworkCapabilitiesUtils.unpackBits(oemManaged);
+ final ArrayList<String> oemManagedNames = new ArrayList<String>();
+ for (int position : bitPositions) {
+ oemManagedNames.add(nameOfOemManaged(1 << position));
+ }
+ return String.join(",", oemManagedNames);
+ }
+
+ private static String nameOfOemManaged(int oemManagedBit) {
+ switch (oemManagedBit) {
+ case OEM_PAID:
+ return "OEM_PAID";
+ case OEM_PRIVATE:
+ return "OEM_PRIVATE";
+ default:
+ return "Invalid(" + oemManagedBit + ")";
+ }
+ }
+
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
@@ -192,17 +219,19 @@
String networkId = null;
boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
- boolean metered = !snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ boolean metered = !(snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ || snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
if (legacyType == TYPE_WIFI) {
- networkId = snapshot.getNetworkCapabilities().getSsid();
- if (networkId == null) {
- final WifiManager wifi = context.getSystemService(WifiManager.class);
- final WifiInfo info = wifi.getConnectionInfo();
- networkId = info != null ? info.getSSID() : null;
+ final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+ .getTransportInfo();
+ if (transportInfo instanceof WifiInfo) {
+ final WifiInfo info = (WifiInfo) transportInfo;
+ networkId = info != null ? info.getCurrentNetworkKey() : null;
}
}
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java
similarity index 96%
rename from services/core/java/com/android/server/net/NetworkIdentitySet.java
rename to framework-t/src/android/net/NetworkIdentitySet.java
index 22ed781..abbebef 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/framework-t/src/android/net/NetworkIdentitySet.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package com.android.server.net;
+package android.net;
-import android.net.NetworkIdentity;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+
import android.service.NetworkIdentitySetProto;
import android.util.proto.ProtoOutputStream;
@@ -25,8 +26,6 @@
import java.io.IOException;
import java.util.HashSet;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-
/**
* Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
* active on that interface.
@@ -97,6 +96,9 @@
}
}
+ /**
+ * Method to serialize this object into a {@code DataOutput}.
+ */
public void writeToStream(DataOutput out) throws IOException {
out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
out.writeInt(size());
@@ -179,6 +181,9 @@
return ident.compareTo(anotherIdent);
}
+ /**
+ * Method to dump this object into proto debug file.
+ */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
diff --git a/core/java/android/net/NetworkStateSnapshot.java b/framework-t/src/android/net/NetworkStateSnapshot.java
similarity index 100%
rename from core/java/android/net/NetworkStateSnapshot.java
rename to framework-t/src/android/net/NetworkStateSnapshot.java
diff --git a/core/java/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
similarity index 95%
rename from core/java/android/net/NetworkStats.java
rename to framework-t/src/android/net/NetworkStats.java
index 288b06e..b00fea4 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -16,6 +16,8 @@
package android.net;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -29,7 +31,7 @@
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
+import com.android.net.module.util.CollectionUtils;
import libcore.util.EmptyArray;
@@ -81,10 +83,7 @@
*/
// TODO: Rename TAG_ALL to TAG_ANY.
public static final int TAG_ALL = -1;
- /**
- * {@link #set} value for all sets combined, not including debug sets.
- * @hide
- */
+ /** {@link #set} value for all sets combined, not including debug sets. */
public static final int SET_ALL = -1;
/** {@link #set} value where background data is accounted. */
public static final int SET_DEFAULT = 0;
@@ -112,9 +111,6 @@
SET_ALL,
SET_DEFAULT,
SET_FOREGROUND,
- SET_DEBUG_START,
- SET_DBG_VPN_IN,
- SET_DBG_VPN_OUT
})
public @interface State {
}
@@ -129,10 +125,7 @@
// TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
- /**
- * {@link #metered} value to account for all metered states.
- * @hide
- */
+ /** {@link #metered} value to account for all metered states. */
public static final int METERED_ALL = -1;
/** {@link #metered} value where native, unmetered data is accounted. */
public static final int METERED_NO = 0;
@@ -150,10 +143,7 @@
}
- /**
- * {@link #roaming} value to account for all roaming states.
- * @hide
- */
+ /** {@link #roaming} value to account for all roaming states. */
public static final int ROAMING_ALL = -1;
/** {@link #roaming} value where native, non-roaming data is accounted. */
public static final int ROAMING_NO = 0;
@@ -170,10 +160,7 @@
public @interface Roaming {
}
- /**
- * {@link #onDefaultNetwork} value to account for all default network states.
- * @hide
- */
+ /** {@link #onDefaultNetwork} value to account for all default network states. */
public static final int DEFAULT_NETWORK_ALL = -1;
/** {@link #onDefaultNetwork} value to account for usage while not the default network. */
public static final int DEFAULT_NETWORK_NO = 0;
@@ -218,8 +205,10 @@
// TODO: move fields to "mVariable" notation
/**
- * {@link SystemClock#elapsedRealtime()} timestamp when this data was
+ * {@link SystemClock#elapsedRealtime()} timestamp in milliseconds when this data was
* generated.
+ * It's a timestamps delta when {@link #subtract()},
+ * {@code INetworkStatsSession#getSummaryForAllUid()} methods are used.
*/
private long elapsedRealtime;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -1181,7 +1170,7 @@
* @hide
*/
public void removeUids(int[] uids) {
- filter(e -> !ArrayUtils.contains(uids, e.uid));
+ filter(e -> !CollectionUtils.contains(uids, e.uid));
}
/**
@@ -1214,7 +1203,7 @@
filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
&& (limitTag == TAG_ALL || limitTag == e.tag)
&& (limitIfaces == INTERFACES_ALL
- || ArrayUtils.contains(limitIfaces, e.iface)));
+ || CollectionUtils.contains(limitIfaces, e.iface)));
}
/**
@@ -1581,32 +1570,37 @@
// processes this every time device has transmitted/received amount equivalent to
// global threshold alert (~ 2MB) across all interfaces.
final long rxBytesAcrossUnderlyingIfaces =
- underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+ multiplySafeByRational(underlyingIfacesTotal.rxBytes,
+ rxBytes[i], tunIfaceTotal.rxBytes);
// app must not be blamed for more than it consumed on tunIface
totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
}
long totalRxPackets = 0;
if (tunIfaceTotal.rxPackets > 0) {
final long rxPacketsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+ multiplySafeByRational(underlyingIfacesTotal.rxPackets,
+ rxPackets[i], tunIfaceTotal.rxPackets);
totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
}
long totalTxBytes = 0;
if (tunIfaceTotal.txBytes > 0) {
final long txBytesAcrossUnderlyingIfaces =
- underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+ multiplySafeByRational(underlyingIfacesTotal.txBytes,
+ txBytes[i], tunIfaceTotal.txBytes);
totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
}
long totalTxPackets = 0;
if (tunIfaceTotal.txPackets > 0) {
final long txPacketsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+ multiplySafeByRational(underlyingIfacesTotal.txPackets,
+ txPackets[i], tunIfaceTotal.txPackets);
totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
}
long totalOperations = 0;
if (tunIfaceTotal.operations > 0) {
final long operationsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
+ multiplySafeByRational(underlyingIfacesTotal.operations,
+ operations[i], tunIfaceTotal.operations);
totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
}
// In a second pass, distribute these values across interfaces in the proportion that
@@ -1618,37 +1612,37 @@
tmpEntry.set = set[i];
if (underlyingIfacesTotal.rxBytes > 0) {
tmpEntry.rxBytes =
- totalRxBytes
- * perInterfaceTotal[j].rxBytes
- / underlyingIfacesTotal.rxBytes;
+ multiplySafeByRational(totalRxBytes,
+ perInterfaceTotal[j].rxBytes,
+ underlyingIfacesTotal.rxBytes);
}
tmpEntry.rxPackets = 0;
if (underlyingIfacesTotal.rxPackets > 0) {
tmpEntry.rxPackets =
- totalRxPackets
- * perInterfaceTotal[j].rxPackets
- / underlyingIfacesTotal.rxPackets;
+ multiplySafeByRational(totalRxPackets,
+ perInterfaceTotal[j].rxPackets,
+ underlyingIfacesTotal.rxPackets);
}
tmpEntry.txBytes = 0;
if (underlyingIfacesTotal.txBytes > 0) {
tmpEntry.txBytes =
- totalTxBytes
- * perInterfaceTotal[j].txBytes
- / underlyingIfacesTotal.txBytes;
+ multiplySafeByRational(totalTxBytes,
+ perInterfaceTotal[j].txBytes,
+ underlyingIfacesTotal.txBytes);
}
tmpEntry.txPackets = 0;
if (underlyingIfacesTotal.txPackets > 0) {
tmpEntry.txPackets =
- totalTxPackets
- * perInterfaceTotal[j].txPackets
- / underlyingIfacesTotal.txPackets;
+ multiplySafeByRational(totalTxPackets,
+ perInterfaceTotal[j].txPackets,
+ underlyingIfacesTotal.txPackets);
}
tmpEntry.operations = 0;
if (underlyingIfacesTotal.operations > 0) {
tmpEntry.operations =
- totalOperations
- * perInterfaceTotal[j].operations
- / underlyingIfacesTotal.operations;
+ multiplySafeByRational(totalOperations,
+ perInterfaceTotal[j].operations,
+ underlyingIfacesTotal.operations);
}
// tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
// interface. Add that data usage to this object.
diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java
similarity index 83%
rename from services/core/java/com/android/server/net/NetworkStatsAccess.java
rename to framework-t/src/android/net/NetworkStatsAccess.java
index d25eae4..b64fbdb 100644
--- a/services/core/java/com/android/server/net/NetworkStatsAccess.java
+++ b/framework-t/src/android/net/NetworkStatsAccess.java
@@ -11,12 +11,13 @@
* 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
+ * limitations under the License.
*/
-package com.android.server.net;
+package android.net;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
@@ -24,7 +25,7 @@
import android.Manifest;
import android.annotation.IntDef;
import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -32,12 +33,14 @@
import android.os.UserHandle;
import android.telephony.TelephonyManager;
-import com.android.server.LocalServices;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-/** Utility methods for controlling access to network stats APIs. */
+/**
+ * Utility methods for controlling access to network stats APIs.
+ *
+ * @hide
+ */
public final class NetworkStatsAccess {
private NetworkStatsAccess() {}
@@ -104,9 +107,8 @@
/** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
public static @NetworkStatsAccess.Level int checkAccessLevel(
- Context context, int callingUid, String callingPackage) {
- final DevicePolicyManagerInternal dpmi = LocalServices.getService(
- DevicePolicyManagerInternal.class);
+ Context context, int callingPid, int callingUid, String callingPackage) {
+ final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
final TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
boolean hasCarrierPrivileges;
@@ -119,10 +121,15 @@
Binder.restoreCallingIdentity(token);
}
- final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid);
+ final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
final int appId = UserHandle.getAppId(callingUid);
+
+ final boolean isNetworkStack = context.checkPermission(
+ android.Manifest.permission.NETWORK_STACK, callingPid, callingUid)
+ == PERMISSION_GRANTED;
+
if (hasCarrierPrivileges || isDeviceOwner
- || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) {
+ || appId == Process.SYSTEM_UID || isNetworkStack) {
// Carrier-privileged apps and device owners, and the system (including the
// network stack) can access data usage for all apps on the device.
return NetworkStatsAccess.Level.DEVICE;
@@ -135,8 +142,8 @@
}
//TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
- boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid)
- || dpmi.isActiveDeviceOwner(callingUid));
+ boolean isProfileOwner = mDpm != null && (mDpm.isProfileOwnerApp(callingPackage)
+ || mDpm.isDeviceOwnerApp(callingPackage));
if (isProfileOwner) {
// Apps with the AppOps permission, profile owners, and apps with the privileged
// permission can access data usage for all apps in this user/profile.
@@ -153,6 +160,8 @@
*/
public static boolean isAccessibleToUser(int uid, int callerUid,
@NetworkStatsAccess.Level int accessLevel) {
+ final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final int callerUserId = UserHandle.getUserHandleForUid(callerUid).getIdentifier();
switch (accessLevel) {
case NetworkStatsAccess.Level.DEVICE:
// Device-level access - can access usage for any uid.
@@ -163,13 +172,13 @@
// anonymized uids
return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
|| uid == UID_TETHERING || uid == UID_ALL
- || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+ || userId == callerUserId;
case NetworkStatsAccess.Level.USER:
// User-level access - can access usage for any app running in the same user, along
// with some special uids (system, removed, or tethering).
return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
|| uid == UID_TETHERING
- || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+ || userId == callerUserId;
case NetworkStatsAccess.Level.DEFAULT:
default:
// Default access level - can only access one's own usage.
@@ -183,8 +192,8 @@
AppOpsManager appOps = (AppOpsManager) context.getSystemService(
Context.APP_OPS_SERVICE);
- final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
- callingUid, callingPackage);
+ final int mode = appOps.noteOp(AppOpsManager.OPSTR_GET_USAGE_STATS,
+ callingUid, callingPackage, null /* attributionTag */, null /* message */);
if (mode == AppOpsManager.MODE_DEFAULT) {
// The default behavior here is to check if PackageManager has given the app
// permission.
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java
similarity index 93%
rename from services/core/java/com/android/server/net/NetworkStatsCollection.java
rename to framework-t/src/android/net/NetworkStatsCollection.java
index df372b1..7935d28 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/framework-t/src/android/net/NetworkStatsCollection.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.net;
+package android.net;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -30,14 +30,8 @@
import static android.net.TrafficStats.UID_REMOVED;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
-import static com.android.server.net.NetworkStatsService.TAG;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-import android.net.NetworkIdentity;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.Binder;
import android.service.NetworkStatsCollectionKeyProto;
import android.service.NetworkStatsCollectionProto;
@@ -46,29 +40,24 @@
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
-import android.util.IntArray;
-import android.util.MathUtils;
+import android.util.IndentingPrintWriter;
+import android.util.Log;
import android.util.Range;
-import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastDataInput;
import com.android.internal.util.FastDataOutput;
import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
import libcore.io.IoUtils;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
import java.io.BufferedInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
-import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -86,8 +75,11 @@
/**
* Collection of {@link NetworkStatsHistory}, stored based on combined key of
* {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself.
+ *
+ * @hide
*/
public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer {
+ private static final String TAG = NetworkStatsCollection.class.getSimpleName();
/** File header magic number: "ANET" */
private static final int FILE_MAGIC = 0x414E4554;
@@ -200,11 +192,11 @@
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
final int callerUid) {
- IntArray uids = new IntArray();
+ final ArrayList<Integer> uids = new ArrayList<>();
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
if (NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)) {
- int j = uids.binarySearch(key.uid);
+ int j = Collections.binarySearch(uids, new Integer(key.uid));
if (j < 0) {
j = ~j;
@@ -212,7 +204,7 @@
}
}
}
- return uids.toArray();
+ return CollectionUtils.toIntArray(uids);
}
/**
@@ -229,7 +221,8 @@
// 180 days of history should be enough for anyone; if we end up needing
// more, we'll dynamically grow the history object.
- final int bucketEstimate = (int) MathUtils.constrain(((end - start) / mBucketDuration), 0,
+ final int bucketEstimate = (int) NetworkStatsUtils.constrain(
+ ((end - start) / mBucketDuration), 0,
(180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration);
final NetworkStatsHistory combined = new NetworkStatsHistory(
mBucketDuration, bucketEstimate, fields);
@@ -320,7 +313,7 @@
final long deltaTotal = combined.getTotalBytes() - beforeTotal;
if (deltaTotal != 0) {
- Slog.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
+ Log.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
}
// Finally we can slice data as originally requested
@@ -335,7 +328,13 @@
/**
* Summarize all {@link NetworkStatsHistory} in this collection which match
- * the requested parameters.
+ * the requested parameters across the requested range.
+ *
+ * @param template - a predicate for filtering netstats.
+ * @param start - start of the range, timestamp in milliseconds since the epoch.
+ * @param end - end of the range, timestamp in milliseconds since the epoch.
+ * @param accessLevel - caller access level.
+ * @param callerUid - caller UID.
*/
public NetworkStats getSummary(NetworkTemplate template, long start, long end,
@NetworkStatsAccess.Level int accessLevel, int callerUid) {
@@ -361,8 +360,8 @@
entry.uid = key.uid;
entry.set = key.set;
entry.tag = key.tag;
- entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() ?
- DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO;
+ entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork()
+ ? DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO;
entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO;
entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO;
entry.rxBytes = historyEntry.rxBytes;
@@ -487,11 +486,11 @@
private void write(DataOutput out) throws IOException {
// cluster key lists grouped by ident
- final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = Maps.newHashMap();
+ final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = new HashMap<>();
for (Key key : mStats.keySet()) {
ArrayList<Key> keys = keysByIdent.get(key.ident);
if (keys == null) {
- keys = Lists.newArrayList();
+ keys = new ArrayList<>();
keysByIdent.put(key.ident, keys);
}
keys.add(key);
@@ -516,6 +515,12 @@
}
}
+ /**
+ * Read legacy network summary statistics file format into the collection,
+ * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
+ *
+ * @deprecated
+ */
@Deprecated
public void readLegacyNetwork(File file) throws IOException {
final AtomicFile inputFile = new AtomicFile(file);
@@ -555,6 +560,12 @@
}
}
+ /**
+ * Read legacy Uid statistics file format into the collection,
+ * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
+ *
+ * @deprecated
+ */
@Deprecated
public void readLegacyUid(File file, boolean onlyTags) throws IOException {
final AtomicFile inputFile = new AtomicFile(file);
@@ -626,12 +637,12 @@
* {@link TrafficStats#UID_REMOVED}.
*/
public void removeUids(int[] uids) {
- final ArrayList<Key> knownKeys = Lists.newArrayList();
+ final ArrayList<Key> knownKeys = new ArrayList<>();
knownKeys.addAll(mStats.keySet());
// migrate all UID stats into special "removed" bucket
for (Key key : knownKeys) {
- if (ArrayUtils.contains(uids, key.uid)) {
+ if (CollectionUtils.contains(uids, key.uid)) {
// only migrate combined TAG_NONE history
if (key.tag == TAG_NONE) {
final NetworkStatsHistory uidHistory = mStats.get(key);
@@ -658,7 +669,7 @@
}
private ArrayList<Key> getSortedKeys() {
- final ArrayList<Key> keys = Lists.newArrayList();
+ final ArrayList<Key> keys = new ArrayList<>();
keys.addAll(mStats.keySet());
Collections.sort(keys);
return keys;
@@ -769,19 +780,19 @@
public final int set;
public final int tag;
- private final int hashCode;
+ private final int mHashCode;
- public Key(NetworkIdentitySet ident, int uid, int set, int tag) {
+ Key(NetworkIdentitySet ident, int uid, int set, int tag) {
this.ident = ident;
this.uid = uid;
this.set = set;
this.tag = tag;
- hashCode = Objects.hash(ident, uid, set, tag);
+ mHashCode = Objects.hash(ident, uid, set, tag);
}
@Override
public int hashCode() {
- return hashCode;
+ return mHashCode;
}
@Override
diff --git a/core/java/android/net/NetworkStatsHistory.aidl b/framework-t/src/android/net/NetworkStatsHistory.aidl
similarity index 100%
rename from core/java/android/net/NetworkStatsHistory.aidl
rename to framework-t/src/android/net/NetworkStatsHistory.aidl
diff --git a/core/java/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java
similarity index 95%
rename from core/java/android/net/NetworkStatsHistory.java
rename to framework-t/src/android/net/NetworkStatsHistory.java
index f413063..428bc6d 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/framework-t/src/android/net/NetworkStatsHistory.java
@@ -28,8 +28,7 @@
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
-import static com.android.internal.util.ArrayUtils.total;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
@@ -37,10 +36,11 @@
import android.os.Parcelable;
import android.service.NetworkStatsHistoryBucketProto;
import android.service.NetworkStatsHistoryProto;
-import android.util.MathUtils;
+import android.util.IndentingPrintWriter;
import android.util.proto.ProtoOutputStream;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
import libcore.util.EmptyArray;
@@ -174,7 +174,7 @@
txPackets = new long[bucketStart.length];
operations = new long[bucketStart.length];
bucketCount = bucketStart.length;
- totalBytes = total(rxBytes) + total(txBytes);
+ totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
break;
}
case VERSION_ADD_PACKETS:
@@ -189,7 +189,7 @@
txPackets = readVarLongArray(in);
operations = readVarLongArray(in);
bucketCount = bucketStart.length;
- totalBytes = total(rxBytes) + total(txBytes);
+ totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
break;
}
default: {
@@ -267,7 +267,7 @@
} else {
index -= 1;
}
- return MathUtils.constrain(index, 0, bucketCount - 1);
+ return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
}
/**
@@ -281,7 +281,7 @@
} else {
index += 1;
}
- return MathUtils.constrain(index, 0, bucketCount - 1);
+ return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
}
/**
@@ -349,6 +349,9 @@
// create any buckets needed by this range
ensureBuckets(start, end);
+ // Return fast if there is still no entry. This would typically happen when the start,
+ // end or duration are not valid values, e.g. start > end, negative duration value, etc.
+ if (bucketCount == 0) return;
// distribute data usage into buckets
long duration = end - start;
@@ -526,6 +529,13 @@
/**
* Return interpolated data usage across the requested range. Interpolates
* across buckets, so values may be rounded slightly.
+ *
+ * <p>If the active bucket is not completed yet, it returns the proportional value of it
+ * based on its duration and the {@code end} param.
+ *
+ * @param start - start of the range, timestamp in milliseconds since the epoch.
+ * @param end - end of the range, timestamp in milliseconds since the epoch.
+ * @param recycle - entry instance for performance, could be null.
*/
@UnsupportedAppUsage
public Entry getValues(long start, long end, Entry recycle) {
@@ -535,6 +545,11 @@
/**
* Return interpolated data usage across the requested range. Interpolates
* across buckets, so values may be rounded slightly.
+ *
+ * @param start - start of the range, timestamp in milliseconds since the epoch.
+ * @param end - end of the range, timestamp in milliseconds since the epoch.
+ * @param now - current timestamp in milliseconds since the epoch (wall clock).
+ * @param recycle - entry instance for performance, could be null.
*/
@UnsupportedAppUsage
public Entry getValues(long start, long end, long now, Entry recycle) {
@@ -548,6 +563,9 @@
entry.txPackets = txPackets != null ? 0 : UNKNOWN;
entry.operations = operations != null ? 0 : UNKNOWN;
+ // Return fast if there is no entry.
+ if (bucketCount == 0) return entry;
+
final int startIndex = getIndexAfter(end);
for (int i = startIndex; i >= 0; i--) {
final long curStart = bucketStart[i];
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
new file mode 100644
index 0000000..e9084b0
--- /dev/null
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -0,0 +1,1206 @@
+/*
+ * 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 static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_PROXY;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
+import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.NetworkIdentity.OEM_NONE;
+import static android.net.NetworkIdentity.OEM_PAID;
+import static android.net.NetworkIdentity.OEM_PRIVATE;
+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 android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.net.wifi.WifiInfo;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkIdentityUtils;
+import com.android.net.module.util.NetworkStatsUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Predicate used to match {@link NetworkIdentity}, usually when collecting
+ * statistics. (It should probably have been named {@code NetworkPredicate}.)
+ *
+ * @hide
+ */
+@SystemApi(client = MODULE_LIBRARIES)
+public final class NetworkTemplate implements Parcelable {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "MATCH_" }, value = {
+ MATCH_MOBILE,
+ MATCH_WIFI,
+ MATCH_ETHERNET,
+ MATCH_BLUETOOTH,
+ MATCH_CARRIER
+ })
+ public @interface TemplateMatchRule{}
+
+ /** Match rule to match cellular networks with given Subscriber Ids. */
+ public static final int MATCH_MOBILE = 1;
+ /** Match rule to match wifi networks. */
+ public static final int MATCH_WIFI = 4;
+ /** Match rule to match ethernet networks. */
+ public static final int MATCH_ETHERNET = 5;
+ /**
+ * Match rule to match all cellular networks.
+ *
+ * @hide
+ */
+ public static final int MATCH_MOBILE_WILDCARD = 6;
+ /**
+ * Match rule to match all wifi networks.
+ *
+ * @hide
+ */
+ public static final int MATCH_WIFI_WILDCARD = 7;
+ /** Match rule to match bluetooth networks. */
+ public static final int MATCH_BLUETOOTH = 8;
+ /**
+ * Match rule to match networks with {@link Connectivity#TYPE_PROXY} as the legacy network type.
+ *
+ * @hide
+ */
+ public static final int MATCH_PROXY = 9;
+ /**
+ * Match rule to match all networks with subscriberId inside the template. Some carriers
+ * may offer non-cellular networks like WiFi, which will be matched by this rule.
+ */
+ public static final int MATCH_CARRIER = 10;
+
+ // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL.
+ /** @hide */
+ public static final String WIFI_NETWORKID_ALL = null;
+
+ /**
+ * Wi-Fi Network Key is never supposed to be null (if it is, it is a bug that
+ * should be fixed), so it's not possible to want to match null vs
+ * non-null. Therefore it's fine to use null as a sentinel for Wifi Network Key.
+ *
+ * @hide
+ */
+ public static final String WIFI_NETWORK_KEY_ALL = WIFI_NETWORKID_ALL;
+
+ /**
+ * Include all network types when filtering. This is meant to merge in with the
+ * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
+ */
+ public static final int NETWORK_TYPE_ALL = -1;
+ /**
+ * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
+ * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
+ * with NR state as connected. This should not be overlapped with any of the
+ * {@code TelephonyManager.NETWORK_TYPE_*} constants.
+ *
+ * @hide
+ */
+ public static final int NETWORK_TYPE_5G_NSA = -2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "OEM_MANAGED_" }, value = {
+ OEM_MANAGED_ALL,
+ OEM_MANAGED_NO,
+ OEM_MANAGED_YES,
+ OEM_MANAGED_PAID,
+ OEM_MANAGED_PRIVATE
+ })
+ public @interface OemManaged{}
+
+ /**
+ * Value to match both OEM managed and unmanaged networks (all networks).
+ */
+ public static final int OEM_MANAGED_ALL = -1;
+ /**
+ * Value to match networks which are not OEM managed.
+ */
+ public static final int OEM_MANAGED_NO = OEM_NONE;
+ /**
+ * Value to match any OEM managed network.
+ */
+ public static final int OEM_MANAGED_YES = -2;
+ /**
+ * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
+ */
+ public static final int OEM_MANAGED_PAID = OEM_PAID;
+ /**
+ * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
+ */
+ public static final int OEM_MANAGED_PRIVATE = OEM_PRIVATE;
+
+ private static boolean isKnownMatchRule(final int rule) {
+ switch (rule) {
+ case MATCH_MOBILE:
+ case MATCH_WIFI:
+ case MATCH_ETHERNET:
+ case MATCH_MOBILE_WILDCARD:
+ case MATCH_WIFI_WILDCARD:
+ case MATCH_BLUETOOTH:
+ case MATCH_PROXY:
+ case MATCH_CARRIER:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
+ * the given IMSI.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
+ return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
+ }
+
+ /**
+ * Template to match cellular networks with the given IMSI, {@code ratType} and
+ * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
+ * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
+ *
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
+ @NetworkType int ratType, int metered) {
+ if (TextUtils.isEmpty(subscriberId)) {
+ return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */,
+ null /* matchSubscriberIds */,
+ new String[0] /* matchWifiNetworkKeys */, metered, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+ return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[] { subscriberId },
+ new String[0] /* matchWifiNetworkKeys */,
+ metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+
+ /**
+ * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
+ * regardless of IMSI.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public static NetworkTemplate buildTemplateMobileWildcard() {
+ return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
+ }
+
+ /**
+ * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
+ * regardless of key of the wifi network.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static NetworkTemplate buildTemplateWifiWildcard() {
+ // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL
+ // and SUBSCRIBER_ID_MATCH_RULE_ALL.
+ return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
+ }
+
+ /** @hide */
+ @Deprecated
+ @UnsupportedAppUsage
+ public static NetworkTemplate buildTemplateWifi() {
+ return buildTemplateWifiWildcard();
+ }
+
+ /**
+ * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
+ * given key of the wifi network.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * to know details about the key.
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) {
+ Objects.requireNonNull(wifiNetworkKey);
+ return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */,
+ new String[] { null } /* matchSubscriberIds */,
+ new String[] { wifiNetworkKey }, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL);
+ }
+
+ /**
+ * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given
+ * key of the wifi network and IMSI.
+ *
+ * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless
+ * of key of the wifi network.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * to know details about the key.
+ * @param subscriberId the IMSI associated to this wifi network.
+ *
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey,
+ @Nullable String subscriberId) {
+ return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId },
+ wifiNetworkKey != null
+ ? new String[] { wifiNetworkKey } : new String[0],
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
+ * networks together.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static NetworkTemplate buildTemplateEthernet() {
+ return new NetworkTemplate(MATCH_ETHERNET, null, null);
+ }
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
+ * networks together.
+ *
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateBluetooth() {
+ return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
+ }
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
+ * networks together.
+ *
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateProxy() {
+ return new NetworkTemplate(MATCH_PROXY, null, null);
+ }
+
+ /**
+ * Template to match all metered carrier networks with the given IMSI.
+ *
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
+ Objects.requireNonNull(subscriberId);
+ return new NetworkTemplate(MATCH_CARRIER, subscriberId,
+ new String[] { subscriberId },
+ new String[0] /* matchWifiNetworkKeys */,
+ METERED_YES, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+
+ private final int mMatchRule;
+ private final String mSubscriberId;
+
+ /**
+ * Ugh, templates are designed to target a single subscriber, but we might
+ * need to match several "merged" subscribers. These are the subscribers
+ * that should be considered to match this template.
+ * <p>
+ * Since the merge set is dynamic, it should <em>not</em> be persisted or
+ * used for determining equality.
+ */
+ private final String[] mMatchSubscriberIds;
+
+ @NonNull
+ private final String[] mMatchWifiNetworkKeys;
+
+ // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
+ private final int mMetered;
+ private final int mRoaming;
+ private final int mDefaultNetwork;
+ private final int mSubType;
+ /**
+ * The subscriber Id match rule defines how the template should match networks with
+ * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
+ */
+ private final int mSubscriberIdMatchRule;
+
+ // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
+ private final int mOemManaged;
+
+ private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) {
+ switch (matchRule) {
+ case MATCH_MOBILE:
+ case MATCH_CARRIER:
+ // MOBILE and CARRIER templates must always specify a subscriber ID.
+ if (subscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL) {
+ throw new IllegalArgumentException("Invalid SubscriberIdMatchRule "
+ + "on match rule: " + getMatchRuleName(matchRule));
+ }
+ return;
+ default:
+ return;
+ }
+ }
+
+ /** @hide */
+ // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
+ @UnsupportedAppUsage
+ public NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey) {
+ this(matchRule, subscriberId, new String[] { subscriberId }, wifiNetworkKey);
+ }
+
+ /** @hide */
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String wifiNetworkKey) {
+ // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
+ // to metered networks. It is now possible to match mobile with any meteredness, but
+ // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
+ //constructor passes METERED_YES for these types.
+ this(matchRule, subscriberId, matchSubscriberIds,
+ wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
+ (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES
+ : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+
+ /** @hide */
+ // TODO: Remove it after updating all of the caller.
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType,
+ int oemManaged) {
+ this(matchRule, subscriberId, matchSubscriberIds,
+ wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
+ metered, roaming, defaultNetwork, subType, oemManaged,
+ NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+
+ /** @hide */
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String[] matchWifiNetworkKeys, int metered, int roaming,
+ int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) {
+ Objects.requireNonNull(matchWifiNetworkKeys);
+ mMatchRule = matchRule;
+ mSubscriberId = subscriberId;
+ // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when
+ // mSubscriberId is null
+ mMatchSubscriberIds = matchSubscriberIds;
+ mMatchWifiNetworkKeys = matchWifiNetworkKeys;
+ mMetered = metered;
+ mRoaming = roaming;
+ mDefaultNetwork = defaultNetwork;
+ mSubType = subType;
+ mOemManaged = oemManaged;
+ mSubscriberIdMatchRule = subscriberIdMatchRule;
+ checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
+ if (!isKnownMatchRule(matchRule)) {
+ throw new IllegalArgumentException("Unknown network template rule " + matchRule
+ + " will not match any identity.");
+ }
+ }
+
+ private NetworkTemplate(Parcel in) {
+ mMatchRule = in.readInt();
+ mSubscriberId = in.readString();
+ mMatchSubscriberIds = in.createStringArray();
+ mMatchWifiNetworkKeys = in.createStringArray();
+ mMetered = in.readInt();
+ mRoaming = in.readInt();
+ mDefaultNetwork = in.readInt();
+ mSubType = in.readInt();
+ mOemManaged = in.readInt();
+ mSubscriberIdMatchRule = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mMatchRule);
+ dest.writeString(mSubscriberId);
+ dest.writeStringArray(mMatchSubscriberIds);
+ dest.writeStringArray(mMatchWifiNetworkKeys);
+ dest.writeInt(mMetered);
+ dest.writeInt(mRoaming);
+ dest.writeInt(mDefaultNetwork);
+ dest.writeInt(mSubType);
+ dest.writeInt(mOemManaged);
+ dest.writeInt(mSubscriberIdMatchRule);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
+ builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
+ if (mSubscriberId != null) {
+ builder.append(", subscriberId=").append(
+ NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
+ }
+ if (mMatchSubscriberIds != null) {
+ builder.append(", matchSubscriberIds=").append(
+ Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds)));
+ }
+ builder.append(", matchWifiNetworkKeys=").append(Arrays.toString(mMatchWifiNetworkKeys));
+ 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));
+ }
+ if (mSubType != NETWORK_TYPE_ALL) {
+ builder.append(", subType=").append(mSubType);
+ }
+ if (mOemManaged != OEM_MANAGED_ALL) {
+ builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
+ }
+ builder.append(", subscriberIdMatchRule=")
+ .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule));
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
+ mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (obj instanceof NetworkTemplate) {
+ final NetworkTemplate other = (NetworkTemplate) obj;
+ return mMatchRule == other.mMatchRule
+ && Objects.equals(mSubscriberId, other.mSubscriberId)
+ && mMetered == other.mMetered
+ && mRoaming == other.mRoaming
+ && mDefaultNetwork == other.mDefaultNetwork
+ && mSubType == other.mSubType
+ && mOemManaged == other.mOemManaged
+ && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
+ && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
+ }
+ return false;
+ }
+
+ private static String subscriberIdMatchRuleToString(int rule) {
+ switch (rule) {
+ case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT:
+ return "EXACT_MATCH";
+ case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL:
+ return "ALL";
+ default:
+ return "Unknown rule " + rule;
+ }
+ }
+
+ /** @hide */
+ public boolean isMatchRuleMobile() {
+ switch (mMatchRule) {
+ case MATCH_MOBILE:
+ case MATCH_MOBILE_WILDCARD:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Get match rule of the template. See {@code MATCH_*}.
+ */
+ @UnsupportedAppUsage
+ public int getMatchRule() {
+ // Wildcard rules are not exposed. For external callers, convert wildcard rules to
+ // exposed rules before returning.
+ switch (mMatchRule) {
+ case MATCH_MOBILE_WILDCARD:
+ return MATCH_MOBILE;
+ case MATCH_WIFI_WILDCARD:
+ return MATCH_WIFI;
+ default:
+ return mMatchRule;
+ }
+ }
+
+ /**
+ * Get subscriber Id of the template.
+ * @hide
+ */
+ @Nullable
+ @UnsupportedAppUsage
+ public String getSubscriberId() {
+ return mSubscriberId;
+ }
+
+ /**
+ * Get set of subscriber Ids of the template.
+ */
+ @NonNull
+ public Set<String> getSubscriberIds() {
+ return new ArraySet<>(Arrays.asList(mMatchSubscriberIds));
+ }
+
+ /**
+ * Get the set of Wifi Network Keys of the template.
+ * See {@link WifiInfo#getCurrentNetworkKey()}.
+ */
+ @NonNull
+ public Set<String> getWifiNetworkKeys() {
+ return new ArraySet<>(Arrays.asList(mMatchWifiNetworkKeys));
+ }
+
+ /** @hide */
+ // TODO: Remove this and replace all callers with {@link #getWifiNetworkKeys()}.
+ @Nullable
+ public String getNetworkId() {
+ return getWifiNetworkKeys().isEmpty() ? null : getWifiNetworkKeys().iterator().next();
+ }
+
+ /**
+ * Get meteredness filter of the template.
+ */
+ @NetworkStats.Meteredness
+ public int getMeteredness() {
+ return mMetered;
+ }
+
+ /**
+ * Get roaming filter of the template.
+ */
+ @NetworkStats.Roaming
+ public int getRoaming() {
+ return mRoaming;
+ }
+
+ /**
+ * Get the default network status filter of the template.
+ */
+ @NetworkStats.DefaultNetwork
+ public int getDefaultNetworkStatus() {
+ return mDefaultNetwork;
+ }
+
+ /**
+ * Get the Radio Access Technology(RAT) type filter of the template.
+ */
+ public int getRatType() {
+ return mSubType;
+ }
+
+ /**
+ * Get the OEM managed filter of the template. See {@code OEM_MANAGED_*} or
+ * {@code android.net.NetworkIdentity#OEM_*}.
+ */
+ @OemManaged
+ public int getOemManaged() {
+ return mOemManaged;
+ }
+
+ /**
+ * Test if given {@link NetworkIdentity} matches this template.
+ *
+ * @hide
+ */
+ public boolean matches(NetworkIdentity ident) {
+ if (!matchesMetered(ident)) return false;
+ if (!matchesRoaming(ident)) return false;
+ if (!matchesDefaultNetwork(ident)) return false;
+ if (!matchesOemNetwork(ident)) return false;
+
+ switch (mMatchRule) {
+ case MATCH_MOBILE:
+ return matchesMobile(ident);
+ case MATCH_WIFI:
+ return matchesWifi(ident);
+ case MATCH_ETHERNET:
+ return matchesEthernet(ident);
+ case MATCH_MOBILE_WILDCARD:
+ return matchesMobileWildcard(ident);
+ case MATCH_WIFI_WILDCARD:
+ return matchesWifiWildcard(ident);
+ case MATCH_BLUETOOTH:
+ return matchesBluetooth(ident);
+ case MATCH_PROXY:
+ return matchesProxy(ident);
+ case MATCH_CARRIER:
+ return matchesCarrier(ident);
+ default:
+ // We have no idea what kind of network template we are, so we
+ // just claim not to match anything.
+ return false;
+ }
+ }
+
+ 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);
+ }
+
+ private boolean matchesOemNetwork(NetworkIdentity ident) {
+ return (mOemManaged == OEM_MANAGED_ALL)
+ || (mOemManaged == OEM_MANAGED_YES
+ && ident.mOemManaged != OEM_NONE)
+ || (mOemManaged == ident.mOemManaged);
+ }
+
+ private boolean matchesCollapsedRatType(NetworkIdentity ident) {
+ return mSubType == NETWORK_TYPE_ALL
+ || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
+ }
+
+ /**
+ * Check if this template matches {@code subscriberId}. Returns true if this
+ * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a
+ * {@code mMatchSubscriberIds} array that contains {@code subscriberId}.
+ *
+ * @hide
+ */
+ public boolean matchesSubscriberId(@Nullable String subscriberId) {
+ return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
+ || CollectionUtils.contains(mMatchSubscriberIds, subscriberId);
+ }
+
+ /**
+ * Check if network matches key of the wifi network.
+ * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is
+ * empty.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * to know details about the key.
+ */
+ private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
+ Objects.requireNonNull(wifiNetworkKey);
+ return CollectionUtils.isEmpty(mMatchWifiNetworkKeys)
+ || CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey);
+ }
+
+ /**
+ * Check if mobile network matches IMSI.
+ */
+ private boolean matchesMobile(NetworkIdentity ident) {
+ if (ident.mType == TYPE_WIMAX) {
+ // TODO: consider matching against WiMAX subscriber identity
+ return true;
+ } else {
+ return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds)
+ && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
+ && matchesCollapsedRatType(ident);
+ }
+ }
+
+ /**
+ * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
+ * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
+ *
+ * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+ *
+ * @hide
+ */
+ // TODO: 1. Consider move this to TelephonyManager if used by other modules.
+ // 2. Consider make this configurable.
+ // 3. Use TelephonyManager APIs when available.
+ // TODO: @SystemApi when ready.
+ public static int getCollapsedRatType(int ratType) {
+ switch (ratType) {
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ return TelephonyManager.NETWORK_TYPE_GSM;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return TelephonyManager.NETWORK_TYPE_UMTS;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ case TelephonyManager.NETWORK_TYPE_IWLAN:
+ return TelephonyManager.NETWORK_TYPE_LTE;
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return TelephonyManager.NETWORK_TYPE_NR;
+ // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+ case NetworkTemplate.NETWORK_TYPE_5G_NSA:
+ return NetworkTemplate.NETWORK_TYPE_5G_NSA;
+ default:
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Return all supported collapsed RAT types that could be returned by
+ * {@link #getCollapsedRatType(int)}.
+ *
+ * @hide
+ */
+ // TODO: @SystemApi when ready.
+ @NonNull
+ public static final int[] getAllCollapsedRatTypes() {
+ final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
+ final HashSet<Integer> collapsedRatTypes = new HashSet<>();
+ for (final int ratType : ratTypes) {
+ collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
+ }
+ // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
+ // it is not in TelephonyManager#NETWORK_TYPE_* constants.
+ // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+ collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA));
+ // Ensure that unknown type is returned.
+ collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ return toIntArray(collapsedRatTypes);
+ }
+
+ @NonNull
+ private static int[] toIntArray(@NonNull Collection<Integer> list) {
+ final int[] array = new int[list.size()];
+ int i = 0;
+ for (final Integer item : list) {
+ array[i++] = item;
+ }
+ return array;
+ }
+
+ /**
+ * Check if matches Wi-Fi network template.
+ */
+ private boolean matchesWifi(NetworkIdentity ident) {
+ switch (ident.mType) {
+ case TYPE_WIFI:
+ return matchesSubscriberId(ident.mSubscriberId)
+ && matchesWifiNetworkKey(ident.mNetworkId);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Check if matches Ethernet network template.
+ */
+ private boolean matchesEthernet(NetworkIdentity ident) {
+ if (ident.mType == TYPE_ETHERNET) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if matches carrier network. The carrier networks means it includes the subscriberId.
+ */
+ private boolean matchesCarrier(NetworkIdentity ident) {
+ return ident.mSubscriberId != null
+ && !CollectionUtils.isEmpty(mMatchSubscriberIds)
+ && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
+ }
+
+ private boolean matchesMobileWildcard(NetworkIdentity ident) {
+ if (ident.mType == TYPE_WIMAX) {
+ return true;
+ } else {
+ return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident);
+ }
+ }
+
+ private boolean matchesWifiWildcard(NetworkIdentity ident) {
+ switch (ident.mType) {
+ case TYPE_WIFI:
+ case TYPE_WIFI_P2P:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Check if matches Bluetooth network template.
+ */
+ private boolean matchesBluetooth(NetworkIdentity ident) {
+ if (ident.mType == TYPE_BLUETOOTH) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if matches Proxy network template.
+ */
+ private boolean matchesProxy(NetworkIdentity ident) {
+ return ident.mType == TYPE_PROXY;
+ }
+
+ private static String getMatchRuleName(int matchRule) {
+ switch (matchRule) {
+ case MATCH_MOBILE:
+ return "MOBILE";
+ case MATCH_WIFI:
+ return "WIFI";
+ case MATCH_ETHERNET:
+ return "ETHERNET";
+ case MATCH_MOBILE_WILDCARD:
+ return "MOBILE_WILDCARD";
+ case MATCH_WIFI_WILDCARD:
+ return "WIFI_WILDCARD";
+ case MATCH_BLUETOOTH:
+ return "BLUETOOTH";
+ case MATCH_PROXY:
+ return "PROXY";
+ case MATCH_CARRIER:
+ return "CARRIER";
+ default:
+ return "UNKNOWN(" + matchRule + ")";
+ }
+ }
+
+ private static String getOemManagedNames(int oemManaged) {
+ switch (oemManaged) {
+ case OEM_MANAGED_ALL:
+ return "OEM_MANAGED_ALL";
+ case OEM_MANAGED_NO:
+ return "OEM_MANAGED_NO";
+ case OEM_MANAGED_YES:
+ return "OEM_MANAGED_YES";
+ default:
+ return NetworkIdentity.getOemManagedNames(oemManaged);
+ }
+ }
+
+ /**
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that primarily matches
+ * A, but also matches B.
+ * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
+ return normalize(template, Arrays.<String[]>asList(merged));
+ }
+
+ /**
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ *
+ * There can be multiple merged subscriberIds for multi-SIM devices.
+ *
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that primarily matches
+ * A, but also matches B.
+ *
+ * @hide
+ */
+ // TODO: @SystemApi when ready.
+ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
+ // Now there are several types of network which uses SubscriberId to store network
+ // information. For instances:
+ // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
+ // The TYPE_CARRIER means that the network associate to specific carrier network.
+
+ if (template.mSubscriberId == null) return template;
+
+ for (String[] merged : mergedList) {
+ if (CollectionUtils.contains(merged, template.mSubscriberId)) {
+ // Requested template subscriber is part of the merge group; return
+ // a template that matches all merged subscribers.
+ final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys;
+ return new NetworkTemplate(template.mMatchRule, merged[0], merged,
+ CollectionUtils.isEmpty(matchWifiNetworkKeys)
+ ? null : matchWifiNetworkKeys[0]);
+ }
+ }
+
+ return template;
+ }
+
+ @UnsupportedAppUsage
+ public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
+ @Override
+ public NetworkTemplate createFromParcel(Parcel in) {
+ return new NetworkTemplate(in);
+ }
+
+ @Override
+ public NetworkTemplate[] newArray(int size) {
+ return new NetworkTemplate[size];
+ }
+ };
+
+ /**
+ * Builder class for NetworkTemplate.
+ */
+ public static final class Builder {
+ private final int mMatchRule;
+ // Use a SortedSet to provide a deterministic order when fetching the first one.
+ @NonNull
+ private final SortedSet<String> mMatchSubscriberIds =
+ new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder()));
+ @NonNull
+ private final SortedSet<String> mMatchWifiNetworkKeys = new TreeSet<>();
+
+ // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
+ private int mMetered;
+ private int mRoaming;
+ private int mDefaultNetwork;
+ private int mRatType;
+
+ // Bitfield containing OEM network properties {@code NetworkIdentity#OEM_*}.
+ private int mOemManaged;
+
+ /**
+ * Creates a new Builder with given match rule to construct NetworkTemplate objects.
+ *
+ * @param matchRule the match rule of the template, see {@code MATCH_*}.
+ */
+ public Builder(@TemplateMatchRule final int matchRule) {
+ assertRequestableMatchRule(matchRule);
+ // Initialize members with default values.
+ mMatchRule = matchRule;
+ mMetered = METERED_ALL;
+ mRoaming = ROAMING_ALL;
+ mDefaultNetwork = DEFAULT_NETWORK_ALL;
+ mRatType = NETWORK_TYPE_ALL;
+ mOemManaged = OEM_MANAGED_ALL;
+ }
+
+ /**
+ * Set the Subscriber Ids. Calling this function with an empty set represents
+ * the intention of matching any Subscriber Ids.
+ *
+ * @param subscriberIds the list of Subscriber Ids.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setSubscriberIds(@NonNull Set<String> subscriberIds) {
+ Objects.requireNonNull(subscriberIds);
+ mMatchSubscriberIds.clear();
+ mMatchSubscriberIds.addAll(subscriberIds);
+ return this;
+ }
+
+ /**
+ * Set the Wifi Network Keys. Calling this function with an empty set represents
+ * the intention of matching any Wifi Network Key.
+ *
+ * @param wifiNetworkKeys the list of Wifi Network Key,
+ * see {@link WifiInfo#getCurrentNetworkKey()}.
+ * Or an empty list to match all networks.
+ * Note that {@code getCurrentNetworkKey()} might get null key
+ * when wifi disconnects. However, the caller should never invoke
+ * this function with a null Wifi Network Key since such statistics
+ * never exists.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setWifiNetworkKeys(@NonNull Set<String> wifiNetworkKeys) {
+ Objects.requireNonNull(wifiNetworkKeys);
+ for (String key : wifiNetworkKeys) {
+ if (key == null) {
+ throw new IllegalArgumentException("Null is not a valid key");
+ }
+ }
+ mMatchWifiNetworkKeys.clear();
+ mMatchWifiNetworkKeys.addAll(wifiNetworkKeys);
+ return this;
+ }
+
+ /**
+ * Set the meteredness filter.
+ *
+ * @param metered the meteredness filter.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setMeteredness(@NetworkStats.Meteredness int metered) {
+ mMetered = metered;
+ return this;
+ }
+
+ /**
+ * Set the roaming filter.
+ *
+ * @param roaming the roaming filter.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRoaming(@NetworkStats.Roaming int roaming) {
+ mRoaming = roaming;
+ return this;
+ }
+
+ /**
+ * Set the default network status filter.
+ *
+ * @param defaultNetwork the default network status filter.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setDefaultNetworkStatus(@NetworkStats.DefaultNetwork int defaultNetwork) {
+ mDefaultNetwork = defaultNetwork;
+ return this;
+ }
+
+ /**
+ * Set the Radio Access Technology(RAT) type filter.
+ *
+ * @param ratType the Radio Access Technology(RAT) type filter. Use
+ * {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
+ * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRatType(@NetworkType int ratType) {
+ // Input will be validated with the match rule when building the template.
+ mRatType = ratType;
+ return this;
+ }
+
+ /**
+ * Set the OEM managed filter.
+ *
+ * @param oemManaged the match rule to match different type of OEM managed network or
+ * unmanaged networks. See {@code OEM_MANAGED_*}.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setOemManaged(@OemManaged int oemManaged) {
+ mOemManaged = oemManaged;
+ return this;
+ }
+
+ /**
+ * Check whether the match rule is requestable.
+ *
+ * @param matchRule the target match rule to be checked.
+ */
+ private static void assertRequestableMatchRule(final int matchRule) {
+ if (!isKnownMatchRule(matchRule)
+ || matchRule == MATCH_PROXY
+ || matchRule == MATCH_MOBILE_WILDCARD
+ || matchRule == MATCH_WIFI_WILDCARD) {
+ throw new IllegalArgumentException("Invalid match rule: "
+ + getMatchRuleName(matchRule));
+ }
+ }
+
+ private void assertRequestableParameters() {
+ validateWifiNetworkKeys();
+ // TODO: Check all the input are legitimate.
+ }
+
+ private void validateWifiNetworkKeys() {
+ if (mMatchRule != MATCH_WIFI && !mMatchWifiNetworkKeys.isEmpty()) {
+ throw new IllegalArgumentException("Trying to build non wifi match rule: "
+ + mMatchRule + " with wifi network keys");
+ }
+ }
+
+ /**
+ * For backward compatibility, deduce match rule to a wildcard match rule
+ * if the Subscriber Ids are empty.
+ */
+ private int getWildcardDeducedMatchRule() {
+ if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) {
+ return MATCH_MOBILE_WILDCARD;
+ } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty()
+ && mMatchWifiNetworkKeys.isEmpty()) {
+ return MATCH_WIFI_WILDCARD;
+ }
+ return mMatchRule;
+ }
+
+ /**
+ * Builds the instance of the NetworkTemplate.
+ *
+ * @return the built instance of NetworkTemplate.
+ */
+ @NonNull
+ public NetworkTemplate build() {
+ assertRequestableParameters();
+ final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty()
+ ? NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
+ : NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT;
+ return new NetworkTemplate(getWildcardDeducedMatchRule(),
+ mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(),
+ mMatchSubscriberIds.toArray(new String[0]),
+ mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming,
+ mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule);
+ }
+ }
+}
diff --git a/core/java/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java
similarity index 98%
rename from core/java/android/net/TrafficStats.java
rename to framework-t/src/android/net/TrafficStats.java
index fa65061..d8feb88 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/framework-t/src/android/net/TrafficStats.java
@@ -29,7 +29,6 @@
import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.DataUnit;
import com.android.server.NetworkManagementSocketTagger;
@@ -59,19 +58,19 @@
*/
public final static int UNSUPPORTED = -1;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long KB_IN_BYTES = 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
diff --git a/core/java/android/net/UnderlyingNetworkInfo.aidl b/framework-t/src/android/net/UnderlyingNetworkInfo.aidl
similarity index 100%
rename from core/java/android/net/UnderlyingNetworkInfo.aidl
rename to framework-t/src/android/net/UnderlyingNetworkInfo.aidl
diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/framework-t/src/android/net/UnderlyingNetworkInfo.java
similarity index 100%
rename from core/java/android/net/UnderlyingNetworkInfo.java
rename to framework-t/src/android/net/UnderlyingNetworkInfo.java
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl
similarity index 100%
rename from core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
rename to framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
similarity index 100%
rename from core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
rename to framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
similarity index 100%
rename from core/java/android/net/netstats/provider/NetworkStatsProvider.java
rename to framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
diff --git a/core/java/android/net/nsd/INsdManager.aidl b/framework-t/src/android/net/nsd/INsdManager.aidl
similarity index 68%
rename from core/java/android/net/nsd/INsdManager.aidl
rename to framework-t/src/android/net/nsd/INsdManager.aidl
index e9e8935..89e9cdb 100644
--- a/core/java/android/net/nsd/INsdManager.aidl
+++ b/framework-t/src/android/net/nsd/INsdManager.aidl
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2012, The Android Open Source Project
+ * Copyright (c) 2021, 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.
@@ -16,16 +16,15 @@
package android.net.nsd;
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.INsdServiceConnector;
import android.os.Messenger;
/**
- * Interface that NsdService implements
+ * Interface that NsdService implements to connect NsdManager clients.
*
* {@hide}
*/
-interface INsdManager
-{
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- Messenger getMessenger();
- void setEnabled(boolean enable);
+interface INsdManager {
+ INsdServiceConnector connect(INsdManagerCallback cb);
}
diff --git a/framework-t/src/android/net/nsd/INsdManagerCallback.aidl b/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
new file mode 100644
index 0000000..1a262ec
--- /dev/null
+++ b/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, 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.nsd;
+
+import android.os.Messenger;
+import android.net.nsd.NsdServiceInfo;
+
+/**
+ * Callbacks from NsdService to NsdManager
+ * @hide
+ */
+oneway interface INsdManagerCallback {
+ void onDiscoverServicesStarted(int listenerKey, in NsdServiceInfo info);
+ void onDiscoverServicesFailed(int listenerKey, int error);
+ void onServiceFound(int listenerKey, in NsdServiceInfo info);
+ void onServiceLost(int listenerKey, in NsdServiceInfo info);
+ void onStopDiscoveryFailed(int listenerKey, int error);
+ void onStopDiscoverySucceeded(int listenerKey);
+ void onRegisterServiceFailed(int listenerKey, int error);
+ void onRegisterServiceSucceeded(int listenerKey, in NsdServiceInfo info);
+ void onUnregisterServiceFailed(int listenerKey, int error);
+ void onUnregisterServiceSucceeded(int listenerKey);
+ void onResolveServiceFailed(int listenerKey, int error);
+ void onResolveServiceSucceeded(int listenerKey, in NsdServiceInfo info);
+}
diff --git a/framework-t/src/android/net/nsd/INsdServiceConnector.aidl b/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
new file mode 100644
index 0000000..b06ae55
--- /dev/null
+++ b/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2021, 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.nsd;
+
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Messenger;
+
+/**
+ * Interface that NsdService implements for each NsdManager client.
+ *
+ * {@hide}
+ */
+interface INsdServiceConnector {
+ void registerService(int listenerKey, in NsdServiceInfo serviceInfo);
+ void unregisterService(int listenerKey);
+ void discoverServices(int listenerKey, in NsdServiceInfo serviceInfo);
+ void stopDiscovery(int listenerKey);
+ void resolveService(int listenerKey, in NsdServiceInfo serviceInfo);
+ void startDaemon();
+}
\ No newline at end of file
diff --git a/core/java/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
similarity index 81%
rename from core/java/android/net/nsd/NsdManager.java
rename to framework-t/src/android/net/nsd/NsdManager.java
index ae8d010..0f21e55 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -16,10 +16,6 @@
package android.net.nsd;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkStringNotEmpty;
-
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
@@ -31,16 +27,14 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
-import android.os.Messenger;
import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.Protocol;
-import java.util.concurrent.CountDownLatch;
+import java.util.Objects;
/**
* The Network Service Discovery Manager class provides the API to discover services
@@ -179,60 +173,63 @@
*/
public static final int NSD_STATE_ENABLED = 2;
- private static final int BASE = Protocol.BASE_NSD_MANAGER;
+ /** @hide */
+ public static final int DISCOVER_SERVICES = 1;
+ /** @hide */
+ public static final int DISCOVER_SERVICES_STARTED = 2;
+ /** @hide */
+ public static final int DISCOVER_SERVICES_FAILED = 3;
+ /** @hide */
+ public static final int SERVICE_FOUND = 4;
+ /** @hide */
+ public static final int SERVICE_LOST = 5;
/** @hide */
- public static final int DISCOVER_SERVICES = BASE + 1;
+ public static final int STOP_DISCOVERY = 6;
/** @hide */
- public static final int DISCOVER_SERVICES_STARTED = BASE + 2;
+ public static final int STOP_DISCOVERY_FAILED = 7;
/** @hide */
- public static final int DISCOVER_SERVICES_FAILED = BASE + 3;
- /** @hide */
- public static final int SERVICE_FOUND = BASE + 4;
- /** @hide */
- public static final int SERVICE_LOST = BASE + 5;
+ public static final int STOP_DISCOVERY_SUCCEEDED = 8;
/** @hide */
- public static final int STOP_DISCOVERY = BASE + 6;
+ public static final int REGISTER_SERVICE = 9;
/** @hide */
- public static final int STOP_DISCOVERY_FAILED = BASE + 7;
+ public static final int REGISTER_SERVICE_FAILED = 10;
/** @hide */
- public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 8;
+ public static final int REGISTER_SERVICE_SUCCEEDED = 11;
/** @hide */
- public static final int REGISTER_SERVICE = BASE + 9;
+ public static final int UNREGISTER_SERVICE = 12;
/** @hide */
- public static final int REGISTER_SERVICE_FAILED = BASE + 10;
+ public static final int UNREGISTER_SERVICE_FAILED = 13;
/** @hide */
- public static final int REGISTER_SERVICE_SUCCEEDED = BASE + 11;
+ public static final int UNREGISTER_SERVICE_SUCCEEDED = 14;
/** @hide */
- public static final int UNREGISTER_SERVICE = BASE + 12;
+ public static final int RESOLVE_SERVICE = 15;
/** @hide */
- public static final int UNREGISTER_SERVICE_FAILED = BASE + 13;
+ public static final int RESOLVE_SERVICE_FAILED = 16;
/** @hide */
- public static final int UNREGISTER_SERVICE_SUCCEEDED = BASE + 14;
+ public static final int RESOLVE_SERVICE_SUCCEEDED = 17;
/** @hide */
- public static final int RESOLVE_SERVICE = BASE + 18;
- /** @hide */
- public static final int RESOLVE_SERVICE_FAILED = BASE + 19;
- /** @hide */
- public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20;
+ public static final int DAEMON_CLEANUP = 18;
/** @hide */
- public static final int DAEMON_CLEANUP = BASE + 21;
+ public static final int DAEMON_STARTUP = 19;
/** @hide */
- public static final int DAEMON_STARTUP = BASE + 22;
+ public static final int ENABLE = 20;
+ /** @hide */
+ public static final int DISABLE = 21;
/** @hide */
- public static final int ENABLE = BASE + 24;
- /** @hide */
- public static final int DISABLE = BASE + 25;
+ public static final int NATIVE_DAEMON_EVENT = 22;
/** @hide */
- public static final int NATIVE_DAEMON_EVENT = BASE + 26;
+ public static final int REGISTER_CLIENT = 23;
+ /** @hide */
+ public static final int UNREGISTER_CLIENT = 24;
/** Dns based service discovery protocol */
public static final int PROTOCOL_DNS_SD = 0x0001;
@@ -274,7 +271,7 @@
private static final int FIRST_LISTENER_KEY = 1;
- private final INsdManager mService;
+ private final INsdServiceConnector mService;
private final Context mContext;
private int mListenerKey = FIRST_LISTENER_KEY;
@@ -282,9 +279,7 @@
private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
private final Object mMapLock = new Object();
- private final AsyncChannel mAsyncChannel = new AsyncChannel();
- private ServiceHandler mHandler;
- private final CountDownLatch mConnected = new CountDownLatch(1);
+ private final ServiceHandler mHandler;
/**
* Create a new Nsd instance. Applications use
@@ -295,18 +290,108 @@
* is a system private class.
*/
public NsdManager(Context context, INsdManager service) {
- mService = service;
mContext = context;
- init();
+
+ HandlerThread t = new HandlerThread("NsdManager");
+ t.start();
+ mHandler = new ServiceHandler(t.getLooper());
+
+ try {
+ mService = service.connect(new NsdCallbackImpl(mHandler));
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to connect to NsdService");
+ }
+
+ // Only proactively start the daemon if the target SDK < S, otherwise the internal service
+ // would automatically start/stop the native daemon as needed.
+ if (!CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
+ try {
+ mService.startDaemon();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to proactively start daemon");
+ // Continue: the daemon can still be started on-demand later
+ }
+ }
}
- /**
- * @hide
- */
- @VisibleForTesting
- public void disconnect() {
- mAsyncChannel.disconnect();
- mHandler.getLooper().quitSafely();
+ private static class NsdCallbackImpl extends INsdManagerCallback.Stub {
+ private final Handler mServHandler;
+
+ NsdCallbackImpl(Handler serviceHandler) {
+ mServHandler = serviceHandler;
+ }
+
+ private void sendInfo(int message, int listenerKey, NsdServiceInfo info) {
+ mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey, info));
+ }
+
+ private void sendError(int message, int listenerKey, int error) {
+ mServHandler.sendMessage(mServHandler.obtainMessage(message, error, listenerKey));
+ }
+
+ private void sendNoArg(int message, int listenerKey) {
+ mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey));
+ }
+
+ @Override
+ public void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
+ sendInfo(DISCOVER_SERVICES_STARTED, listenerKey, info);
+ }
+
+ @Override
+ public void onDiscoverServicesFailed(int listenerKey, int error) {
+ sendError(DISCOVER_SERVICES_FAILED, listenerKey, error);
+ }
+
+ @Override
+ public void onServiceFound(int listenerKey, NsdServiceInfo info) {
+ sendInfo(SERVICE_FOUND, listenerKey, info);
+ }
+
+ @Override
+ public void onServiceLost(int listenerKey, NsdServiceInfo info) {
+ sendInfo(SERVICE_LOST, listenerKey, info);
+ }
+
+ @Override
+ public void onStopDiscoveryFailed(int listenerKey, int error) {
+ sendError(STOP_DISCOVERY_FAILED, listenerKey, error);
+ }
+
+ @Override
+ public void onStopDiscoverySucceeded(int listenerKey) {
+ sendNoArg(STOP_DISCOVERY_SUCCEEDED, listenerKey);
+ }
+
+ @Override
+ public void onRegisterServiceFailed(int listenerKey, int error) {
+ sendError(REGISTER_SERVICE_FAILED, listenerKey, error);
+ }
+
+ @Override
+ public void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+ sendInfo(REGISTER_SERVICE_SUCCEEDED, listenerKey, info);
+ }
+
+ @Override
+ public void onUnregisterServiceFailed(int listenerKey, int error) {
+ sendError(UNREGISTER_SERVICE_FAILED, listenerKey, error);
+ }
+
+ @Override
+ public void onUnregisterServiceSucceeded(int listenerKey) {
+ sendNoArg(UNREGISTER_SERVICE_SUCCEEDED, listenerKey);
+ }
+
+ @Override
+ public void onResolveServiceFailed(int listenerKey, int error) {
+ sendError(RESOLVE_SERVICE_FAILED, listenerKey, error);
+ }
+
+ @Override
+ public void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+ sendInfo(RESOLVE_SERVICE_SUCCEEDED, listenerKey, info);
+ }
}
/**
@@ -376,19 +461,6 @@
public void handleMessage(Message message) {
final int what = message.what;
final int key = message.arg2;
- switch (what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- return;
- case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
- mConnected.countDown();
- return;
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- Log.e(TAG, "Channel lost");
- return;
- default:
- break;
- }
final Object listener;
final NsdServiceInfo ns;
synchronized (mMapLock) {
@@ -474,7 +546,9 @@
final int key;
synchronized (mMapLock) {
int valueIndex = mListenerMap.indexOfValue(listener);
- checkArgument(valueIndex == -1, "listener already in use");
+ if (valueIndex != -1) {
+ throw new IllegalArgumentException("listener already in use");
+ }
key = nextListenerKey();
mListenerMap.put(key, listener);
mServiceMap.put(key, s);
@@ -493,7 +567,9 @@
checkListener(listener);
synchronized (mMapLock) {
int valueIndex = mListenerMap.indexOfValue(listener);
- checkArgument(valueIndex != -1, "listener not registered");
+ if (valueIndex == -1) {
+ throw new IllegalArgumentException("listener not registered");
+ }
return mListenerMap.keyAt(valueIndex);
}
}
@@ -504,36 +580,6 @@
}
/**
- * Initialize AsyncChannel
- */
- private void init() {
- final Messenger messenger = getMessenger();
- if (messenger == null) {
- fatal("Failed to obtain service Messenger");
- }
- HandlerThread t = new HandlerThread("NsdManager");
- t.start();
- mHandler = new ServiceHandler(t.getLooper());
- mAsyncChannel.connect(mContext, mHandler, messenger);
- try {
- mConnected.await();
- } catch (InterruptedException e) {
- fatal("Interrupted wait at init");
- }
- if (CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
- return;
- }
- // Only proactively start the daemon if the target SDK < S, otherwise the internal service
- // would automatically start/stop the native daemon as needed.
- mAsyncChannel.sendMessage(DAEMON_STARTUP);
- }
-
- private static void fatal(String msg) {
- Log.e(TAG, msg);
- throw new RuntimeException(msg);
- }
-
- /**
* Register a service to be discovered by other services.
*
* <p> The function call immediately returns after sending a request to register service
@@ -552,11 +598,17 @@
*/
public void registerService(NsdServiceInfo serviceInfo, int protocolType,
RegistrationListener listener) {
- checkArgument(serviceInfo.getPort() > 0, "Invalid port number");
+ if (serviceInfo.getPort() <= 0) {
+ throw new IllegalArgumentException("Invalid port number");
+ }
checkServiceInfo(serviceInfo);
checkProtocol(protocolType);
int key = putListener(listener, serviceInfo);
- mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo);
+ try {
+ mService.registerService(key, serviceInfo);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
}
/**
@@ -574,7 +626,11 @@
*/
public void unregisterService(RegistrationListener listener) {
int id = getListenerKey(listener);
- mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id);
+ try {
+ mService.unregisterService(id);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
}
/**
@@ -606,14 +662,20 @@
* Cannot be null. Cannot be in use for an active service discovery.
*/
public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
- checkStringNotEmpty(serviceType, "Service type cannot be empty");
+ if (TextUtils.isEmpty(serviceType)) {
+ throw new IllegalArgumentException("Service type cannot be empty");
+ }
checkProtocol(protocolType);
NsdServiceInfo s = new NsdServiceInfo();
s.setServiceType(serviceType);
int key = putListener(listener, s);
- mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s);
+ try {
+ mService.discoverServices(key, s);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
}
/**
@@ -634,7 +696,11 @@
*/
public void stopServiceDiscovery(DiscoveryListener listener) {
int id = getListenerKey(listener);
- mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id);
+ try {
+ mService.stopDiscovery(id);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
}
/**
@@ -649,43 +715,30 @@
public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
checkServiceInfo(serviceInfo);
int key = putListener(listener, serviceInfo);
- mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo);
- }
-
- /** Internal use only @hide */
- public void setEnabled(boolean enabled) {
try {
- mService.setEnabled(enabled);
+ mService.resolveService(key, serviceInfo);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get a reference to NsdService handler. This is used to establish
- * an AsyncChannel communication with the service
- *
- * @return Messenger pointing to the NsdService handler
- */
- private Messenger getMessenger() {
- try {
- return mService.getMessenger();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ e.rethrowFromSystemServer();
}
}
private static void checkListener(Object listener) {
- checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
}
private static void checkProtocol(int protocolType) {
- checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol");
+ if (protocolType != PROTOCOL_DNS_SD) {
+ throw new IllegalArgumentException("Unsupported protocol");
+ }
}
private static void checkServiceInfo(NsdServiceInfo serviceInfo) {
- checkNotNull(serviceInfo, "NsdServiceInfo cannot be null");
- checkStringNotEmpty(serviceInfo.getServiceName(), "Service name cannot be empty");
- checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty");
+ Objects.requireNonNull(serviceInfo, "NsdServiceInfo cannot be null");
+ if (TextUtils.isEmpty(serviceInfo.getServiceName())) {
+ throw new IllegalArgumentException("Service name cannot be empty");
+ }
+ if (TextUtils.isEmpty(serviceInfo.getServiceType())) {
+ throw new IllegalArgumentException("Service type cannot be empty");
+ }
}
}
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/framework-t/src/android/net/nsd/NsdServiceInfo.java
similarity index 100%
rename from core/java/android/net/nsd/NsdServiceInfo.java
rename to framework-t/src/android/net/nsd/NsdServiceInfo.java
diff --git a/core/java/android/net/NetworkStats.aidl b/framework/aidl-export/android/net/NetworkStats.aidl
similarity index 100%
rename from core/java/android/net/NetworkStats.aidl
rename to framework/aidl-export/android/net/NetworkStats.aidl
diff --git a/core/java/android/net/NetworkTemplate.aidl b/framework/aidl-export/android/net/NetworkTemplate.aidl
similarity index 100%
rename from core/java/android/net/NetworkTemplate.aidl
rename to framework/aidl-export/android/net/NetworkTemplate.aidl
diff --git a/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl b/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl
new file mode 100644
index 0000000..657bdd1
--- /dev/null
+++ b/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.nsd;
+
+@JavaOnlyStableParcelable parcelable NsdServiceInfo;
\ No newline at end of file
diff --git a/service-t/Sources.bp b/service-t/Sources.bp
new file mode 100644
index 0000000..97dfb64
--- /dev/null
+++ b/service-t/Sources.bp
@@ -0,0 +1,89 @@
+//
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// NetworkStats related libraries.
+
+filegroup {
+ name: "services.connectivity-netstats-sources",
+ srcs: [
+ "src/com/android/server/net/NetworkIdentity*.java",
+ "src/com/android/server/net/NetworkStats*.java",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// Nsd related libraries.
+
+filegroup {
+ name: "services.connectivity-nsd-sources",
+ srcs: [
+ "src/com/android/server/INativeDaemon*.java",
+ "src/com/android/server/NativeDaemon*.java",
+ "src/com/android/server/Nsd*.java",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// IpSec related libraries.
+
+filegroup {
+ name: "services.connectivity-ipsec-sources",
+ srcs: [
+ "src/com/android/server/IpSecService.java",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+// Ethernet related libraries.
+
+filegroup {
+ name: "services.connectivity-ethernet-sources",
+ srcs: [
+ "src/com/android/server/net/IpConfigStore.java",
+ ],
+ path: "src",
+ visibility: [
+ "//frameworks/opt/net/ethernet",
+ ],
+}
+
+// Connectivity-T common libraries.
+
+filegroup {
+ name: "services.connectivity-tiramisu-sources",
+ srcs: [
+ ":services.connectivity-ethernet-sources",
+ ":services.connectivity-ipsec-sources",
+ ":services.connectivity-netstats-sources",
+ ":services.connectivity-nsd-sources",
+ ],
+ path: "src",
+ visibility: ["//frameworks/base/services/core"],
+}
diff --git a/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java b/service-t/src/com/android/server/INativeDaemonConnectorCallbacks.java
similarity index 100%
rename from services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java
rename to service-t/src/com/android/server/INativeDaemonConnectorCallbacks.java
diff --git a/services/core/java/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
similarity index 90%
rename from services/core/java/com/android/server/IpSecService.java
rename to service-t/src/com/android/server/IpSecService.java
index d6ee951..179d945 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -45,7 +45,6 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.TrafficStats;
-import android.net.util.NetdService;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -58,13 +57,13 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.Range;
-import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
@@ -96,8 +95,6 @@
public class IpSecService extends IIpSecService.Stub {
private static final String TAG = "IpSecService";
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-
- private static final String NETD_SERVICE_NAME = "netd";
private static final int[] ADDRESS_FAMILIES =
new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
@@ -106,6 +103,8 @@
@VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
+ private final INetd mNetd;
+
static {
try {
INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
@@ -119,6 +118,7 @@
/* Binder context for this service */
private final Context mContext;
+ private final Dependencies mDeps;
/**
* The next non-repeating global ID for tracking resources between users, this service, and
@@ -129,23 +129,24 @@
@GuardedBy("IpSecService.this")
private int mNextResourceId = 1;
- interface IpSecServiceConfiguration {
- INetd getNetdInstance() throws RemoteException;
-
- static IpSecServiceConfiguration GETSRVINSTANCE =
- new IpSecServiceConfiguration() {
- @Override
- public INetd getNetdInstance() throws RemoteException {
- final INetd netd = NetdService.getInstance();
- if (netd == null) {
- throw new RemoteException("Failed to Get Netd Instance");
- }
- return netd;
- }
- };
+ /**
+ * Dependencies of IpSecService, for injection in tests.
+ */
+ @VisibleForTesting
+ public static class Dependencies {
+ /**
+ * Get a reference to INetd.
+ */
+ public INetd getNetdInstance(Context context) throws RemoteException {
+ final INetd netd = INetd.Stub.asInterface((IBinder)
+ context.getSystemService(Context.NETD_SERVICE));
+ if (netd == null) {
+ throw new RemoteException("Failed to Get Netd Instance");
+ }
+ return netd;
+ }
}
- private final IpSecServiceConfiguration mSrvConfig;
final UidFdTagger mUidFdTagger;
/**
@@ -491,8 +492,8 @@
* <p>This class associates kernel resources with the UID that owns and controls them.
*/
private abstract class OwnedResourceRecord implements IResource {
- final int pid;
- final int uid;
+ final int mPid;
+ final int mUid;
protected final int mResourceId;
OwnedResourceRecord(int resourceId) {
@@ -501,8 +502,8 @@
throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
}
mResourceId = resourceId;
- pid = Binder.getCallingPid();
- uid = Binder.getCallingUid();
+ mPid = Binder.getCallingPid();
+ mUid = Binder.getCallingUid();
getResourceTracker().take();
}
@@ -512,7 +513,7 @@
/** Convenience method; retrieves the user resource record for the stored UID. */
protected UserRecord getUserRecord() {
- return mUserResourceTracker.getUserRecord(uid);
+ return mUserResourceTracker.getUserRecord(mUid);
}
@Override
@@ -527,9 +528,9 @@
.append("{mResourceId=")
.append(mResourceId)
.append(", pid=")
- .append(pid)
+ .append(mPid)
.append(", uid=")
- .append(uid)
+ .append(mUid)
.append("}")
.toString();
}
@@ -545,7 +546,7 @@
SparseArray<RefcountedResource<T>> mArray = new SparseArray<>();
private final String mTypeName;
- public RefcountedResourceArray(String typeName) {
+ RefcountedResourceArray(String typeName) {
this.mTypeName = typeName;
}
@@ -625,16 +626,14 @@
public void freeUnderlyingResources() {
int spi = mSpi.getSpi();
try {
- mSrvConfig
- .getNetdInstance()
- .ipSecDeleteSecurityAssociation(
- uid,
- mConfig.getSourceAddress(),
- mConfig.getDestinationAddress(),
- spi,
- mConfig.getMarkValue(),
- mConfig.getMarkMask(),
- mConfig.getXfrmInterfaceId());
+ mNetd.ipSecDeleteSecurityAssociation(
+ mUid,
+ mConfig.getSourceAddress(),
+ mConfig.getDestinationAddress(),
+ spi,
+ mConfig.getMarkValue(),
+ mConfig.getMarkMask(),
+ mConfig.getXfrmInterfaceId());
} catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
}
@@ -681,7 +680,8 @@
private boolean mOwnedByTransform = false;
- SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) {
+ SpiRecord(int resourceId, String sourceAddress,
+ String destinationAddress, int spi) {
super(resourceId);
mSourceAddress = sourceAddress;
mDestinationAddress = destinationAddress;
@@ -693,11 +693,9 @@
public void freeUnderlyingResources() {
try {
if (!mOwnedByTransform) {
- mSrvConfig
- .getNetdInstance()
- .ipSecDeleteSecurityAssociation(
- uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
- 0 /* mask */, 0 /* if_id */);
+ mNetd.ipSecDeleteSecurityAssociation(
+ mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
+ 0 /* mask */, 0 /* if_id */);
}
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
@@ -844,19 +842,18 @@
// Teardown VTI
// Delete global policies
try {
- final INetd netd = mSrvConfig.getNetdInstance();
- netd.ipSecRemoveTunnelInterface(mInterfaceName);
+ mNetd.ipSecRemoveTunnelInterface(mInterfaceName);
for (int selAddrFamily : ADDRESS_FAMILIES) {
- netd.ipSecDeleteSecurityPolicy(
- uid,
+ mNetd.ipSecDeleteSecurityPolicy(
+ mUid,
selAddrFamily,
IpSecManager.DIRECTION_OUT,
mOkey,
0xffffffff,
mIfId);
- netd.ipSecDeleteSecurityPolicy(
- uid,
+ mNetd.ipSecDeleteSecurityPolicy(
+ mUid,
selAddrFamily,
IpSecManager.DIRECTION_IN,
mIkey,
@@ -1012,29 +1009,28 @@
* @param context Binder context for this service
*/
private IpSecService(Context context) {
- this(context, IpSecServiceConfiguration.GETSRVINSTANCE);
+ this(context, new Dependencies());
}
static IpSecService create(Context context)
throws InterruptedException {
final IpSecService service = new IpSecService(context);
- service.connectNativeNetdService();
return service;
}
@NonNull
private AppOpsManager getAppOpsManager() {
AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps");
+ if (appOps == null) throw new RuntimeException("System Server couldn't get AppOps");
return appOps;
}
/** @hide */
@VisibleForTesting
- public IpSecService(Context context, IpSecServiceConfiguration config) {
+ public IpSecService(Context context, Dependencies deps) {
this(
context,
- config,
+ deps,
(fd, uid) -> {
try {
TrafficStats.setThreadStatsUid(uid);
@@ -1047,40 +1043,32 @@
/** @hide */
@VisibleForTesting
- public IpSecService(Context context, IpSecServiceConfiguration config,
- UidFdTagger uidFdTagger) {
+ public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) {
mContext = context;
- mSrvConfig = config;
+ mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
mUidFdTagger = uidFdTagger;
- }
-
- public void systemReady() {
- if (isNetdAlive()) {
- Slog.d(TAG, "IpSecService is ready");
- } else {
- Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
+ try {
+ mNetd = mDeps.getNetdInstance(mContext);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
- private void connectNativeNetdService() {
- // Avoid blocking the system server to do this
- new Thread() {
- @Override
- public void run() {
- synchronized (IpSecService.this) {
- NetdService.get(NETD_FETCH_TIMEOUT_MS);
- }
- }
- }.start();
+ /** Called by system server when system is ready. */
+ public void systemReady() {
+ if (isNetdAlive()) {
+ Log.d(TAG, "IpSecService is ready");
+ } else {
+ Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
+ }
}
synchronized boolean isNetdAlive() {
try {
- final INetd netd = mSrvConfig.getNetdInstance();
- if (netd == null) {
+ if (mNetd == null) {
return false;
}
- return netd.isAlive();
+ return mNetd.isAlive();
} catch (RemoteException re) {
return false;
}
@@ -1141,15 +1129,13 @@
IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
}
- spi =
- mSrvConfig
- .getNetdInstance()
- .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
+ spi = mNetd.ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
Log.d(TAG, "Allocated SPI " + spi);
userRecord.mSpiRecords.put(
resourceId,
new RefcountedResource<SpiRecord>(
- new SpiRecord(resourceId, "", destinationAddress, spi), binder));
+ new SpiRecord(resourceId, "",
+ destinationAddress, spi), binder));
} catch (ServiceSpecificException e) {
if (e.errorCode == OsConstants.ENOENT) {
return new IpSecSpiResponse(
@@ -1229,7 +1215,7 @@
* <p>Since the socket is created on behalf of an unprivileged application, all traffic
* should be accounted to the UID of the unprivileged application.
*/
- public void tag(FileDescriptor fd, int uid) throws IOException;
+ void tag(FileDescriptor fd, int uid) throws IOException;
}
/**
@@ -1250,38 +1236,53 @@
int callingUid = Binder.getCallingUid();
UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
final int resourceId = mNextResourceId++;
- FileDescriptor sockFd = null;
+
+ ParcelFileDescriptor pFd = null;
try {
if (!userRecord.mSocketQuotaTracker.isAvailable()) {
return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
- sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- mUidFdTagger.tag(sockFd, callingUid);
+ FileDescriptor sockFd = null;
+ try {
+ sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ pFd = ParcelFileDescriptor.dup(sockFd);
+ } finally {
+ IoUtils.closeQuietly(sockFd);
+ }
+ mUidFdTagger.tag(pFd.getFileDescriptor(), callingUid);
// This code is common to both the unspecified and specified port cases
Os.setsockoptInt(
- sockFd,
+ pFd.getFileDescriptor(),
OsConstants.IPPROTO_UDP,
OsConstants.UDP_ENCAP,
OsConstants.UDP_ENCAP_ESPINUDP);
- mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(
- new ParcelFileDescriptor(sockFd), callingUid);
+ mNetd.ipSecSetEncapSocketOwner(pFd, callingUid);
if (port != 0) {
Log.v(TAG, "Binding to port " + port);
- Os.bind(sockFd, INADDR_ANY, port);
+ Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port);
} else {
- port = bindToRandomPort(sockFd);
+ port = bindToRandomPort(pFd.getFileDescriptor());
}
userRecord.mEncapSocketRecords.put(
resourceId,
new RefcountedResource<EncapSocketRecord>(
- new EncapSocketRecord(resourceId, sockFd, port), binder));
- return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port, sockFd);
+ new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port),
+ binder));
+ return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port,
+ pFd.getFileDescriptor());
} catch (IOException | ErrnoException e) {
- IoUtils.closeQuietly(sockFd);
+ try {
+ if (pFd != null) {
+ pFd.close();
+ }
+ } catch (IOException ex) {
+ // Nothing can be done at this point
+ Log.e(TAG, "Failed to close pFd.");
+ }
}
// If we make it to here, then something has gone wrong and we couldn't open a socket.
// The only reasonable condition that would cause that is resource unavailable.
@@ -1329,16 +1330,15 @@
// Create VTI
// Add inbound/outbound global policies
// (use reqid = 0)
- final INetd netd = mSrvConfig.getNetdInstance();
- netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
+ mNetd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
- Binder.withCleanCallingIdentity(() -> {
- NetdUtils.setInterfaceUp(netd, intfName);
+ BinderUtils.withCleanCallingIdentity(() -> {
+ NetdUtils.setInterfaceUp(mNetd, intfName);
});
for (int selAddrFamily : ADDRESS_FAMILIES) {
// Always send down correct local/remote addresses for template.
- netd.ipSecAddSecurityPolicy(
+ mNetd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
IpSecManager.DIRECTION_OUT,
@@ -1348,7 +1348,7 @@
okey,
0xffffffff,
resourceId);
- netd.ipSecAddSecurityPolicy(
+ mNetd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
IpSecManager.DIRECTION_IN,
@@ -1368,7 +1368,7 @@
//
// This is necessary only on the tunnel interface, and not any the interface to
// which traffic will be forwarded to.
- netd.ipSecAddSecurityPolicy(
+ mNetd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
IpSecManager.DIRECTION_FWD,
@@ -1425,12 +1425,10 @@
try {
// We can assume general validity of the IP address, since we get them as a
// LinkAddress, which does some validation.
- mSrvConfig
- .getNetdInstance()
- .interfaceAddAddress(
- tunnelInterfaceInfo.mInterfaceName,
- localAddr.getAddress().getHostAddress(),
- localAddr.getPrefixLength());
+ mNetd.interfaceAddAddress(
+ tunnelInterfaceInfo.mInterfaceName,
+ localAddr.getAddress().getHostAddress(),
+ localAddr.getPrefixLength());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1454,9 +1452,7 @@
try {
// We can assume general validity of the IP address, since we get them as a
// LinkAddress, which does some validation.
- mSrvConfig
- .getNetdInstance()
- .interfaceDelAddress(
+ mNetd.interfaceDelAddress(
tunnelInterfaceInfo.mInterfaceName,
localAddr.getAddress().getHostAddress(),
localAddr.getPrefixLength());
@@ -1669,30 +1665,28 @@
cryptName = crypt.getName();
}
- mSrvConfig
- .getNetdInstance()
- .ipSecAddSecurityAssociation(
- Binder.getCallingUid(),
- c.getMode(),
- c.getSourceAddress(),
- c.getDestinationAddress(),
- (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
- spiRecord.getSpi(),
- c.getMarkValue(),
- c.getMarkMask(),
- (auth != null) ? auth.getName() : "",
- (auth != null) ? auth.getKey() : new byte[] {},
- (auth != null) ? auth.getTruncationLengthBits() : 0,
- cryptName,
- (crypt != null) ? crypt.getKey() : new byte[] {},
- (crypt != null) ? crypt.getTruncationLengthBits() : 0,
- (authCrypt != null) ? authCrypt.getName() : "",
- (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
- (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
- encapType,
- encapLocalPort,
- encapRemotePort,
- c.getXfrmInterfaceId());
+ mNetd.ipSecAddSecurityAssociation(
+ Binder.getCallingUid(),
+ c.getMode(),
+ c.getSourceAddress(),
+ c.getDestinationAddress(),
+ (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
+ spiRecord.getSpi(),
+ c.getMarkValue(),
+ c.getMarkMask(),
+ (auth != null) ? auth.getName() : "",
+ (auth != null) ? auth.getKey() : new byte[] {},
+ (auth != null) ? auth.getTruncationLengthBits() : 0,
+ cryptName,
+ (crypt != null) ? crypt.getKey() : new byte[] {},
+ (crypt != null) ? crypt.getTruncationLengthBits() : 0,
+ (authCrypt != null) ? authCrypt.getName() : "",
+ (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
+ (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
+ encapType,
+ encapLocalPort,
+ encapRemotePort,
+ c.getXfrmInterfaceId());
}
/**
@@ -1771,7 +1765,7 @@
TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
// TODO: make this a function.
- if (info.pid != getCallingPid() || info.uid != callingUid) {
+ if (info.mPid != getCallingPid() || info.mUid != callingUid) {
throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
}
@@ -1781,15 +1775,13 @@
c.getMode() == IpSecTransform.MODE_TRANSPORT,
"Transform mode was not Transport mode; cannot be applied to a socket");
- mSrvConfig
- .getNetdInstance()
- .ipSecApplyTransportModeTransform(
- socket,
- callingUid,
- direction,
- c.getSourceAddress(),
- c.getDestinationAddress(),
- info.getSpiRecord().getSpi());
+ mNetd.ipSecApplyTransportModeTransform(
+ socket,
+ callingUid,
+ direction,
+ c.getSourceAddress(),
+ c.getDestinationAddress(),
+ info.getSpiRecord().getSpi());
}
/**
@@ -1801,9 +1793,7 @@
@Override
public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
throws RemoteException {
- mSrvConfig
- .getNetdInstance()
- .ipSecRemoveTransportModeTransform(socket);
+ mNetd.ipSecRemoveTransportModeTransform(socket);
}
/**
@@ -1878,18 +1868,16 @@
// Always update the policy with the relevant XFRM_IF_ID
for (int selAddrFamily : ADDRESS_FAMILIES) {
- mSrvConfig
- .getNetdInstance()
- .ipSecUpdateSecurityPolicy(
- callingUid,
- selAddrFamily,
- direction,
- transformInfo.getConfig().getSourceAddress(),
- transformInfo.getConfig().getDestinationAddress(),
- spi, // If outbound, also add SPI to the policy.
- mark, // Must always set policy mark; ikey/okey for VTIs
- 0xffffffff,
- c.getXfrmInterfaceId());
+ mNetd.ipSecUpdateSecurityPolicy(
+ callingUid,
+ selAddrFamily,
+ direction,
+ transformInfo.getConfig().getSourceAddress(),
+ transformInfo.getConfig().getDestinationAddress(),
+ spi, // If outbound, also add SPI to the policy.
+ mark, // Must always set policy mark; ikey/okey for VTIs
+ 0xffffffff,
+ c.getXfrmInterfaceId());
}
// Update SA with tunnel mark (ikey or okey based on direction)
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/service-t/src/com/android/server/NativeDaemonConnector.java
similarity index 93%
rename from services/core/java/com/android/server/NativeDaemonConnector.java
rename to service-t/src/com/android/server/NativeDaemonConnector.java
index eac767f..ec8d779 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/service-t/src/com/android/server/NativeDaemonConnector.java
@@ -20,18 +20,15 @@
import android.net.LocalSocketAddress;
import android.os.Build;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.util.LocalLog;
-import android.util.Slog;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-import com.android.server.power.ShutdownThread;
-import com.google.android.collect.Lists;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -40,19 +37,19 @@
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.LinkedList;
+import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.LinkedList;
-import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Generic connector class for interfacing with a native daemon which uses the
* {@code libsysutils} FrameworkListener protocol.
*/
-final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
+final class NativeDaemonConnector implements Runnable, Handler.Callback {
private final static boolean VDBG = false;
private final String TAG;
@@ -85,13 +82,6 @@
NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
- this(callbacks, socket, responseQueueSize, logTag, maxLogSize, wl,
- FgThread.get().getLooper());
- }
-
- NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
- int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
- Looper looper) {
mCallbacks = callbacks;
mSocket = socket;
mResponseQueue = new ResponseQueue(responseQueueSize);
@@ -99,15 +89,17 @@
if (mWakeLock != null) {
mWakeLock.setReferenceCounted(true);
}
- mLooper = looper;
mSequenceNumber = new AtomicInteger(0);
TAG = logTag != null ? logTag : "NativeDaemonConnector";
mLocalLog = new LocalLog(maxLogSize);
+ final HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ mLooper = thread.getLooper();
}
/**
* Enable Set debugging mode, which causes messages to also be written to both
- * {@link Slog} in addition to internal log.
+ * {@link Log} in addition to internal log.
*/
public void setDebug(boolean debug) {
mDebug = debug;
@@ -126,7 +118,9 @@
* calls while holding a lock on the given object.
*/
public void setWarnIfHeld(Object warnIfHeld) {
- Preconditions.checkState(mWarnIfHeld == null);
+ if (mWarnIfHeld != null) {
+ throw new IllegalStateException("warnIfHeld is already set.");
+ }
mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
}
@@ -135,23 +129,15 @@
mCallbackHandler = new Handler(mLooper, this);
while (true) {
- if (isShuttingDown()) break;
try {
listenToSocket();
} catch (Exception e) {
loge("Error in NativeDaemonConnector: " + e);
- if (isShuttingDown()) break;
SystemClock.sleep(5000);
}
}
}
- private static boolean isShuttingDown() {
- String shutdownAct = SystemProperties.get(
- ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
- return shutdownAct != null && shutdownAct.length() > 0;
- }
-
@Override
public boolean handleMessage(Message msg) {
final String event = (String) msg.obj;
@@ -183,7 +169,7 @@
// In order to ensure that unprivileged apps aren't able to impersonate native daemons on
// production devices, even if said native daemons ill-advisedly pick a socket name that
// starts with __test__, only allow this on debug builds.
- if (mSocket.startsWith("__test__") && Build.IS_DEBUGGABLE) {
+ if (mSocket.startsWith("__test__") && Build.isDebuggable()) {
return new LocalSocketAddress(mSocket);
} else {
return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED);
@@ -375,7 +361,7 @@
try {
latch.await();
} catch (InterruptedException e) {
- Slog.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
+ Log.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
}
}
@@ -462,13 +448,13 @@
public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
throws NativeDaemonConnectorException {
if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ Log.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
}
final long startTime = SystemClock.elapsedRealtime();
- final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
+ final ArrayList<NativeDaemonEvent> events = new ArrayList<>();
final StringBuilder rawBuilder = new StringBuilder();
final StringBuilder logBuilder = new StringBuilder();
@@ -571,7 +557,7 @@
*/
public static class Command {
private String mCmd;
- private ArrayList<Object> mArguments = Lists.newArrayList();
+ private ArrayList<Object> mArguments = new ArrayList<>();
public Command(String cmd, Object... args) {
mCmd = cmd;
@@ -586,11 +572,6 @@
}
}
- /** {@inheritDoc} */
- public void monitor() {
- synchronized (mDaemonLock) { }
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mLocalLog.dump(fd, pw, args);
pw.println();
@@ -598,12 +579,12 @@
}
private void log(String logstring) {
- if (mDebug) Slog.d(TAG, logstring);
+ if (mDebug) Log.d(TAG, logstring);
mLocalLog.log(logstring);
}
private void loge(String logstring) {
- Slog.e(TAG, logstring);
+ Log.e(TAG, logstring);
mLocalLog.log(logstring);
}
@@ -659,12 +640,12 @@
if (found == null) {
// didn't find it - make sure our queue isn't too big before adding
while (mPendingCmds.size() >= mMaxCount) {
- Slog.e("NativeDaemonConnector.ResponseQueue",
+ Log.e("NativeDaemonConnector.ResponseQueue",
"more buffered than allowed: " + mPendingCmds.size() +
" >= " + mMaxCount);
// let any waiter timeout waiting for this
PendingCmd pendingCmd = mPendingCmds.remove();
- Slog.e("NativeDaemonConnector.ResponseQueue",
+ Log.e("NativeDaemonConnector.ResponseQueue",
"Removing request: " + pendingCmd.logCmd + " (" +
pendingCmd.cmdNum + ")");
}
@@ -706,7 +687,7 @@
result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {}
if (result == null) {
- Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
+ Log.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
}
return result;
}
diff --git a/services/core/java/com/android/server/NativeDaemonConnectorException.java b/service-t/src/com/android/server/NativeDaemonConnectorException.java
similarity index 100%
rename from services/core/java/com/android/server/NativeDaemonConnectorException.java
rename to service-t/src/com/android/server/NativeDaemonConnectorException.java
diff --git a/services/core/java/com/android/server/NativeDaemonEvent.java b/service-t/src/com/android/server/NativeDaemonEvent.java
similarity index 93%
rename from services/core/java/com/android/server/NativeDaemonEvent.java
rename to service-t/src/com/android/server/NativeDaemonEvent.java
index e6feda3..5683694 100644
--- a/services/core/java/com/android/server/NativeDaemonEvent.java
+++ b/service-t/src/com/android/server/NativeDaemonEvent.java
@@ -16,8 +16,7 @@
package com.android.server;
-import android.util.Slog;
-import com.google.android.collect.Lists;
+import android.util.Log;
import java.io.FileDescriptor;
import java.util.ArrayList;
@@ -179,7 +178,7 @@
* {@link #getMessage()} for any events matching the requested code.
*/
public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
- final ArrayList<String> result = Lists.newArrayList();
+ final ArrayList<String> result = new ArrayList<>();
for (NativeDaemonEvent event : events) {
if (event.getCode() == matchCode) {
result.add(event.getMessage());
@@ -212,7 +211,7 @@
int wordEnd = -1;
boolean quoted = false;
- if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'");
+ if (DEBUG_ROUTINE) Log.e(LOGTAG, "parsing '" + rawEvent + "'");
if (rawEvent.charAt(current) == '\"') {
quoted = true;
current++;
@@ -240,14 +239,14 @@
word = word.replace("\\\\", "\\");
word = word.replace("\\\"", "\"");
- if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'");
+ if (DEBUG_ROUTINE) Log.e(LOGTAG, "found '" + word + "'");
parsed.add(word);
// find the beginning of the next word - either of these options
int nextSpace = rawEvent.indexOf(' ', current);
int nextQuote = rawEvent.indexOf(" \"", current);
if (DEBUG_ROUTINE) {
- Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
+ Log.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
}
if (nextQuote > -1 && nextQuote <= nextSpace) {
quoted = true;
@@ -259,8 +258,8 @@
}
} // else we just start the next word after the current and read til the end
if (DEBUG_ROUTINE) {
- Slog.e(LOGTAG, "next loop - current=" + current +
- ", length=" + length + ", quoted=" + quoted);
+ Log.e(LOGTAG, "next loop - current=" + current
+ + ", length=" + length + ", quoted=" + quoted);
}
}
return parsed.toArray(new String[parsed.size()]);
diff --git a/services/core/java/com/android/server/NativeDaemonTimeoutException.java b/service-t/src/com/android/server/NativeDaemonTimeoutException.java
similarity index 100%
rename from services/core/java/com/android/server/NativeDaemonTimeoutException.java
rename to service-t/src/com/android/server/NativeDaemonTimeoutException.java
diff --git a/services/core/java/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
similarity index 64%
rename from services/core/java/com/android/server/NsdService.java
rename to service-t/src/com/android/server/NsdService.java
index c9608a5..497107d 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -16,29 +16,27 @@
package com.android.server;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
-import android.net.NetworkStack;
-import android.net.Uri;
+import android.content.pm.PackageManager;
import android.net.nsd.INsdManager;
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.INsdServiceConnector;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Message;
-import android.os.Messenger;
+import android.os.RemoteException;
import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Base64;
-import android.util.Slog;
+import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.DumpUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.net.module.util.DnsSdTxtRecord;
@@ -64,7 +62,6 @@
private static final long CLEANUP_DELAY_MS = 10000;
private final Context mContext;
- private final NsdSettings mNsdSettings;
private final NsdStateMachine mNsdStateMachine;
private final DaemonConnection mDaemon;
private final NativeCallbackReceiver mDaemonCallback;
@@ -72,12 +69,11 @@
/**
* Clients receiving asynchronous messages
*/
- private final HashMap<Messenger, ClientInfo> mClients = new HashMap<>();
+ private final HashMap<NsdServiceConnector, ClientInfo> mClients = new HashMap<>();
/* A map from unique id to client info */
private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
- private final AsyncChannel mReplyChannel = new AsyncChannel();
private final long mCleanupDelayMs;
private static final int INVALID_ID = 0;
@@ -120,94 +116,79 @@
this.removeMessages(NsdManager.DAEMON_CLEANUP);
}
- /**
- * Observes the NSD on/off setting, and takes action when changed.
- */
- private void registerForNsdSetting() {
- final ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- notifyEnabled(isNsdEnabled());
- }
- };
-
- final Uri uri = Settings.Global.getUriFor(Settings.Global.NSD_ON);
- mNsdSettings.registerContentObserver(uri, contentObserver);
- }
-
NsdStateMachine(String name, Handler handler) {
super(name, handler);
addState(mDefaultState);
addState(mDisabledState, mDefaultState);
addState(mEnabledState, mDefaultState);
- State initialState = isNsdEnabled() ? mEnabledState : mDisabledState;
+ State initialState = mEnabledState;
setInitialState(initialState);
setLogRecSize(25);
- registerForNsdSetting();
}
class DefaultState extends State {
@Override
public boolean processMessage(Message msg) {
- ClientInfo cInfo = null;
+ final ClientInfo cInfo;
+ final int clientId = msg.arg2;
switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- AsyncChannel c = (AsyncChannel) msg.obj;
- if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
- c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
- cInfo = new ClientInfo(c, msg.replyTo);
- mClients.put(msg.replyTo, cInfo);
- } else {
- Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
+ case NsdManager.REGISTER_CLIENT:
+ final Pair<NsdServiceConnector, INsdManagerCallback> arg =
+ (Pair<NsdServiceConnector, INsdManagerCallback>) msg.obj;
+ final INsdManagerCallback cb = arg.second;
+ try {
+ cb.asBinder().linkToDeath(arg.first, 0);
+ cInfo = new ClientInfo(cb);
+ mClients.put(arg.first, cInfo);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Client " + clientId + " has already died");
}
break;
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- switch (msg.arg1) {
- case AsyncChannel.STATUS_SEND_UNSUCCESSFUL:
- Slog.e(TAG, "Send failed, client connection lost");
- break;
- case AsyncChannel.STATUS_REMOTE_DISCONNECTION:
- if (DBG) Slog.d(TAG, "Client disconnected");
- break;
- default:
- if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
- break;
- }
-
- cInfo = mClients.get(msg.replyTo);
+ case NsdManager.UNREGISTER_CLIENT:
+ final NsdServiceConnector connector = (NsdServiceConnector) msg.obj;
+ cInfo = mClients.remove(connector);
if (cInfo != null) {
cInfo.expungeAllRequests();
- mClients.remove(msg.replyTo);
if (cInfo.isLegacy()) {
mLegacyClientCount -= 1;
}
}
maybeScheduleStop();
break;
- case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
- AsyncChannel ac = new AsyncChannel();
- ac.connect(mContext, getHandler(), msg.replyTo);
- break;
case NsdManager.DISCOVER_SERVICES:
- replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ cInfo = getClientInfoForReply(msg);
+ if (cInfo != null) {
+ cInfo.onDiscoverServicesFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ }
break;
case NsdManager.STOP_DISCOVERY:
- replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ cInfo = getClientInfoForReply(msg);
+ if (cInfo != null) {
+ cInfo.onStopDiscoveryFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ }
break;
case NsdManager.REGISTER_SERVICE:
- replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ cInfo = getClientInfoForReply(msg);
+ if (cInfo != null) {
+ cInfo.onRegisterServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ }
break;
case NsdManager.UNREGISTER_SERVICE:
- replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ cInfo = getClientInfoForReply(msg);
+ if (cInfo != null) {
+ cInfo.onUnregisterServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ }
break;
case NsdManager.RESOLVE_SERVICE:
- replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ cInfo = getClientInfoForReply(msg);
+ if (cInfo != null) {
+ cInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ }
break;
case NsdManager.DAEMON_CLEANUP:
mDaemon.maybeStop();
@@ -215,7 +196,7 @@
// This event should be only sent by the legacy (target SDK < S) clients.
// Mark the sending client as legacy.
case NsdManager.DAEMON_STARTUP:
- cInfo = mClients.get(msg.replyTo);
+ cInfo = getClientInfoForReply(msg);
if (cInfo != null) {
cancelStop();
cInfo.setLegacy();
@@ -225,11 +206,16 @@
break;
case NsdManager.NATIVE_DAEMON_EVENT:
default:
- Slog.e(TAG, "Unhandled " + msg);
+ Log.e(TAG, "Unhandled " + msg);
return NOT_HANDLED;
}
return HANDLED;
}
+
+ private ClientInfo getClientInfoForReply(Message msg) {
+ final ListenerArgs args = (ListenerArgs) msg.obj;
+ return mClients.get(args.connector);
+ }
}
class DisabledState extends State {
@@ -266,7 +252,7 @@
private boolean requestLimitReached(ClientInfo clientInfo) {
if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
- if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo);
+ if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo);
return true;
}
return false;
@@ -289,122 +275,119 @@
@Override
public boolean processMessage(Message msg) {
- ClientInfo clientInfo;
- NsdServiceInfo servInfo;
- int id;
+ final ClientInfo clientInfo;
+ final int id;
+ final int clientId = msg.arg2;
+ final ListenerArgs args;
switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- return NOT_HANDLED;
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- return NOT_HANDLED;
case NsdManager.DISABLE:
//TODO: cleanup clients
transitionTo(mDisabledState);
break;
case NsdManager.DISCOVER_SERVICES:
- if (DBG) Slog.d(TAG, "Discover services");
- servInfo = (NsdServiceInfo) msg.obj;
- clientInfo = mClients.get(msg.replyTo);
+ if (DBG) Log.d(TAG, "Discover services");
+ args = (ListenerArgs) msg.obj;
+ clientInfo = mClients.get(args.connector);
if (requestLimitReached(clientInfo)) {
- replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
- NsdManager.FAILURE_MAX_LIMIT);
+ clientInfo.onDiscoverServicesFailed(
+ clientId, NsdManager.FAILURE_MAX_LIMIT);
break;
}
maybeStartDaemon();
id = getUniqueId();
- if (discoverServices(id, servInfo.getServiceType())) {
+ if (discoverServices(id, args.serviceInfo.getServiceType())) {
if (DBG) {
- Slog.d(TAG, "Discover " + msg.arg2 + " " + id +
- servInfo.getServiceType());
+ Log.d(TAG, "Discover " + msg.arg2 + " " + id
+ + args.serviceInfo.getServiceType());
}
- storeRequestMap(msg.arg2, id, clientInfo, msg.what);
- replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo);
+ storeRequestMap(clientId, id, clientInfo, msg.what);
+ clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
} else {
stopServiceDiscovery(id);
- replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
+ clientInfo.onDiscoverServicesFailed(clientId,
NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
case NsdManager.STOP_DISCOVERY:
- if (DBG) Slog.d(TAG, "Stop service discovery");
- clientInfo = mClients.get(msg.replyTo);
+ if (DBG) Log.d(TAG, "Stop service discovery");
+ args = (ListenerArgs) msg.obj;
+ clientInfo = mClients.get(args.connector);
try {
- id = clientInfo.mClientIds.get(msg.arg2);
+ id = clientInfo.mClientIds.get(clientId);
} catch (NullPointerException e) {
- replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onStopDiscoveryFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
}
- removeRequestMap(msg.arg2, id, clientInfo);
+ removeRequestMap(clientId, id, clientInfo);
if (stopServiceDiscovery(id)) {
- replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED);
+ clientInfo.onStopDiscoverySucceeded(clientId);
} else {
- replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onStopDiscoveryFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
case NsdManager.REGISTER_SERVICE:
- if (DBG) Slog.d(TAG, "Register service");
- clientInfo = mClients.get(msg.replyTo);
+ if (DBG) Log.d(TAG, "Register service");
+ args = (ListenerArgs) msg.obj;
+ clientInfo = mClients.get(args.connector);
if (requestLimitReached(clientInfo)) {
- replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_MAX_LIMIT);
+ clientInfo.onRegisterServiceFailed(
+ clientId, NsdManager.FAILURE_MAX_LIMIT);
break;
}
maybeStartDaemon();
id = getUniqueId();
- if (registerService(id, (NsdServiceInfo) msg.obj)) {
- if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
- storeRequestMap(msg.arg2, id, clientInfo, msg.what);
+ if (registerService(id, args.serviceInfo)) {
+ if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
+ storeRequestMap(clientId, id, clientInfo, msg.what);
// Return success after mDns reports success
} else {
unregisterService(id);
- replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onRegisterServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
case NsdManager.UNREGISTER_SERVICE:
- if (DBG) Slog.d(TAG, "unregister service");
- clientInfo = mClients.get(msg.replyTo);
- try {
- id = clientInfo.mClientIds.get(msg.arg2);
- } catch (NullPointerException e) {
- replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ if (DBG) Log.d(TAG, "unregister service");
+ args = (ListenerArgs) msg.obj;
+ clientInfo = mClients.get(args.connector);
+ if (clientInfo == null) {
+ Log.e(TAG, "Unknown connector in unregistration");
break;
}
- removeRequestMap(msg.arg2, id, clientInfo);
+ id = clientInfo.mClientIds.get(clientId);
+ removeRequestMap(clientId, id, clientInfo);
if (unregisterService(id)) {
- replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED);
+ clientInfo.onUnregisterServiceSucceeded(clientId);
} else {
- replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onUnregisterServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
case NsdManager.RESOLVE_SERVICE:
- if (DBG) Slog.d(TAG, "Resolve service");
- servInfo = (NsdServiceInfo) msg.obj;
- clientInfo = mClients.get(msg.replyTo);
-
+ if (DBG) Log.d(TAG, "Resolve service");
+ args = (ListenerArgs) msg.obj;
+ clientInfo = mClients.get(args.connector);
if (clientInfo.mResolvedService != null) {
- replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_ALREADY_ACTIVE);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
break;
}
maybeStartDaemon();
id = getUniqueId();
- if (resolveService(id, servInfo)) {
+ if (resolveService(id, args.serviceInfo)) {
clientInfo.mResolvedService = new NsdServiceInfo();
- storeRequestMap(msg.arg2, id, clientInfo, msg.what);
+ storeRequestMap(clientId, id, clientInfo, msg.what);
} else {
- replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
case NsdManager.NATIVE_DAEMON_EVENT:
@@ -425,7 +408,7 @@
ClientInfo clientInfo = mIdToClientInfoMap.get(id);
if (clientInfo == null) {
String name = NativeResponseCode.nameOf(code);
- Slog.e(TAG, String.format("id %d for %s has no client mapping", id, name));
+ Log.e(TAG, String.format("id %d for %s has no client mapping", id, name));
return false;
}
@@ -436,43 +419,40 @@
// SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
// and we may get in this situation.
String name = NativeResponseCode.nameOf(code);
- Slog.d(TAG, String.format(
+ Log.d(TAG, String.format(
"Notification %s for listener id %d that is no longer active",
name, id));
return false;
}
if (DBG) {
String name = NativeResponseCode.nameOf(code);
- Slog.d(TAG, String.format("Native daemon message %s: %s", name, raw));
+ Log.d(TAG, String.format("Native daemon message %s: %s", name, raw));
}
switch (code) {
case NativeResponseCode.SERVICE_FOUND:
/* NNN uniqueId serviceName regType domain */
servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
- clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
- clientId, servInfo);
+ clientInfo.onServiceFound(clientId, servInfo);
break;
case NativeResponseCode.SERVICE_LOST:
/* NNN uniqueId serviceName regType domain */
servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
- clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
- clientId, servInfo);
+ clientInfo.onServiceLost(clientId, servInfo);
break;
case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
/* NNN uniqueId errorCode */
- clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+ clientInfo.onDiscoverServicesFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
case NativeResponseCode.SERVICE_REGISTERED:
/* NNN regId serviceName regType */
servInfo = new NsdServiceInfo(cooked[2], null);
- clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
- id, clientId, servInfo);
+ clientInfo.onRegisterServiceSucceeded(clientId, servInfo);
break;
case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
/* NNN regId errorCode */
- clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+ clientInfo.onRegisterServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
case NativeResponseCode.SERVICE_UPDATED:
/* NNN regId */
@@ -490,7 +470,7 @@
++index;
}
if (index >= cooked[2].length()) {
- Slog.e(TAG, "Invalid service found " + raw);
+ Log.e(TAG, "Invalid service found " + raw);
break;
}
String name = cooked[2].substring(0, index);
@@ -511,8 +491,8 @@
if (getAddrInfo(id2, cooked[3])) {
storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
} else {
- clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
clientInfo.mResolvedService = null;
}
break;
@@ -521,26 +501,26 @@
stopResolveService(id);
removeRequestMap(clientId, id, clientInfo);
clientInfo.mResolvedService = null;
- clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
case NativeResponseCode.SERVICE_GET_ADDR_FAILED:
/* NNN resolveId errorCode */
stopGetAddrInfo(id);
removeRequestMap(clientId, id, clientInfo);
clientInfo.mResolvedService = null;
- clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
/* NNN resolveId hostname ttl addr */
try {
clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
- clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED,
- 0, clientId, clientInfo.mResolvedService);
+ clientInfo.onResolveServiceSucceeded(
+ clientId, clientInfo.mResolvedService);
} catch (java.net.UnknownHostException e) {
- clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
- NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
stopGetAddrInfo(id);
removeRequestMap(clientId, id, clientInfo);
@@ -560,13 +540,13 @@
char c = s.charAt(i);
if (c == '\\') {
if (++i >= s.length()) {
- Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ Log.e(TAG, "Unexpected end of escape sequence in: " + s);
break;
}
c = s.charAt(i);
if (c != '.' && c != '\\') {
if (i + 2 >= s.length()) {
- Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ Log.e(TAG, "Unexpected end of escape sequence in: " + s);
break;
}
c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
@@ -579,11 +559,9 @@
}
@VisibleForTesting
- NsdService(Context ctx, NsdSettings settings, Handler handler,
- DaemonConnectionSupplier fn, long cleanupDelayMs) {
+ NsdService(Context ctx, Handler handler, DaemonConnectionSupplier fn, long cleanupDelayMs) {
mCleanupDelayMs = cleanupDelayMs;
mContext = ctx;
- mNsdSettings = settings;
mNsdStateMachine = new NsdStateMachine(TAG, handler);
mNsdStateMachine.start();
mDaemonCallback = new NativeCallbackReceiver();
@@ -591,29 +569,80 @@
}
public static NsdService create(Context context) throws InterruptedException {
- NsdSettings settings = NsdSettings.makeDefault(context);
HandlerThread thread = new HandlerThread(TAG);
thread.start();
Handler handler = new Handler(thread.getLooper());
- NsdService service = new NsdService(context, settings, handler,
- DaemonConnection::new, CLEANUP_DELAY_MS);
+ NsdService service =
+ new NsdService(context, handler, DaemonConnection::new, CLEANUP_DELAY_MS);
service.mDaemonCallback.awaitConnection();
return service;
}
- public Messenger getMessenger() {
+ @Override
+ public INsdServiceConnector connect(INsdManagerCallback cb) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
- return new Messenger(mNsdStateMachine.getHandler());
+ final INsdServiceConnector connector = new NsdServiceConnector();
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb)));
+ return connector;
}
- public void setEnabled(boolean isEnabled) {
- NetworkStack.checkNetworkStackPermission(mContext);
- mNsdSettings.putEnabledStatus(isEnabled);
- notifyEnabled(isEnabled);
+ private static class ListenerArgs {
+ public final NsdServiceConnector connector;
+ public final NsdServiceInfo serviceInfo;
+ ListenerArgs(NsdServiceConnector connector, NsdServiceInfo serviceInfo) {
+ this.connector = connector;
+ this.serviceInfo = serviceInfo;
+ }
}
- private void notifyEnabled(boolean isEnabled) {
- mNsdStateMachine.sendMessage(isEnabled ? NsdManager.ENABLE : NsdManager.DISABLE);
+ private class NsdServiceConnector extends INsdServiceConnector.Stub
+ implements IBinder.DeathRecipient {
+ @Override
+ public void registerService(int listenerKey, NsdServiceInfo serviceInfo) {
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.REGISTER_SERVICE, 0, listenerKey,
+ new ListenerArgs(this, serviceInfo)));
+ }
+
+ @Override
+ public void unregisterService(int listenerKey) {
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.UNREGISTER_SERVICE, 0, listenerKey,
+ new ListenerArgs(this, null)));
+ }
+
+ @Override
+ public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) {
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.DISCOVER_SERVICES, 0, listenerKey,
+ new ListenerArgs(this, serviceInfo)));
+ }
+
+ @Override
+ public void stopDiscovery(int listenerKey) {
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.STOP_DISCOVERY, 0, listenerKey, new ListenerArgs(this, null)));
+ }
+
+ @Override
+ public void resolveService(int listenerKey, NsdServiceInfo serviceInfo) {
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.RESOLVE_SERVICE, 0, listenerKey,
+ new ListenerArgs(this, serviceInfo)));
+ }
+
+ @Override
+ public void startDaemon() {
+ mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+ NsdManager.DAEMON_STARTUP, new ListenerArgs(this, null)));
+ }
+
+ @Override
+ public void binderDied() {
+ mNsdStateMachine.sendMessage(
+ mNsdStateMachine.obtainMessage(NsdManager.UNREGISTER_CLIENT, this));
+ }
}
private void sendNsdStateChangeBroadcast(boolean isEnabled) {
@@ -624,14 +653,6 @@
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- private boolean isNsdEnabled() {
- boolean ret = mNsdSettings.isEnabled();
- if (DBG) {
- Slog.d(TAG, "Network service discovery is " + (ret ? "enabled" : "disabled"));
- }
- return ret;
- }
-
private int getUniqueId() {
if (++mUniqueId == INVALID_ID) return ++mUniqueId;
return mUniqueId;
@@ -737,12 +758,12 @@
*/
public boolean execute(Object... args) {
if (DBG) {
- Slog.d(TAG, "mdnssd " + Arrays.toString(args));
+ Log.d(TAG, "mdnssd " + Arrays.toString(args));
}
try {
mNativeConnector.execute("mdnssd", args);
} catch (NativeDaemonConnectorException e) {
- Slog.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
+ Log.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
return false;
}
return true;
@@ -773,7 +794,7 @@
private boolean registerService(int regId, NsdServiceInfo service) {
if (DBG) {
- Slog.d(TAG, "registerService: " + regId + " " + service);
+ Log.d(TAG, "registerService: " + regId + " " + service);
}
String name = service.getServiceName();
String type = service.getServiceType();
@@ -822,7 +843,12 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump " + TAG
+ + " due to missing android.permission.DUMP permission");
+ return;
+ }
for (ClientInfo client : mClients.values()) {
pw.println("Client Info");
@@ -832,43 +858,11 @@
mNsdStateMachine.dump(fd, pw, args);
}
- /* arg2 on the source message has an id that needs to be retained in replies
- * see NsdManager for details */
- private Message obtainMessage(Message srcMsg) {
- Message msg = Message.obtain();
- msg.arg2 = srcMsg.arg2;
- return msg;
- }
-
- private void replyToMessage(Message msg, int what) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessage(msg);
- dstMsg.what = what;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- private void replyToMessage(Message msg, int what, int arg1) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessage(msg);
- dstMsg.what = what;
- dstMsg.arg1 = arg1;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- private void replyToMessage(Message msg, int what, Object obj) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessage(msg);
- dstMsg.what = what;
- dstMsg.obj = obj;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
/* Information tracked per client */
private class ClientInfo {
private static final int MAX_LIMIT = 10;
- private final AsyncChannel mChannel;
- private final Messenger mMessenger;
+ private final INsdManagerCallback mCb;
/* Remembers a resolved service until getaddrinfo completes */
private NsdServiceInfo mResolvedService;
@@ -881,17 +875,14 @@
// The target SDK of this client < Build.VERSION_CODES.S
private boolean mIsLegacy = false;
- private ClientInfo(AsyncChannel c, Messenger m) {
- mChannel = c;
- mMessenger = m;
- if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m);
+ private ClientInfo(INsdManagerCallback cb) {
+ mCb = cb;
+ if (DBG) Log.d(TAG, "New client");
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("mChannel ").append(mChannel).append("\n");
- sb.append("mMessenger ").append(mMessenger).append("\n");
sb.append("mResolvedService ").append(mResolvedService).append("\n");
sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
for(int i = 0; i< mClientIds.size(); i++) {
@@ -920,8 +911,10 @@
clientId = mClientIds.keyAt(i);
globalId = mClientIds.valueAt(i);
mIdToClientInfoMap.remove(globalId);
- if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId +
- " global-ID " + globalId + " type " + mClientRequests.get(clientId));
+ if (DBG) {
+ Log.d(TAG, "Terminating client-ID " + clientId
+ + " global-ID " + globalId + " type " + mClientRequests.get(clientId));
+ }
switch (mClientRequests.get(clientId)) {
case NsdManager.DISCOVER_SERVICES:
stopServiceDiscovery(globalId);
@@ -949,36 +942,101 @@
}
return mClientIds.keyAt(idx);
}
- }
- /**
- * Interface which encapsulates dependencies of NsdService that are hard to mock, hard to
- * override, or have side effects on global state in unit tests.
- */
- @VisibleForTesting
- public interface NsdSettings {
- boolean isEnabled();
- void putEnabledStatus(boolean isEnabled);
- void registerContentObserver(Uri uri, ContentObserver observer);
+ void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
+ try {
+ mCb.onDiscoverServicesStarted(listenerKey, info);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onDiscoverServicesStarted", e);
+ }
+ }
- static NsdSettings makeDefault(Context context) {
- final ContentResolver resolver = context.getContentResolver();
- return new NsdSettings() {
- @Override
- public boolean isEnabled() {
- return Settings.Global.getInt(resolver, Settings.Global.NSD_ON, 1) == 1;
- }
+ void onDiscoverServicesFailed(int listenerKey, int error) {
+ try {
+ mCb.onDiscoverServicesFailed(listenerKey, error);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onDiscoverServicesFailed", e);
+ }
+ }
- @Override
- public void putEnabledStatus(boolean isEnabled) {
- Settings.Global.putInt(resolver, Settings.Global.NSD_ON, isEnabled ? 1 : 0);
- }
+ void onServiceFound(int listenerKey, NsdServiceInfo info) {
+ try {
+ mCb.onServiceFound(listenerKey, info);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onServiceFound(", e);
+ }
+ }
- @Override
- public void registerContentObserver(Uri uri, ContentObserver observer) {
- resolver.registerContentObserver(uri, false, observer);
- }
- };
+ void onServiceLost(int listenerKey, NsdServiceInfo info) {
+ try {
+ mCb.onServiceLost(listenerKey, info);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onServiceLost(", e);
+ }
+ }
+
+ void onStopDiscoveryFailed(int listenerKey, int error) {
+ try {
+ mCb.onStopDiscoveryFailed(listenerKey, error);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onStopDiscoveryFailed", e);
+ }
+ }
+
+ void onStopDiscoverySucceeded(int listenerKey) {
+ try {
+ mCb.onStopDiscoverySucceeded(listenerKey);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onStopDiscoverySucceeded", e);
+ }
+ }
+
+ void onRegisterServiceFailed(int listenerKey, int error) {
+ try {
+ mCb.onRegisterServiceFailed(listenerKey, error);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onRegisterServiceFailed", e);
+ }
+ }
+
+ void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+ try {
+ mCb.onRegisterServiceSucceeded(listenerKey, info);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onRegisterServiceSucceeded", e);
+ }
+ }
+
+ void onUnregisterServiceFailed(int listenerKey, int error) {
+ try {
+ mCb.onUnregisterServiceFailed(listenerKey, error);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onUnregisterServiceFailed", e);
+ }
+ }
+
+ void onUnregisterServiceSucceeded(int listenerKey) {
+ try {
+ mCb.onUnregisterServiceSucceeded(listenerKey);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onUnregisterServiceSucceeded", e);
+ }
+ }
+
+ void onResolveServiceFailed(int listenerKey, int error) {
+ try {
+ mCb.onResolveServiceFailed(listenerKey, error);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onResolveServiceFailed", e);
+ }
+ }
+
+ void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+ try {
+ mCb.onResolveServiceSucceeded(listenerKey, info);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling onResolveServiceSucceeded", e);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/service-t/src/com/android/server/net/IpConfigStore.java
similarity index 93%
rename from services/core/java/com/android/server/net/IpConfigStore.java
rename to service-t/src/com/android/server/net/IpConfigStore.java
index df1eb6d..3a9a544 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/service-t/src/com/android/server/net/IpConfigStore.java
@@ -44,6 +44,9 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * This class provides an API to store and manage L3 network IP configuration.
+ */
public class IpConfigStore {
private static final String TAG = "IpConfigStore";
private static final boolean DBG = false;
@@ -78,6 +81,9 @@
return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION);
}
+ /**
+ * Write the IP configuration with the given parameters to {@link DataOutputStream}.
+ */
@VisibleForTesting
public static boolean writeConfig(DataOutputStream out, String configKey,
IpConfiguration config, int version) throws IOException {
@@ -154,10 +160,10 @@
break;
case UNASSIGNED:
/* Ignore */
- break;
- default:
- loge("Ignore invalid proxy settings while writing");
- break;
+ break;
+ default:
+ loge("Ignore invalid proxy settings while writing");
+ break;
}
if (written) {
@@ -177,7 +183,7 @@
}
/**
- * @Deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
+ * @deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
* New method uses string as network identifier which could be interface name or MAC address or
* other token.
*/
@@ -186,22 +192,28 @@
final SparseArray<IpConfiguration> networks) {
mWriter.write(filePath, out -> {
out.writeInt(IPCONFIG_FILE_VERSION);
- for(int i = 0; i < networks.size(); i++) {
+ for (int i = 0; i < networks.size(); i++) {
writeConfig(out, String.valueOf(networks.keyAt(i)), networks.valueAt(i));
}
});
}
+ /**
+ * Write the IP configuration associated to the target networks to the destination path.
+ */
public void writeIpConfigurations(String filePath,
ArrayMap<String, IpConfiguration> networks) {
mWriter.write(filePath, out -> {
out.writeInt(IPCONFIG_FILE_VERSION);
- for(int i = 0; i < networks.size(); i++) {
+ for (int i = 0; i < networks.size(); i++) {
writeConfig(out, networks.keyAt(i), networks.valueAt(i));
}
});
}
+ /**
+ * Read the IP configuration from the destination path to {@link BufferedInputStream}.
+ */
public static ArrayMap<String, IpConfiguration> readIpConfigurations(String filePath) {
BufferedInputStream bufferedInputStream;
try {
@@ -215,7 +227,7 @@
return readIpConfigurations(bufferedInputStream);
}
- /** @Deprecated use {@link #readIpConfigurations(String)} */
+ /** @deprecated use {@link #readIpConfigurations(String)} */
@Deprecated
public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
BufferedInputStream bufferedInputStream;
@@ -230,7 +242,7 @@
return readIpAndProxyConfigurations(bufferedInputStream);
}
- /** @Deprecated use {@link #readIpConfigurations(InputStream)} */
+ /** @deprecated use {@link #readIpConfigurations(InputStream)} */
@Deprecated
public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(
InputStream inputStream) {
@@ -322,8 +334,11 @@
gateway = InetAddresses.parseNumericAddress(in.readUTF());
}
// If the destination is a default IPv4 route, use the gateway
- // address unless already set.
- if (dest.getAddress() instanceof Inet4Address
+ // address unless already set. If there is no destination, assume
+ // it is default route and use the gateway address in all cases.
+ if (dest == null) {
+ gatewayAddress = gateway;
+ } else if (dest.getAddress() instanceof Inet4Address
&& dest.getPrefixLength() == 0 && gatewayAddress == null) {
gatewayAddress = gateway;
} else {
@@ -417,7 +432,7 @@
if (in != null) {
try {
in.close();
- } catch (Exception e) {}
+ } catch (Exception e) { }
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java
similarity index 97%
rename from services/core/java/com/android/server/net/NetworkStatsFactory.java
rename to service-t/src/com/android/server/net/NetworkStatsFactory.java
index 431b009..bb123a3 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java
@@ -24,19 +24,19 @@
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.INetd;
import android.net.NetworkStats;
import android.net.UnderlyingNetworkInfo;
-import android.net.util.NetdService;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
+import com.android.net.module.util.CollectionUtils;
import libcore.io.IoUtils;
@@ -70,7 +70,7 @@
private final boolean mUseBpfStats;
- private INetd mNetdService;
+ private final INetd mNetd;
/**
* Guards persistent data access in this class
@@ -158,12 +158,12 @@
NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
}
- public NetworkStatsFactory() {
- this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists());
+ public NetworkStatsFactory(@NonNull INetd netd) {
+ this(new File("/proc/"), true, netd);
}
@VisibleForTesting
- public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
+ public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) {
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
@@ -172,6 +172,7 @@
mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
+ mNetd = netd;
}
public NetworkStats readBpfNetworkStatsDev() throws IOException {
@@ -298,10 +299,7 @@
// Ask netd to do a active map stats swap. When the binder call successfully returns,
// the system server should be able to safely read and clean the inactive map
// without race problem.
- if (mNetdService == null) {
- mNetdService = NetdService.getInstance();
- }
- mNetdService.trafficSwapActiveStatsMap();
+ mNetd.trafficSwapActiveStatsMap();
}
/**
@@ -434,7 +432,7 @@
entry.txBytes = reader.nextLong();
entry.txPackets = reader.nextLong();
- if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
+ if ((limitIfaces == null || CollectionUtils.contains(limitIfaces, entry.iface))
&& (limitUid == UID_ALL || limitUid == entry.uid)
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
stats.insertEntry(entry);
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java
similarity index 92%
rename from services/core/java/com/android/server/net/NetworkStatsObservers.java
rename to service-t/src/com/android/server/net/NetworkStatsObservers.java
index 2564dae..b57a4f9 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java
@@ -18,11 +18,12 @@
import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
-import static com.android.internal.util.Preconditions.checkArgument;
-
import android.app.usage.NetworkStatsManager;
import android.net.DataUsageRequest;
+import android.net.NetworkIdentitySet;
import android.net.NetworkStats;
+import android.net.NetworkStatsAccess;
+import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.Bundle;
@@ -35,7 +36,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.util.ArrayMap;
-import android.util.Slog;
+import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -80,7 +81,7 @@
RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid,
accessLevel);
- if (LOGV) Slog.v(TAG, "Registering observer for " + request);
+ if (LOGV) Log.v(TAG, "Registering observer for " + request);
getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
return request;
}
@@ -113,7 +114,7 @@
if (mHandler == null) {
synchronized (this) {
if (mHandler == null) {
- if (LOGV) Slog.v(TAG, "Creating handler");
+ if (LOGV) Log.v(TAG, "Creating handler");
mHandler = new Handler(getHandlerLooperLocked(), mHandlerCallback);
}
}
@@ -169,15 +170,15 @@
RequestInfo requestInfo;
requestInfo = mDataUsageRequests.get(request.requestId);
if (requestInfo == null) {
- if (LOGV) Slog.v(TAG, "Trying to unregister unknown request " + request);
+ if (LOGV) Log.v(TAG, "Trying to unregister unknown request " + request);
return;
}
if (Process.SYSTEM_UID != callingUid && requestInfo.mCallingUid != callingUid) {
- Slog.w(TAG, "Caller uid " + callingUid + " is not owner of " + request);
+ Log.w(TAG, "Caller uid " + callingUid + " is not owner of " + request);
return;
}
- if (LOGV) Slog.v(TAG, "Unregistering " + request);
+ if (LOGV) Log.v(TAG, "Unregistering " + request);
mDataUsageRequests.remove(request.requestId);
requestInfo.unlinkDeathRecipient();
requestInfo.callCallback(NetworkStatsManager.CALLBACK_RELEASED);
@@ -198,7 +199,7 @@
// Cap the minimum threshold to a safe default to avoid too many callbacks
long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes);
if (thresholdInBytes < request.thresholdInBytes) {
- Slog.w(TAG, "Threshold was too low for " + request
+ Log.w(TAG, "Threshold was too low for " + request
+ ". Overriding to a safer default of " + thresholdInBytes + " bytes");
}
return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(),
@@ -213,7 +214,10 @@
accessLevel);
} else {
// Safety check in case a new access level is added and we forgot to update this
- checkArgument(accessLevel >= NetworkStatsAccess.Level.DEVICESUMMARY);
+ if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
+ throw new IllegalArgumentException(
+ "accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
+ }
return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid,
accessLevel);
}
@@ -252,8 +256,9 @@
@Override
public void binderDied() {
- if (LOGV) Slog.v(TAG, "RequestInfo binderDied("
- + mRequest + ", " + mBinder + ")");
+ if (LOGV) {
+ Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")");
+ }
mStatsObserver.unregister(mRequest, Process.SYSTEM_UID);
callCallback(NetworkStatsManager.CALLBACK_RELEASED);
}
@@ -296,13 +301,13 @@
msg.setData(bundle);
try {
if (LOGV) {
- Slog.v(TAG, "sending notification " + callbackTypeToName(callbackType)
+ Log.v(TAG, "sending notification " + callbackTypeToName(callbackType)
+ " for " + mRequest);
}
mMessenger.send(msg);
} catch (RemoteException e) {
// May occur naturally in the race of binder death.
- Slog.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
+ Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
}
}
@@ -338,7 +343,7 @@
protected boolean checkStats() {
long bytesSoFar = getTotalBytesForNetwork(mRequest.template);
if (LOGV) {
- Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
+ Log.v(TAG, bytesSoFar + " bytes so far since notification for "
+ mRequest.template);
}
if (bytesSoFar > mRequest.thresholdInBytes) {
@@ -413,7 +418,7 @@
return history.getTotalBytes();
} catch (SecurityException e) {
if (LOGV) {
- Slog.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid "
+ Log.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid "
+ uid);
}
return 0;
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java
similarity index 95%
rename from services/core/java/com/android/server/net/NetworkStatsRecorder.java
rename to service-t/src/com/android/server/net/NetworkStatsRecorder.java
index 978ae87..c371f08 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java
@@ -21,23 +21,23 @@
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
+import android.net.NetworkIdentitySet;
import android.net.NetworkStats;
import android.net.NetworkStats.NonMonotonicObserver;
+import android.net.NetworkStatsAccess;
+import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.Binder;
import android.os.DropBoxManager;
import android.service.NetworkStatsRecorderProto;
+import android.util.IndentingPrintWriter;
import android.util.Log;
-import android.util.MathUtils;
-import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
-
-import com.google.android.collect.Sets;
+import com.android.net.module.util.NetworkStatsUtils;
import libcore.io.IoUtils;
@@ -129,8 +129,8 @@
}
public void setPersistThreshold(long thresholdBytes) {
- if (LOGV) Slog.v(TAG, "setPersistThreshold() with " + thresholdBytes);
- mPersistThresholdBytes = MathUtils.constrain(
+ if (LOGV) Log.v(TAG, "setPersistThreshold() with " + thresholdBytes);
+ mPersistThresholdBytes = NetworkStatsUtils.constrain(
thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES);
}
@@ -182,7 +182,7 @@
}
private NetworkStatsCollection loadLocked(long start, long end) {
- if (LOGD) Slog.d(TAG, "loadLocked() reading from disk for " + mCookie);
+ if (LOGD) Log.d(TAG, "loadLocked() reading from disk for " + mCookie);
final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration);
try {
mRotator.readMatching(res, start, end);
@@ -204,7 +204,7 @@
*/
public void recordSnapshotLocked(NetworkStats snapshot,
Map<String, NetworkIdentitySet> ifaceIdent, long currentTimeMillis) {
- final HashSet<String> unknownIfaces = Sets.newHashSet();
+ final HashSet<String> unknownIfaces = new HashSet<>();
// skip recording when snapshot missing
if (snapshot == null) return;
@@ -269,7 +269,7 @@
mLastSnapshot = snapshot;
if (LOGV && unknownIfaces.size() > 0) {
- Slog.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats");
+ Log.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats");
}
}
@@ -293,7 +293,7 @@
public void forcePersistLocked(long currentTimeMillis) {
Objects.requireNonNull(mRotator, "missing FileRotator");
if (mPending.isDirty()) {
- if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie);
+ if (LOGD) Log.d(TAG, "forcePersistLocked() writing for " + mCookie);
try {
mRotator.rewriteActive(mPendingRewriter, currentTimeMillis);
mRotator.maybeRotate(currentTimeMillis);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
similarity index 94%
rename from services/core/java/com/android/server/net/NetworkStatsService.java
rename to service-t/src/com/android/server/net/NetworkStatsService.java
index 097b071..ced2e22 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -25,7 +25,6 @@
import static android.content.Intent.EXTRA_UID;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
-import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.IFACE_VT;
@@ -43,7 +42,6 @@
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
-import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UNSUPPORTED;
@@ -90,27 +88,31 @@
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.DataUsageRequest;
+import android.net.INetd;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkIdentity;
+import android.net.NetworkIdentitySet;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStateSnapshot;
import android.net.NetworkStats;
import android.net.NetworkStats.NonMonotonicObserver;
+import android.net.NetworkStatsAccess;
+import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TelephonyNetworkSpecifier;
+import android.net.TetheringManager;
import android.net.TrafficStats;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.BestClock;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
@@ -138,27 +140,30 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
+import android.util.IndentingPrintWriter;
import android.util.Log;
-import android.util.MathUtils;
-import android.util.Slog;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.DumpUtils;
import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.BestClock;
+import com.android.net.module.util.BinderUtils;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
+import com.android.net.module.util.PermissionUtils;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.Clock;
import java.time.ZoneOffset;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -215,8 +220,6 @@
private final PowerManager.WakeLock mWakeLock;
- private final boolean mUseBpfTrafficStats;
-
private final ContentObserver mContentObserver;
private final ContentResolver mContentResolver;
@@ -408,10 +411,11 @@
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock =
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
-
+ final INetd netd = INetd.Stub.asInterface(
+ (IBinder) context.getSystemService(Context.NETD_SERVICE));
final NetworkStatsService service = new NetworkStatsService(context, networkManager,
alarmManager, wakeLock, getDefaultClock(),
- new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(),
+ new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd),
new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
new Dependencies());
service.registerLocalService();
@@ -438,7 +442,6 @@
mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
- mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
mDeps = Objects.requireNonNull(deps, "missing Dependencies");
final HandlerThread handlerThread = mDeps.makeHandlerThread();
@@ -528,8 +531,9 @@
}
// watch for tethering changes
- final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
- mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
+ final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
+ tetheringManager.registerTetheringEventCallback(
+ new HandlerExecutor(mHandler), mTetherListener);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
@@ -585,7 +589,8 @@
@GuardedBy("mStatsLock")
private void shutdownLocked() {
- mContext.unregisterReceiver(mTetherReceiver);
+ final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
+ tetheringManager.unregisterTetheringEventCallback(mTetherListener);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mUserReceiver);
@@ -645,7 +650,7 @@
try {
mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
} catch (IllegalStateException e) {
- Slog.w(TAG, "problem registering for global alert: " + e);
+ Log.w(TAG, "problem registering for global alert: " + e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -654,8 +659,6 @@
@Override
public INetworkStatsSession openSession() {
- // NOTE: if callers want to get non-augmented data, they should go
- // through the public API
return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
}
@@ -765,7 +768,7 @@
return stats;
} catch (NullPointerException e) {
// TODO: Track down and fix the cause of this crash and remove this catch block.
- Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
+ Log.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
throw e;
}
}
@@ -810,7 +813,7 @@
private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
return NetworkStatsAccess.checkAccessLevel(
- mContext, Binder.getCallingUid(), callingPackage);
+ mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
}
/**
@@ -822,7 +825,7 @@
SubscriptionPlan plan = null;
if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
&& mSettings.getAugmentEnabled()) {
- if (LOGD) Slog.d(TAG, "Resolving plan for " + template);
+ if (LOGD) Log.d(TAG, "Resolving plan for " + template);
final long token = Binder.clearCallingIdentity();
try {
plan = LocalServices.getService(NetworkPolicyManagerInternal.class)
@@ -830,7 +833,7 @@
} finally {
Binder.restoreCallingIdentity(token);
}
- if (LOGD) Slog.d(TAG, "Resolved to plan " + plan);
+ if (LOGD) Log.d(TAG, "Resolved to plan " + plan);
}
return plan;
}
@@ -875,8 +878,6 @@
private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
assertSystemReady();
- // NOTE: if callers want to get non-augmented data, they should go
- // through the public API
return internalGetSummaryForNetwork(template,
NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
@@ -935,7 +936,7 @@
@Override
public String[] getMobileIfaces() {
// TODO (b/192758557): Remove debug log.
- if (ArrayUtils.contains(mMobileIfaces, null)) {
+ if (CollectionUtils.contains(mMobileIfaces, null)) {
throw new NullPointerException(
"null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
}
@@ -984,7 +985,7 @@
@NonNull NetworkStateSnapshot[] networkStates,
@Nullable String activeIface,
@NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
- checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
final long token = Binder.clearCallingIdentity();
try {
@@ -1013,9 +1014,10 @@
private void advisePersistThreshold(long thresholdBytes) {
// clamp threshold into safe range
- mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
+ mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes,
+ 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
if (LOGV) {
- Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
+ Log.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
+ mPersistThreshold);
}
@@ -1084,13 +1086,13 @@
if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
return UNSUPPORTED;
}
- return nativeGetUidStat(uid, type, checkBpfStatsEnable());
+ return nativeGetUidStat(uid, type);
}
@Override
public long getIfaceStats(@NonNull String iface, int type) {
Objects.requireNonNull(iface);
- long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
+ long nativeIfaceStats = nativeGetIfaceStat(iface, type);
if (nativeIfaceStats == -1) {
return nativeIfaceStats;
} else {
@@ -1104,7 +1106,7 @@
@Override
public long getTotalStats(int type) {
- long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable());
+ long nativeTotalStats = nativeGetTotalStat(type);
if (nativeTotalStats == -1) {
return nativeTotalStats;
} else {
@@ -1137,10 +1139,6 @@
}
}
- private boolean checkBpfStatsEnable() {
- return mUseBpfTrafficStats;
- }
-
/**
* Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
* reflect current {@link #mPersistThreshold} value. Always defers to
@@ -1156,14 +1154,15 @@
}
/**
- * Receiver that watches for {@link Tethering} to claim interface pairs.
+ * Listener that watches for {@link TetheringManager} to claim interface pairs.
*/
- private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- performPoll(FLAG_PERSIST_NETWORK);
- }
- };
+ private final TetheringManager.TetheringEventCallback mTetherListener =
+ new TetheringManager.TetheringEventCallback() {
+ @Override
+ public void onUpstreamChanged(@Nullable Network network) {
+ performPoll(FLAG_PERSIST_NETWORK);
+ }
+ };
private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
@Override
@@ -1203,13 +1202,13 @@
// On background handler thread, and USER_REMOVED is protected
// broadcast.
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- if (userId == -1) return;
+ final UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
+ if (userHandle == null) return;
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
- removeUserLocked(userId);
+ removeUserLocked(userHandle);
} finally {
mWakeLock.release();
}
@@ -1234,7 +1233,7 @@
@Override
public void limitReached(String limitName, String iface) {
// only someone like NMS should be calling us
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
// kick off background poll to collect network stats unless there is already
@@ -1282,7 +1281,7 @@
private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
@NonNull NetworkStateSnapshot[] snapshots) {
if (!mSystemReady) return;
- if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()");
+ if (LOGV) Log.v(TAG, "handleNotifyNetworkStatusLocked()");
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
@@ -1306,7 +1305,8 @@
final int displayTransport =
getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
- final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork());
+ final boolean isDefault = CollectionUtils.contains(
+ mDefaultNetworks, snapshot.getNetwork());
final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
: getSubTypeForStateSnapshot(snapshot);
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
@@ -1389,7 +1389,7 @@
mMobileIfaces = mobileIfaces.toArray(new String[0]);
// TODO (b/192758557): Remove debug log.
- if (ArrayUtils.contains(mMobileIfaces, null)) {
+ if (CollectionUtils.contains(mMobileIfaces, null)) {
throw new NullPointerException(
"null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
}
@@ -1404,7 +1404,7 @@
if (spec instanceof TelephonyNetworkSpecifier) {
return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
} else {
- Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
+ Log.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
return INVALID_SUBSCRIPTION_ID;
}
}
@@ -1488,7 +1488,7 @@
try {
recordSnapshotLocked(currentTime);
} catch (IllegalStateException e) {
- Slog.w(TAG, "problem reading network stats: " + e);
+ Log.w(TAG, "problem reading network stats: " + e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -1513,7 +1513,7 @@
@GuardedBy("mStatsLock")
private void performPollLocked(int flags) {
if (!mSystemReady) return;
- if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
+ if (LOGV) Log.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
@@ -1635,7 +1635,7 @@
*/
@GuardedBy("mStatsLock")
private void removeUidsLocked(int... uids) {
- if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
+ if (LOGV) Log.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
// Perform one last poll before removing
performPollLocked(FLAG_PERSIST_ALL);
@@ -1653,20 +1653,20 @@
* Clean up {@link #mUidRecorder} after user is removed.
*/
@GuardedBy("mStatsLock")
- private void removeUserLocked(int userId) {
- if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
+ private void removeUserLocked(@NonNull UserHandle userHandle) {
+ if (LOGV) Log.v(TAG, "removeUserLocked() for UserHandle=" + userHandle);
// Build list of UIDs that we should clean up
- int[] uids = new int[0];
+ final ArrayList<Integer> uids = new ArrayList<>();
final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
PackageManager.MATCH_ANY_USER
| PackageManager.MATCH_DISABLED_COMPONENTS);
for (ApplicationInfo app : apps) {
- final int uid = UserHandle.getUid(userId, app.uid);
- uids = ArrayUtils.appendInt(uids, uid);
+ final int uid = userHandle.getUid(app.uid);
+ uids.add(uid);
}
- removeUidsLocked(uids);
+ removeUidsLocked(CollectionUtils.toIntArray(uids));
}
private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal {
@@ -1709,7 +1709,7 @@
public void setStatsProviderWarningAndLimitAsync(
@NonNull String iface, long warning, long limit) {
if (LOGV) {
- Slog.v(TAG, "setStatsProviderWarningAndLimitAsync("
+ Log.v(TAG, "setStatsProviderWarningAndLimitAsync("
+ iface + "," + warning + "," + limit + ")");
}
invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
@@ -1719,7 +1719,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
- if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
+ if (!PermissionUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
long duration = DateUtils.DAY_IN_MILLIS;
final HashSet<String> argSet = new HashSet<String>();
@@ -1780,15 +1780,15 @@
pw.println("Configs:");
pw.increaseIndent();
- pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
+ pw.print(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
pw.println();
pw.decreaseIndent();
pw.println("Active interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveIfaces.size(); i++) {
- pw.printPair("iface", mActiveIfaces.keyAt(i));
- pw.printPair("ident", mActiveIfaces.valueAt(i));
+ pw.print("iface", mActiveIfaces.keyAt(i));
+ pw.print("ident", mActiveIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
@@ -1796,8 +1796,8 @@
pw.println("Active UID interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveUidIfaces.size(); i++) {
- pw.printPair("iface", mActiveUidIfaces.keyAt(i));
- pw.printPair("ident", mActiveUidIfaces.valueAt(i));
+ pw.print("iface", mActiveUidIfaces.keyAt(i));
+ pw.print("ident", mActiveUidIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
@@ -1870,7 +1870,7 @@
@GuardedBy("mStatsLock")
private void dumpProtoLocked(FileDescriptor fd) {
- final ProtoOutputStream proto = new ProtoOutputStream(fd);
+ final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd));
// TODO Right now it writes all history. Should it limit to the "since-boot" log?
@@ -2104,14 +2104,18 @@
@Override
public void notifyAlertReached() throws RemoteException {
- mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
+ // This binder object can only have been obtained by a process that holds
+ // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
+ BinderUtils.withCleanCallingIdentity(() ->
+ mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
}
@Override
public void notifyWarningOrLimitReached() {
Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
- LocalServices.getService(NetworkPolicyManagerInternal.class)
- .onStatsProviderWarningOrLimitReached(mTag);
+ BinderUtils.withCleanCallingIdentity(() ->
+ LocalServices.getService(NetworkPolicyManagerInternal.class)
+ .onStatsProviderWarningOrLimitReached(mTag));
}
@Override
@@ -2249,7 +2253,7 @@
}
}
- private static native long nativeGetTotalStat(int type, boolean useBpfStats);
- private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
- private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
+ private static native long nativeGetTotalStat(int type);
+ private static native long nativeGetIfaceStat(String iface, int type);
+ private static native long nativeGetUidStat(int uid, int type);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
similarity index 92%
rename from services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
rename to service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index 5646c75..9bb7bb8 100644
--- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -33,7 +33,7 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.CollectionUtils;
+import com.android.net.module.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
@@ -99,18 +99,20 @@
// prevent binder call to telephony when querying RAT. Keep listener registration with empty
// IMSI is meaningless since the RAT type changed is ambiguous for multi-SIM if reported
// with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration.
- final List<Pair<Integer, String>> filteredNewSubs =
- CollectionUtils.mapNotNull(newSubs, subId -> {
- final String subscriberId = mTeleManager.getSubscriberId(subId);
- return TextUtils.isEmpty(subscriberId) ? null : new Pair(subId, subscriberId);
- });
+ final List<Pair<Integer, String>> filteredNewSubs = new ArrayList<>();
+ for (final int subId : newSubs) {
+ final String subscriberId =
+ mTeleManager.createForSubscriptionId(subId).getSubscriberId();
+ if (!TextUtils.isEmpty(subscriberId)) {
+ filteredNewSubs.add(new Pair(subId, subscriberId));
+ }
+ }
for (final Pair<Integer, String> sub : filteredNewSubs) {
// Fully match listener with subId and IMSI, since in some rare cases, IMSI might be
// suddenly change regardless of subId, such as switch IMSI feature in modem side.
// If that happens, register new listener with new IMSI and remove old one later.
- if (CollectionUtils.find(mRatListeners,
- it -> it.equalsKey(sub.first, sub.second)) != null) {
+ if (CollectionUtils.any(mRatListeners, it -> it.equalsKey(sub.first, sub.second))) {
continue;
}
@@ -126,8 +128,8 @@
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
// If there is no subId and IMSI matched the listener, removes it.
- if (CollectionUtils.find(filteredNewSubs,
- it -> listener.equalsKey(it.first, it.second)) == null) {
+ if (!CollectionUtils.any(filteredNewSubs,
+ it -> listener.equalsKey(it.first, it.second))) {
handleRemoveRatTypeListener(listener);
}
}
@@ -148,9 +150,10 @@
* @return collapsed RatType for the given subscriberId
*/
public int getRatTypeForSubscriberId(@NonNull String subscriberId) {
- final RatTypeListener match = CollectionUtils.find(mRatListeners,
+ final int index = CollectionUtils.indexOf(mRatListeners,
it -> TextUtils.equals(subscriberId, it.mSubscriberId));
- return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ return index != -1 ? mRatListeners.get(index).mLastCollapsedRatType
+ : TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
/**
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 10b248a..5178132 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -38,9 +38,6 @@
namespace android {
-static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt";
-static const char* QTAGUID_UID_STATS = "/proc/net/xt_qtaguid/stats";
-
// NOTE: keep these in sync with TrafficStats.java
static const uint64_t UNKNOWN = -1;
@@ -72,102 +69,17 @@
}
}
-static int parseIfaceStats(const char* iface, Stats* stats) {
- FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
- if (fp == NULL) {
- return -1;
- }
-
- char buffer[384];
- char cur_iface[32];
- bool foundTcp = false;
- uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets;
-
- while (fgets(buffer, sizeof(buffer), fp) != NULL) {
- int matched = sscanf(buffer, "%31s %" SCNu64 " %" SCNu64 " %" SCNu64
- " %" SCNu64 " " "%*u %" SCNu64 " %*u %*u %*u %*u "
- "%*u %" SCNu64 " %*u %*u %*u %*u", cur_iface, &rxBytes,
- &rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets);
- if (matched >= 5) {
- if (matched == 7) {
- foundTcp = true;
- }
- if (!iface || !strcmp(iface, cur_iface)) {
- stats->rxBytes += rxBytes;
- stats->rxPackets += rxPackets;
- stats->txBytes += txBytes;
- stats->txPackets += txPackets;
- if (matched == 7) {
- stats->tcpRxPackets += tcpRxPackets;
- stats->tcpTxPackets += tcpTxPackets;
- }
- }
- }
- }
-
- if (!foundTcp) {
- stats->tcpRxPackets = UNKNOWN;
- stats->tcpTxPackets = UNKNOWN;
- }
-
- if (fclose(fp) != 0) {
- return -1;
- }
- return 0;
-}
-
-static int parseUidStats(const uint32_t uid, Stats* stats) {
- FILE *fp = fopen(QTAGUID_UID_STATS, "r");
- if (fp == NULL) {
- return -1;
- }
-
- char buffer[384];
- char iface[32];
- uint32_t idx, cur_uid, set;
- uint64_t tag, rxBytes, rxPackets, txBytes, txPackets;
-
- while (fgets(buffer, sizeof(buffer), fp) != NULL) {
- if (sscanf(buffer,
- "%" SCNu32 " %31s 0x%" SCNx64 " %u %u %" SCNu64 " %" SCNu64
- " %" SCNu64 " %" SCNu64 "",
- &idx, iface, &tag, &cur_uid, &set, &rxBytes, &rxPackets,
- &txBytes, &txPackets) == 9) {
- if (uid == cur_uid && tag == 0L) {
- stats->rxBytes += rxBytes;
- stats->rxPackets += rxPackets;
- stats->txBytes += txBytes;
- stats->txPackets += txPackets;
- }
- }
- }
-
- if (fclose(fp) != 0) {
- return -1;
- }
- return 0;
-}
-
-static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
+static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
Stats stats = {};
- if (useBpfStats) {
- if (bpfGetIfaceStats(NULL, &stats) == 0) {
- return getStatsType(&stats, (StatsType) type);
- } else {
- return UNKNOWN;
- }
- }
-
- if (parseIfaceStats(NULL, &stats) == 0) {
+ if (bpfGetIfaceStats(NULL, &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
} else {
return UNKNOWN;
}
}
-static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
- jboolean useBpfStats) {
+static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
ScopedUtfChars iface8(env, iface);
if (iface8.c_str() == NULL) {
return UNKNOWN;
@@ -175,33 +87,17 @@
Stats stats = {};
- if (useBpfStats) {
- if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
- return getStatsType(&stats, (StatsType) type);
- } else {
- return UNKNOWN;
- }
- }
-
- if (parseIfaceStats(iface8.c_str(), &stats) == 0) {
+ if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
} else {
return UNKNOWN;
}
}
-static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
+static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
Stats stats = {};
- if (useBpfStats) {
- if (bpfGetUidStats(uid, &stats) == 0) {
- return getStatsType(&stats, (StatsType) type);
- } else {
- return UNKNOWN;
- }
- }
-
- if (parseUidStats(uid, &stats) == 0) {
+ if (bpfGetUidStats(uid, &stats) == 0) {
return getStatsType(&stats, (StatsType) type);
} else {
return UNKNOWN;
@@ -209,9 +105,9 @@
}
static const JNINativeMethod gMethods[] = {
- {"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat},
- {"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat},
- {"nativeGetUidStat", "(IIZ)J", (void*) getUidStat},
+ {"nativeGetTotalStat", "(I)J", (void*)getTotalStat},
+ {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat},
+ {"nativeGetUidStat", "(II)J", (void*)getUidStat},
};
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
diff --git a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java b/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
rename to tests/unit/java/com/android/server/NativeDaemonConnectorTest.java