Snap for 8364388 from 965da01e8c51a8f6947fa4ce535f82451260a792 to main-cg-testing-release
Change-Id: I7737db28e9da2a3990712b0501dcbb7f896bca24
diff --git a/Android.bp b/Android.bp
index 80b4c76..8c5a855 100644
--- a/Android.bp
+++ b/Android.bp
@@ -271,8 +271,6 @@
include_dirs: [
"frameworks/av/aidl",
"frameworks/native/libs/permission/aidl",
- // TODO: remove when moved to the below package
- "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
"packages/modules/Connectivity/framework/aidl-export",
"packages/modules/Media/apex/aidl/stable",
],
@@ -519,8 +517,6 @@
include_dirs: [
"frameworks/av/aidl",
"frameworks/native/libs/permission/aidl",
- // TODO: remove when moved to the below package
- "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
"packages/modules/Connectivity/framework/aidl-export",
],
},
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index 7e3cc27..d18154a 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -33,6 +33,7 @@
"&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
srcs: [
+ ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -63,6 +64,7 @@
" $(in)",
srcs: [
+ ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -78,6 +80,7 @@
java_library_host {
name: "platformprotos",
srcs: [
+ ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -117,6 +120,7 @@
],
sdk_version: "9",
srcs: [
+ ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -135,6 +139,7 @@
},
srcs: [
+ ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
@@ -172,6 +177,7 @@
],
srcs: [
+ ":framework-connectivity-protos",
":ipconnectivity-proto-src",
":libstats_atom_enum_protos",
":libstats_atom_message_protos",
diff --git a/core/api/current.txt b/core/api/current.txt
index da0c7ed..a09a359 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -41422,7 +41422,8 @@
method public void setSubscriptionOverrideCongested(int, boolean, @NonNull int[], long);
method public void setSubscriptionOverrideUnmetered(int, boolean, long);
method public void setSubscriptionOverrideUnmetered(int, boolean, @NonNull int[], long);
- method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
+ method @Deprecated public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
+ method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>, long);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, @NonNull android.app.PendingIntent);
field public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
@@ -42282,7 +42283,8 @@
method public boolean isEnabled();
method public boolean isSimPortAvailable(int);
method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
- method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
+ method @Deprecated @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
+ method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccManager.ResultListener);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);
field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
field public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
@@ -42328,6 +42330,10 @@
field public static final int OPERATION_SYSTEM = 1; // 0x1
}
+ public static interface EuiccManager.ResultListener {
+ method public void onComplete(int, @Nullable android.content.Intent);
+ }
+
}
package android.telephony.gsm {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6145886..77cc03c0 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9641,7 +9641,8 @@
method @android.telephony.euicc.EuiccManager.OtaStatus public abstract int onGetOtaStatus(int);
method public abstract int onRetainSubscriptionsForFactoryReset(int);
method public abstract void onStartOtaIfNecessary(int, android.service.euicc.EuiccService.OtaStatusChangedCallback);
- method public abstract int onSwitchToSubscription(int, @Nullable String, boolean);
+ method @Deprecated public abstract int onSwitchToSubscription(int, @Nullable String, boolean);
+ method public int onSwitchToSubscriptionWithPort(int, int, @Nullable String, boolean);
method public abstract int onUpdateSubscriptionNickname(int, String, String);
field public static final String ACTION_BIND_CARRIER_PROVISIONING_SERVICE = "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE";
field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
@@ -9663,6 +9664,7 @@
field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
field public static final String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT";
+ field public static final String EXTRA_RESOLUTION_PORT_INDEX = "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
field public static final String EXTRA_RESOLVABLE_ERRORS = "android.service.euicc.extra.RESOLVABLE_ERRORS";
field public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1; // 0x1
field public static final int RESOLVABLE_ERROR_POLICY_RULES = 2; // 0x2
@@ -11594,7 +11596,6 @@
}
public class TelephonyManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -11639,7 +11640,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public int getMaxNumberOfSimultaneouslyActiveSims();
method public static long getMaxNumberVerificationTimeoutMillis();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
@@ -11647,10 +11648,13 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
method public int getSimApplicationState();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int, int);
method public int getSimCardState();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Collection<android.telephony.UiccSlotMapping> getSimSlotMapping();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -11658,10 +11662,14 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
- method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
- method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void iccCloseLogicalChannelByPort(int, int, int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelByPort(int, int, @Nullable String, int);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelByPort(int, int, int, int, int, int, int, @Nullable String);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelByPort(int, int, int, int, int, int, int, int, @Nullable String);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
@@ -11687,7 +11695,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -11737,6 +11745,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterCarrierPrivilegesCallback(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
method public void updateServiceLocation();
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
@@ -11841,8 +11850,9 @@
field public static final int RESULT_SUCCESS = 0; // 0x0
}
- public static interface TelephonyManager.CarrierPrivilegesListener {
- method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
+ public static interface TelephonyManager.CarrierPrivilegesCallback {
+ method public void onCarrierPrivilegesChanged(@NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.Integer>);
+ method public default void onCarrierServiceChanged(@Nullable String, int);
}
public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 7be4c3e..4c30f56 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -586,8 +586,9 @@
/**
* Delete uid from the ActivityManagerService PendingStartActivityUids list.
* @param uid uid
+ * @param nowElapsed starting time of updateOomAdj
*/
- public abstract void deletePendingTopUid(int uid);
+ public abstract void deletePendingTopUid(int uid, long nowElapsed);
/**
* Is the uid in ActivityManagerService PendingStartActivityUids list?
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 6284f56..dc24106 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -72,9 +72,9 @@
SubscriptionPlan getSubscriptionPlan(in NetworkTemplate template);
void notifyStatsProviderWarningOrLimitReached();
SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
- void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
+ void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, long expirationDurationMillis, String callingPackage);
String getSubscriptionPlansOwner(int subId);
- void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long timeoutMillis, String callingPackage);
+ void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long expirationDurationMillis, String callingPackage);
void factoryReset(String subscriber);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 3f92eb1..43ae4fc 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -484,8 +484,8 @@
* @param networkTypes the network types this override applies to. If no
* network types are specified, override values will be ignored.
* {@see TelephonyManager#getAllNetworkTypes()}
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first
* @param callingPackage the name of the package making the call.
@@ -493,11 +493,11 @@
*/
public void setSubscriptionOverride(int subId, @SubscriptionOverrideMask int overrideMask,
@SubscriptionOverrideMask int overrideValue,
- @NonNull @Annotation.NetworkType int[] networkTypes, long timeoutMillis,
+ @NonNull @Annotation.NetworkType int[] networkTypes, long expirationDurationMillis,
@NonNull String callingPackage) {
try {
mService.setSubscriptionOverride(subId, overrideMask, overrideValue, networkTypes,
- timeoutMillis, callingPackage);
+ expirationDurationMillis, callingPackage);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -508,13 +508,16 @@
*
* @param subId the subscriber this relationship applies to.
* @param plans the list of plans.
+ * @param expirationDurationMillis the duration after which the subscription plans
+ * will be automatically cleared, or {@code 0} to leave the plans until
+ * explicitly cleared, or the next reboot, whichever happens first
* @param callingPackage the name of the package making the call
* @hide
*/
public void setSubscriptionPlans(int subId, @NonNull SubscriptionPlan[] plans,
- @NonNull String callingPackage) {
+ long expirationDurationMillis, @NonNull String callingPackage) {
try {
- mService.setSubscriptionPlans(subId, plans, callingPackage);
+ mService.setSubscriptionPlans(subId, plans, expirationDurationMillis, callingPackage);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index ab74199..82d4443 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -218,14 +218,15 @@
/**
* Set the value for the given {@code key} to {@code val}.
*
- * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
+ * @throws IllegalArgumentException for non read-only properties if the {@code val} exceeds
+ * 91 characters
* @throws RuntimeException if the property cannot be set, for example, if it was blocked by
* SELinux. libc will log the underlying reason.
* @hide
*/
@UnsupportedAppUsage
public static void set(@NonNull String key, @Nullable String val) {
- if (val != null && !val.startsWith("ro.") && val.length() > PROP_VALUE_MAX) {
+ if (val != null && !key.startsWith("ro.") && val.length() > PROP_VALUE_MAX) {
throw new IllegalArgumentException("value of system property '" + key
+ "' is longer than " + PROP_VALUE_MAX + " characters: " + val);
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 6dd878c..134cfa1 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -286,28 +286,7 @@
/** @hide The volume is not encrypted. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int ENCRYPTION_STATE_NONE =
- IVold.ENCRYPTION_STATE_NONE;
-
- /** @hide The volume has been encrypted succesfully. */
- public static final int ENCRYPTION_STATE_OK =
- IVold.ENCRYPTION_STATE_OK;
-
- /** @hide The volume is in a bad state. */
- public static final int ENCRYPTION_STATE_ERROR_UNKNOWN =
- IVold.ENCRYPTION_STATE_ERROR_UNKNOWN;
-
- /** @hide Encryption is incomplete */
- public static final int ENCRYPTION_STATE_ERROR_INCOMPLETE =
- IVold.ENCRYPTION_STATE_ERROR_INCOMPLETE;
-
- /** @hide Encryption is incomplete and irrecoverable */
- public static final int ENCRYPTION_STATE_ERROR_INCONSISTENT =
- IVold.ENCRYPTION_STATE_ERROR_INCONSISTENT;
-
- /** @hide Underlying data is corrupt */
- public static final int ENCRYPTION_STATE_ERROR_CORRUPT =
- IVold.ENCRYPTION_STATE_ERROR_CORRUPT;
+ public static final int ENCRYPTION_STATE_NONE = 1;
private static volatile IStorageManager sStorageManager = null;
@@ -2893,15 +2872,10 @@
@GuardedBy("mFuseAppLoopLock")
private @Nullable FuseAppLoop mFuseAppLoop = null;
- /// Consts to match the password types in cryptfs.h
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int CRYPT_TYPE_PASSWORD = IVold.PASSWORD_TYPE_PASSWORD;
+ public static final int CRYPT_TYPE_PASSWORD = 0;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int CRYPT_TYPE_DEFAULT = IVold.PASSWORD_TYPE_DEFAULT;
- /** @hide */
- public static final int CRYPT_TYPE_PATTERN = IVold.PASSWORD_TYPE_PATTERN;
- /** @hide */
- public static final int CRYPT_TYPE_PIN = IVold.PASSWORD_TYPE_PIN;
+ public static final int CRYPT_TYPE_DEFAULT = 1;
}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 0d5ef34..5b59b21 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1425,25 +1425,6 @@
public static final String KEY_TYPE = "key_type";
/**
- * MVNO type:
- * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
- * <P> Type: TEXT </P>
- */
- public static final String MVNO_TYPE = "mvno_type";
-
- /**
- * MVNO data.
- * Use the following examples.
- * <ul>
- * <li>SPN: A MOBILE, BEN NL, ...</li>
- * <li>IMSI: 302720x94, 2060188, ...</li>
- * <li>GID: 4E, 33, ...</li>
- * </ul>
- * <P> Type: TEXT </P>
- */
- public static final String MVNO_MATCH_DATA = "mvno_match_data";
-
- /**
* The carrier public key that is used for the IMSI encryption.
* <P> Type: TEXT </P>
*/
@@ -1470,6 +1451,11 @@
public static final String LAST_MODIFIED = "last_modified";
/**
+ * Carrier ID of the operetor.
+ * <P> Type: TEXT </P>
+ */
+ public static final String CARRIER_ID = "carrier_id";
+ /**
* The {@code content://} style URL for this table.
*/
@NonNull
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
index 0cb69a4..61fd041 100644
--- a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -167,10 +167,7 @@
protected WrappedApplicationKey(Parcel in) {
mAlias = in.readString();
mEncryptedKeyMaterial = in.createByteArray();
- // Check if there is still data to be read.
- if (in.dataAvail() > 0) {
- mMetadata = in.createByteArray();
- }
+ mMetadata = in.createByteArray();
}
@Override
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 542de3f..9c7f23e 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -27,6 +27,7 @@
import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.service.carrier.CarrierService;
import android.telephony.Annotation.CallState;
import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.DisconnectCauses;
@@ -36,7 +37,7 @@
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
-import android.telephony.TelephonyManager.CarrierPrivilegesListener;
+import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.util.ArraySet;
@@ -44,17 +45,19 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.listeners.ListenerExecutor;
-import com.android.internal.telephony.ICarrierPrivilegesListener;
+import com.android.internal.telephony.ICarrierPrivilegesCallback;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
/**
* A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
@@ -1258,63 +1261,79 @@
pkgName, attributionTag, callback, new int[0], notifyNow);
}
- private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub
+ private static class CarrierPrivilegesCallbackWrapper extends ICarrierPrivilegesCallback.Stub
implements ListenerExecutor {
- private final WeakReference<CarrierPrivilegesListener> mListener;
- private final Executor mExecutor;
+ @NonNull private final WeakReference<CarrierPrivilegesCallback> mCallback;
+ @NonNull private final Executor mExecutor;
- CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) {
- mListener = new WeakReference<>(listener);
+ CarrierPrivilegesCallbackWrapper(
+ @NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) {
+ mCallback = new WeakReference<>(callback);
mExecutor = executor;
}
@Override
public void onCarrierPrivilegesChanged(
- List<String> privilegedPackageNames, int[] privilegedUids) {
+ @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) {
+ // AIDL interface does not support Set, keep the List/Array and translate them here
+ Set<String> privilegedPkgNamesSet = Set.copyOf(privilegedPackageNames);
+ Set<Integer> privilegedUidsSet = Arrays.stream(privilegedUids).boxed().collect(
+ Collectors.toSet());
Binder.withCleanCallingIdentity(
() ->
executeSafely(
mExecutor,
- mListener::get,
- cpl ->
- cpl.onCarrierPrivilegesChanged(
- privilegedPackageNames, privilegedUids)));
+ mCallback::get,
+ cpc ->
+ cpc.onCarrierPrivilegesChanged(
+ privilegedPkgNamesSet, privilegedUidsSet)));
+ }
+
+ @Override
+ public void onCarrierServiceChanged(@Nullable String packageName, int uid) {
+ Binder.withCleanCallingIdentity(
+ () ->
+ executeSafely(
+ mExecutor,
+ mCallback::get,
+ cpc -> cpc.onCarrierServiceChanged(packageName, uid)));
}
}
- @GuardedBy("sCarrierPrivilegeListeners")
- private static final WeakHashMap<
- CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>>
- sCarrierPrivilegeListeners = new WeakHashMap<>();
+ @NonNull
+ @GuardedBy("sCarrierPrivilegeCallbacks")
+ private static final WeakHashMap<CarrierPrivilegesCallback,
+ WeakReference<CarrierPrivilegesCallbackWrapper>>
+ sCarrierPrivilegeCallbacks = new WeakHashMap<>();
/**
- * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
+ * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
* receive callbacks when the set of packages with carrier privileges changes. The callback will
* immediately be called with the latest state.
*
* @param logicalSlotIndex The SIM slot to listen on
* @param executor The executor where {@code listener} will be invoked
- * @param listener The callback to register
+ * @param callback The callback to register
*/
- public void addCarrierPrivilegesListener(
+ public void addCarrierPrivilegesCallback(
int logicalSlotIndex,
@NonNull @CallbackExecutor Executor executor,
- @NonNull CarrierPrivilegesListener listener) {
- if (listener == null || executor == null) {
- throw new IllegalArgumentException("listener and executor must be non-null");
+ @NonNull CarrierPrivilegesCallback callback) {
+ if (callback == null || executor == null) {
+ throw new IllegalArgumentException("callback and executor must be non-null");
}
- synchronized (sCarrierPrivilegeListeners) {
- WeakReference<CarrierPrivilegesListenerWrapper> existing =
- sCarrierPrivilegeListeners.get(listener);
+ synchronized (sCarrierPrivilegeCallbacks) {
+ WeakReference<CarrierPrivilegesCallbackWrapper> existing =
+ sCarrierPrivilegeCallbacks.get(callback);
if (existing != null && existing.get() != null) {
- Log.d(TAG, "addCarrierPrivilegesListener: listener already registered");
+ Log.d(TAG, "addCarrierPrivilegesCallback: callback already registered");
return;
}
- CarrierPrivilegesListenerWrapper wrapper =
- new CarrierPrivilegesListenerWrapper(listener, executor);
- sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper));
+ CarrierPrivilegesCallbackWrapper wrapper =
+ new CarrierPrivilegesCallbackWrapper(callback, executor);
+ sCarrierPrivilegeCallbacks.put(callback, new WeakReference<>(wrapper));
try {
- sRegistry.addCarrierPrivilegesListener(
+ sRegistry.addCarrierPrivilegesCallback(
logicalSlotIndex,
wrapper,
mContext.getOpPackageName(),
@@ -1326,22 +1345,22 @@
}
/**
- * Unregisters a {@link CarrierPrivilegesListener}.
+ * Unregisters a {@link CarrierPrivilegesCallback}.
*
- * @param listener The callback to unregister
+ * @param callback The callback to unregister
*/
- public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
- if (listener == null) {
+ public void removeCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
+ if (callback == null) {
throw new IllegalArgumentException("listener must be non-null");
}
- synchronized (sCarrierPrivilegeListeners) {
- WeakReference<CarrierPrivilegesListenerWrapper> ref =
- sCarrierPrivilegeListeners.remove(listener);
+ synchronized (sCarrierPrivilegeCallbacks) {
+ WeakReference<CarrierPrivilegesCallbackWrapper> ref =
+ sCarrierPrivilegeCallbacks.remove(callback);
if (ref == null) return;
- CarrierPrivilegesListenerWrapper wrapper = ref.get();
+ CarrierPrivilegesCallbackWrapper wrapper = ref.get();
if (wrapper == null) return;
try {
- sRegistry.removeCarrierPrivilegesListener(wrapper, mContext.getOpPackageName());
+ sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1357,15 +1376,33 @@
*/
public void notifyCarrierPrivilegesChanged(
int logicalSlotIndex,
- @NonNull List<String> privilegedPackageNames,
- @NonNull int[] privilegedUids) {
+ @NonNull Set<String> privilegedPackageNames,
+ @NonNull Set<Integer> privilegedUids) {
if (privilegedPackageNames == null || privilegedUids == null) {
throw new IllegalArgumentException(
"privilegedPackageNames and privilegedUids must be non-null");
}
try {
- sRegistry.notifyCarrierPrivilegesChanged(
- logicalSlotIndex, privilegedPackageNames, privilegedUids);
+ // AIDL doesn't support Set yet. Convert Set to List/Array
+ List<String> pkgList = List.copyOf(privilegedPackageNames);
+ int[] uids = privilegedUids.stream().mapToInt(Number::intValue).toArray();
+ sRegistry.notifyCarrierPrivilegesChanged(logicalSlotIndex, pkgList, uids);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notify listeners that the {@link CarrierService} for current user has changed.
+ *
+ * @param logicalSlotIndex the SIM slot the change occurred on
+ * @param packageName the package name of the changed {@link CarrierService}
+ * @param uid the UID of the changed {@link CarrierService}
+ */
+ public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName,
+ int uid) {
+ try {
+ sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 9cb0d1f..a06b0e0 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -741,35 +741,42 @@
}
/**
- * Gets the size of the display, in pixels.
- * Value returned by this method does not necessarily represent the actual raw size
- * (native resolution) of the display.
- * <p>
- * 1. The returned size may be adjusted to exclude certain system decor elements
- * that are always visible.
- * </p><p>
- * 2. It may be scaled to provide compatibility with older applications that
- * were originally designed for smaller displays.
- * </p><p>
- * 3. It can be different depending on the WindowManager to which the display belongs.
- * </p><p>
- * - If requested from non-Activity context (e.g. Application context via
- * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)})
- * it will report the size of the entire display based on current rotation and with subtracted
- * system decoration areas.
- * </p><p>
- * - If requested from activity (either using {@code getWindowManager()} or
- * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting size will
- * correspond to current app window size. In this case it can be smaller than physical size in
- * multi-window mode.
- * </p><p>
- * Typically for the purposes of layout apps should make a request from activity context
- * to obtain size available for the app content.
- * </p>
+ * Gets the size of the display in pixels.
*
- * @param outSize A {@link Point} object to receive the size information.
- * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to obtain an instance of
- * {@link WindowMetrics} and use {@link WindowMetrics#getBounds()} instead.
+ * <p>The return value does not necessarily represent the actual size (native resolution) of the
+ * display. The returned size might be adjusted to exclude certain system decor elements that
+ * are always visible, or the size might be scaled to provide compatibility with older
+ * applications that were originally designed for smaller displays.
+ *
+ * <p>The returned size can also be different depending on the WindowManager bound to the
+ * display:
+ * <ul>
+ * <li>If size is requested from an activity (either using a WindowManager accessed by
+ * {@code getWindowManager()} or {@code getSystemService(Context.WINDOW_SERVICE)}), the
+ * size of the current app window is returned. As a result, in multi-window mode, the
+ * returned size can be smaller than the size of the device screen.
+ * <li>If size is requested from a non-activity context (for example, the application
+ * context, where the WindowManager is accessed by
+ * {@code getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}), the
+ * returned size can vary depending on API level:
+ * <ul>
+ * <li>API level 29 and below — The size of the entire display (based on
+ * current rotation) minus system decoration areas is returned.
+ * <li>API level 30 and above — The size of the top running activity in the
+ * current process is returned. If the current process has no running
+ * activities, the size of the device default display, including system
+ * decoration areas, is returned.
+ * </ul>
+ * </ul>
+ *
+ * <p>For layout purposes, apps should make a request from an activity context to obtain the
+ * size of the display area available for app content.
+ *
+ * @param outSize A {@link Point} object which receives the display size information.
+ *
+ * @deprecated Use {@link WindowMetrics} instead. Obtain a {@code WindowMetrics} instance by
+ * calling {@link WindowManager#getCurrentWindowMetrics()}, then call
+ * {@link WindowMetrics#getBounds()} to get the dimensions of the application window.
*/
@Deprecated
public void getSize(Point outSize) {
@@ -785,8 +792,9 @@
* Gets the size of the display as a rectangle, in pixels.
*
* @param outSize A {@link Rect} object to receive the size information.
+ *
* @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application
- * window area.
+ * window.
*/
@Deprecated
public void getRectSize(Rect outSize) {
@@ -1275,32 +1283,39 @@
}
/**
- * Gets display metrics that describe the size and density of this display.
- * The size returned by this method does not necessarily represent the
- * actual raw size (native resolution) of the display.
- * <p>
- * 1. The returned size may be adjusted to exclude certain system decor elements
- * that are always visible.
- * </p><p>
- * 2. It may be scaled to provide compatibility with older applications that
- * were originally designed for smaller displays.
- * </p><p>
- * 3. It can be different depending on the WindowManager to which the display belongs.
- * </p><p>
- * - If requested from non-Activity context (e.g. Application context via
- * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)})
- * metrics will report the size of the entire display based on current rotation and with
- * subtracted system decoration areas.
- * </p><p>
- * - If requested from activity (either using {@code getWindowManager()} or
- * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting metrics will
- * correspond to current app window metrics. In this case the size can be smaller than physical
- * size in multi-window mode.
- * </p>
+ * Gets the size and density of this display.
*
- * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
+ * <p>The size returned does not necessarily represent the actual size (native resolution) of
+ * the display. The returned size might be adjusted to exclude certain system decor elements
+ * that are always visible, or the size might be scaled to provide compatibility with older
+ * applications that were originally designed for smaller displays.
+ *
+ * <p>The returned size can also be different depending on the WindowManager associated with the
+ * display:
+ * <ul>
+ * <li>If metrics are requested from an activity (either using a WindowManager accessed by
+ * {@code getWindowManager()} or {@code getSystemService(Context.WINDOW_SERVICE)}), the
+ * returned metrics provide the size of the current app window. As a result, in
+ * multi-window mode, the returned size can be smaller than the size of the device
+ * screen.
+ * <li>If metrics are requested from a non-activity context (for example, the application
+ * context, where the WindowManager is accessed by
+ * {@code getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}), the
+ * returned size can vary depending on API level:
+ * <ul>
+ * <li>API level 29 and below — The returned metrics provide the size of the
+ * entire display (based on current rotation) minus system decoration areas.
+ * <li>API level 30 and above — The returned metrics provide the size of the
+ * top running activity in the current process. If the current process has no
+ * running activities, the metrics provide the size of the default display of
+ * the device, including system decoration areas.
+ * </ul>
+ * </ul>
+ *
+ * @param outMetrics A {@link DisplayMetrics} object which receives the display metrics.
+ *
* @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application
- * window area, and {@link Configuration#densityDpi} to get the current density.
+ * window. Use {@link Configuration#densityDpi} to get the display density.
*/
@Deprecated
public void getMetrics(DisplayMetrics outMetrics) {
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index e6c911e..3833976 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -9,3 +9,6 @@
per-file *Assist* = file:/core/java/android/service/voice/OWNERS
per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
+# System language settings
+per-file *Locale* = file:platform/packages/apps/Settings:/src/com/android/settings/localepicker/OWNERS
\ No newline at end of file
diff --git a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl b/core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl
similarity index 84%
rename from core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl
rename to core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl
index 6ca8cec..0c8e73f 100644
--- a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl
+++ b/core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl
@@ -16,7 +16,8 @@
package com.android.internal.telephony;
-oneway interface ICarrierPrivilegesListener {
+oneway interface ICarrierPrivilegesCallback {
void onCarrierPrivilegesChanged(
in List<String> privilegedPackageNames, in int[] privilegedUids);
+ void onCarrierServiceChanged(in String carrierServicePackageName, in int carrierServiceUid);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 9712d7e..c7fa757 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -32,7 +32,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber;
-import com.android.internal.telephony.ICarrierPrivilegesListener;
+import com.android.internal.telephony.ICarrierPrivilegesCallback;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -102,9 +102,11 @@
void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId,
in List<LinkCapacityEstimate> linkCapacityEstimateList);
- void addCarrierPrivilegesListener(
- int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId);
- void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg);
+ void addCarrierPrivilegesCallback(
+ int phoneId, ICarrierPrivilegesCallback callback, String pkg, String featureId);
+ void removeCarrierPrivilegesCallback(ICarrierPrivilegesCallback callback, String pkg);
void notifyCarrierPrivilegesChanged(
int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
+ void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid);
+
}
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 361ba95..1074004 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -175,27 +175,6 @@
return mCredential;
}
- /**
- * Returns the credential type recognized by {@link StorageManager}. Can be one of
- * {@link StorageManager#CRYPT_TYPE_DEFAULT}, {@link StorageManager#CRYPT_TYPE_PATTERN},
- * {@link StorageManager#CRYPT_TYPE_PIN} or {@link StorageManager#CRYPT_TYPE_PASSWORD}.
- */
- public int getStorageCryptType() {
- if (isNone()) {
- return StorageManager.CRYPT_TYPE_DEFAULT;
- }
- if (isPattern()) {
- return StorageManager.CRYPT_TYPE_PATTERN;
- }
- if (isPin()) {
- return StorageManager.CRYPT_TYPE_PIN;
- }
- if (isPassword()) {
- return StorageManager.CRYPT_TYPE_PASSWORD;
- }
- throw new IllegalStateException("Unhandled credential type");
- }
-
/** Returns whether this is an empty credential */
public boolean isNone() {
ensureNotZeroized();
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 13ca133..f28e2f6 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -396,6 +396,9 @@
{
JNIEnv* env = javavm_to_jnienv(mVM);
+ LOG_ALWAYS_FATAL_IF(env == nullptr,
+ "Binder thread started or Java binder used, but env null. Attach JVM?");
+
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
IPCThreadState* thread_state = IPCThreadState::self();
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 51e150e..15a6bc4 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -48,7 +48,6 @@
import "frameworks/base/core/proto/android/service/diskstats.proto";
import "frameworks/base/core/proto/android/service/dropbox.proto";
import "frameworks/base/core/proto/android/service/graphicsstats.proto";
-import "frameworks/base/core/proto/android/service/netstats.proto";
import "frameworks/base/core/proto/android/service/notification.proto";
import "frameworks/base/core/proto/android/service/package.proto";
import "frameworks/base/core/proto/android/service/print.proto";
@@ -62,6 +61,7 @@
import "frameworks/base/core/proto/android/privacy.proto";
import "frameworks/base/core/proto/android/section.proto";
import "frameworks/base/proto/src/ipconnectivity.proto";
+import "packages/modules/Connectivity/framework/proto/netstats.proto";
import "packages/modules/Permission/service/proto/com/android/role/roleservice.proto";
package android.os;
diff --git a/core/proto/android/service/netstats.proto b/core/proto/android/service/netstats.proto
deleted file mode 100644
index ba2b6d6b..0000000
--- a/core/proto/android/service/netstats.proto
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-syntax = "proto2";
-package android.service;
-
-option java_multiple_files = true;
-option java_outer_classname = "NetworkStatsServiceProto";
-
-// Represents dumpsys from NetworkStatsService (netstats).
-message NetworkStatsServiceDumpProto {
- repeated NetworkInterfaceProto active_interfaces = 1;
-
- repeated NetworkInterfaceProto active_uid_interfaces = 2;
-
- // Device level network stats, which may include non-IP layer traffic.
- optional NetworkStatsRecorderProto dev_stats = 3;
-
- // IP-layer traffic stats.
- optional NetworkStatsRecorderProto xt_stats = 4;
-
- // Per-UID network stats.
- optional NetworkStatsRecorderProto uid_stats = 5;
-
- // Per-UID, per-tag network stats, excluding the default tag (i.e. tag=0).
- optional NetworkStatsRecorderProto uid_tag_stats = 6;
-}
-
-// Corresponds to NetworkStatsService.mActiveIfaces/mActiveUidIfaces.
-message NetworkInterfaceProto {
- // Name of the network interface (eg: wlan).
- optional string interface = 1;
-
- optional NetworkIdentitySetProto identities = 2;
-}
-
-// Corresponds to NetworkIdentitySet.
-message NetworkIdentitySetProto {
- repeated NetworkIdentityProto identities = 1;
-}
-
-// Corresponds to NetworkIdentity.
-message NetworkIdentityProto {
- // Constants from ConnectivityManager.TYPE_*.
- optional int32 type = 1;
-
- optional bool roaming = 4;
-
- optional bool metered = 5;
-
- optional bool default_network = 6;
-
- optional int32 oem_managed_network = 7;
-}
-
-// Corresponds to NetworkStatsRecorder.
-message NetworkStatsRecorderProto {
- optional int64 pending_total_bytes = 1;
-
- optional NetworkStatsCollectionProto complete_history = 2;
-}
-
-// Corresponds to NetworkStatsCollection.
-message NetworkStatsCollectionProto {
- repeated NetworkStatsCollectionStatsProto stats = 1;
-}
-
-// Corresponds to NetworkStatsCollection.mStats.
-message NetworkStatsCollectionStatsProto {
- optional NetworkStatsCollectionKeyProto key = 1;
-
- optional NetworkStatsHistoryProto history = 2;
-}
-
-// Corresponds to NetworkStatsCollection.Key.
-message NetworkStatsCollectionKeyProto {
- optional NetworkIdentitySetProto identity = 1;
-
- optional int32 uid = 2;
-
- optional int32 set = 3;
-
- optional int32 tag = 4;
-}
-
-// Corresponds to NetworkStatsHistory.
-message NetworkStatsHistoryProto {
- // Duration for this bucket in milliseconds.
- optional int64 bucket_duration_ms = 1;
-
- repeated NetworkStatsHistoryBucketProto buckets = 2;
-}
-
-// Corresponds to each bucket in NetworkStatsHistory.
-message NetworkStatsHistoryBucketProto {
- // Bucket start time in milliseconds since epoch.
- optional int64 bucket_start_ms = 1;
-
- optional int64 rx_bytes = 2;
-
- optional int64 rx_packets = 3;
-
- optional int64 tx_bytes = 4;
-
- optional int64 tx_packets = 5;
-
- optional int64 operations = 6;
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2e17779..b87befb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6352,10 +6352,6 @@
android:resource="@xml/autofill_compat_accessibility_service" />
</service>
- <service android:name="com.google.android.startop.iorap.IorapForwardingService$IorapdJobServiceProxy"
- android:permission="android.permission.BIND_JOB_SERVICE" >
- </service>
-
<service android:name="com.android.server.blob.BlobStoreIdleJobService"
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 05fb4c3..919a93b 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
-import android.security.keystore.KeyProperties;
import android.security.maintenance.IKeystoreMaintenance;
import android.system.keystore2.Domain;
import android.system.keystore2.KeyDescriptor;
@@ -158,11 +157,6 @@
* Migrates a key given by the source descriptor to the location designated by the destination
* descriptor.
*
- * If Domain::APP is selected in either source or destination, nspace must be set to
- * {@link KeyProperties#NAMESPACE_APPLICATION}, implying the caller's UID.
- * If the caller has the MIGRATE_ANY_KEY permission, Domain::APP may be used with
- * other nspace values which then indicates the UID of a different application.
- *
* @param source - The key to migrate may be specified by Domain.APP, Domain.SELINUX, or
* Domain.KEY_ID. The caller needs the permissions use, delete, and grant for the
* source namespace.
@@ -189,20 +183,4 @@
return SYSTEM_ERROR;
}
}
-
- /**
- * @see IKeystoreMaintenance#listEntries(int, long)
- */
- @Nullable
- public static KeyDescriptor[] listEntries(int domain, long nspace) {
- try {
- return getService().listEntries(domain, nspace);
- } catch (ServiceSpecificException e) {
- Log.e(TAG, "listEntries failed", e);
- return null;
- } catch (Exception e) {
- Log.e(TAG, "Can not connect to keystore", e);
- return null;
- }
- }
}
diff --git a/libs/WindowManager/Jetpack/tests/OWNERS b/libs/WindowManager/Jetpack/tests/OWNERS
new file mode 100644
index 0000000..f2c3388
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 909476
+# includes OWNERS from parent directories
+charlesccchen@google.com
+diegovela@google.com
diff --git a/packages/ConnectivityT/OWNERS b/packages/ConnectivityT/OWNERS
deleted file mode 100644
index e267d19..0000000
--- a/packages/ConnectivityT/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
-per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
deleted file mode 100644
index 217a1f67c3..0000000
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ /dev/null
@@ -1,205 +0,0 @@
-//
-// 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/DataUsageRequest.*",
- "src/android/net/INetworkStatsService.aidl",
- "src/android/net/INetworkStatsSession.aidl",
- "src/android/net/NetworkIdentity.java",
- "src/android/net/NetworkIdentitySet.java",
- "src/android/net/NetworkStateSnapshot.*",
- "src/android/net/NetworkStats.*",
- "src/android/net/NetworkStatsAccess.*",
- "src/android/net/NetworkStatsCollection.*",
- "src/android/net/NetworkStatsHistory.*",
- "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/EthernetNetworkManagementException.java",
- "src/android/net/EthernetNetworkManagementException.aidl",
- "src/android/net/EthernetNetworkSpecifier.java",
- "src/android/net/EthernetNetworkUpdateRequest.java",
- "src/android/net/EthernetNetworkUpdateRequest.aidl",
- "src/android/net/IEthernetManager.aidl",
- "src/android/net/IEthernetNetworkManagementListener.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",
- ],
-}
-
-// TODO: remove this empty filegroup.
-filegroup {
- name: "framework-connectivity-tiramisu-sources",
- srcs: [],
- visibility: ["//frameworks/base"],
-}
-
-filegroup {
- name: "framework-connectivity-tiramisu-updatable-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",
- "//packages/modules/Connectivity:__subpackages__",
- ],
-}
-
-cc_library_shared {
- name: "libframework-connectivity-tiramisu-jni",
- min_sdk_version: "30",
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- // Don't warn about S API usage even with
- // min_sdk 30: the library is only loaded
- // on S+ devices
- "-Wno-unguarded-availability",
- "-Wthread-safety",
- ],
- srcs: [
- "jni/android_net_TrafficStats.cpp",
- "jni/onload.cpp",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libnativehelper",
- ],
- stl: "none",
- apex_available: [
- "com.android.tethering",
- ],
-}
diff --git a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl
deleted file mode 100644
index d06ca65..0000000
--- a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl
+++ /dev/null
@@ -1,19 +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;
-
-parcelable NetworkStats;
diff --git a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl
deleted file mode 100644
index 3d37488..0000000
--- a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl
+++ /dev/null
@@ -1,19 +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;
-
-parcelable NetworkTemplate;
diff --git a/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl
deleted file mode 100644
index 657bdd1..0000000
--- a/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
deleted file mode 100644
index f3c58b1..0000000
--- a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-#include <android/file_descriptor_jni.h>
-#include <android/multinetwork.h>
-#include <nativehelper/JNIHelp.h>
-
-namespace android {
-
-static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) {
- int fd = AFileDescriptor_getFd(env, fileDescriptor);
- if (fd == -1) return -EBADF;
- return android_tag_socket_with_uid(fd, tag, uid);
-}
-
-static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
- int fd = AFileDescriptor_getFd(env, fileDescriptor);
- if (fd == -1) return -EBADF;
- return android_untag_socket(fd);
-}
-
-static const JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd },
- { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd },
-};
-
-int register_android_net_TrafficStats(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods));
-}
-
-}; // namespace android
-
diff --git a/packages/ConnectivityT/framework-t/jni/onload.cpp b/packages/ConnectivityT/framework-t/jni/onload.cpp
deleted file mode 100644
index 1fb42c6..0000000
--- a/packages/ConnectivityT/framework-t/jni/onload.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-#define LOG_TAG "FrameworkConnectivityJNI"
-
-#include <log/log.h>
-#include <nativehelper/JNIHelp.h>
-
-namespace android {
-
-int register_android_net_TrafficStats(JNIEnv* env);
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
- return JNI_ERR;
- }
-
- if (register_android_net_TrafficStats(env) < 0) return JNI_ERR;
-
- return JNI_VERSION_1_6;
-}
-
-}; // namespace android
-
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
deleted file mode 100644
index 2b6570a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
+++ /dev/null
@@ -1,742 +0,0 @@
-/**
- * Copyright (C) 2015 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.app.usage;
-
-import android.annotation.IntDef;
-import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.TrafficStats;
-import android.os.RemoteException;
-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
- * are returned as results to various queries in {@link NetworkStatsManager}.
- */
-public final class NetworkStats implements AutoCloseable {
- private final static String TAG = "NetworkStats";
-
- private final CloseGuard mCloseGuard = CloseGuard.get();
-
- /**
- * Start timestamp of stats collected
- */
- private final long mStartTimeStamp;
-
- /**
- * End timestamp of stats collected
- */
- private final long mEndTimeStamp;
-
- /**
- * Non-null array indicates the query enumerates over uids.
- */
- private int[] mUids;
-
- /**
- * Index of the current uid in mUids when doing uid enumeration or a single uid value,
- * depending on query type.
- */
- private int mUidOrUidIndex;
-
- /**
- * Tag id in case if was specified in the query.
- */
- private int mTag = android.net.NetworkStats.TAG_NONE;
-
- /**
- * State in case it was not specified in the query.
- */
- private int mState = Bucket.STATE_ALL;
-
- /**
- * The session while the query requires it, null if all the stats have been collected or close()
- * has been called.
- */
- private INetworkStatsSession mSession;
- private NetworkTemplate mTemplate;
-
- /**
- * Results of a summary query.
- */
- private android.net.NetworkStats mSummary = null;
-
- /**
- * Results of detail queries.
- */
- private NetworkStatsHistory mHistory = null;
-
- /**
- * Where we are in enumerating over the current result.
- */
- private int mEnumerationIndex = 0;
-
- /**
- * Recycling entry objects to prevent heap fragmentation.
- */
- private android.net.NetworkStats.Entry mRecycledSummaryEntry = null;
- private NetworkStatsHistory.Entry mRecycledHistoryEntry = null;
-
- /** @hide */
- NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp,
- long endTimestamp, INetworkStatsService statsService)
- throws RemoteException, SecurityException {
- // Open network stats session
- mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName());
- mCloseGuard.open("close");
- mTemplate = template;
- mStartTimeStamp = startTimestamp;
- mEndTimeStamp = endTimestamp;
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- } finally {
- super.finalize();
- }
- }
-
- // -------------------------BEGINNING OF PUBLIC API-----------------------------------
-
- /**
- * Buckets are the smallest elements of a query result. As some dimensions of a result may be
- * aggregated (e.g. time or state) some values may be equal across all buckets.
- */
- public static class Bucket {
- /** @hide */
- @IntDef(prefix = { "STATE_" }, value = {
- STATE_ALL,
- STATE_DEFAULT,
- STATE_FOREGROUND
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface State {}
-
- /**
- * Combined usage across all states.
- */
- public static final int STATE_ALL = -1;
-
- /**
- * Usage not accounted for in any other state.
- */
- public static final int STATE_DEFAULT = 0x1;
-
- /**
- * Foreground usage.
- */
- public static final int STATE_FOREGROUND = 0x2;
-
- /**
- * Special UID value for aggregate/unspecified.
- */
- public static final int UID_ALL = android.net.NetworkStats.UID_ALL;
-
- /**
- * Special UID value for removed apps.
- */
- public static final int UID_REMOVED = TrafficStats.UID_REMOVED;
-
- /**
- * Special UID value for data usage by tethering.
- */
- public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
-
- /** @hide */
- @IntDef(prefix = { "METERED_" }, value = {
- METERED_ALL,
- METERED_NO,
- METERED_YES
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Metered {}
-
- /**
- * Combined usage across all metered states. Covers metered and unmetered usage.
- */
- public static final int METERED_ALL = -1;
-
- /**
- * Usage that occurs on an unmetered network.
- */
- public static final int METERED_NO = 0x1;
-
- /**
- * Usage that occurs on a metered network.
- *
- * <p>A network is classified as metered when the user is sensitive to heavy data usage on
- * that connection.
- */
- public static final int METERED_YES = 0x2;
-
- /** @hide */
- @IntDef(prefix = { "ROAMING_" }, value = {
- ROAMING_ALL,
- ROAMING_NO,
- ROAMING_YES
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Roaming {}
-
- /**
- * Combined usage across all roaming states. Covers both roaming and non-roaming usage.
- */
- public static final int ROAMING_ALL = -1;
-
- /**
- * Usage that occurs on a home, non-roaming network.
- *
- * <p>Any cellular usage in this bucket was incurred while the device was connected to a
- * tower owned or operated by the user's wireless carrier, or a tower that the user's
- * wireless carrier has indicated should be treated as a home network regardless.
- *
- * <p>This is also the default value for network types that do not support roaming.
- */
- public static final int ROAMING_NO = 0x1;
-
- /**
- * Usage that occurs on a roaming network.
- *
- * <p>Any cellular usage in this bucket as incurred while the device was roaming on another
- * carrier's network, for which additional charges may apply.
- */
- public static final int ROAMING_YES = 0x2;
-
- /** @hide */
- @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = {
- DEFAULT_NETWORK_ALL,
- DEFAULT_NETWORK_NO,
- DEFAULT_NETWORK_YES
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface DefaultNetworkStatus {}
-
- /**
- * Combined usage for this network regardless of default network status.
- */
- public static final int DEFAULT_NETWORK_ALL = -1;
-
- /**
- * Usage that occurs while this network is not a default network.
- *
- * <p>This implies that the app responsible for this usage requested that it occur on a
- * specific network different from the one(s) the system would have selected for it.
- */
- public static final int DEFAULT_NETWORK_NO = 0x1;
-
- /**
- * Usage that occurs while this network is a default network.
- *
- * <p>This implies that the app either did not select a specific network for this usage,
- * or it selected a network that the system could have selected for app traffic.
- */
- public static final int DEFAULT_NETWORK_YES = 0x2;
-
- /**
- * Special TAG value for total data across all tags
- */
- public static final int TAG_NONE = android.net.NetworkStats.TAG_NONE;
-
- private int mUid;
- private int mTag;
- private int mState;
- private int mDefaultNetworkStatus;
- private int mMetered;
- private int mRoaming;
- private long mBeginTimeStamp;
- private long mEndTimeStamp;
- private long mRxBytes;
- private long mRxPackets;
- private long mTxBytes;
- private long mTxPackets;
-
- private static int convertSet(@State int state) {
- switch (state) {
- case STATE_ALL: return android.net.NetworkStats.SET_ALL;
- case STATE_DEFAULT: return android.net.NetworkStats.SET_DEFAULT;
- case STATE_FOREGROUND: return android.net.NetworkStats.SET_FOREGROUND;
- }
- return 0;
- }
-
- private static @State int convertState(int networkStatsSet) {
- switch (networkStatsSet) {
- case android.net.NetworkStats.SET_ALL : return STATE_ALL;
- case android.net.NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
- case android.net.NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND;
- }
- return 0;
- }
-
- private static int convertUid(int uid) {
- switch (uid) {
- case TrafficStats.UID_REMOVED: return UID_REMOVED;
- case TrafficStats.UID_TETHERING: return UID_TETHERING;
- }
- return uid;
- }
-
- private static int convertTag(int tag) {
- switch (tag) {
- case android.net.NetworkStats.TAG_NONE: return TAG_NONE;
- }
- return tag;
- }
-
- private static @Metered int convertMetered(int metered) {
- switch (metered) {
- case android.net.NetworkStats.METERED_ALL : return METERED_ALL;
- case android.net.NetworkStats.METERED_NO: return METERED_NO;
- case android.net.NetworkStats.METERED_YES: return METERED_YES;
- }
- return 0;
- }
-
- private static @Roaming int convertRoaming(int roaming) {
- switch (roaming) {
- case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
- case android.net.NetworkStats.ROAMING_NO: return ROAMING_NO;
- case android.net.NetworkStats.ROAMING_YES: return ROAMING_YES;
- }
- return 0;
- }
-
- private static @DefaultNetworkStatus int convertDefaultNetworkStatus(
- int defaultNetworkStatus) {
- switch (defaultNetworkStatus) {
- case android.net.NetworkStats.DEFAULT_NETWORK_ALL : return DEFAULT_NETWORK_ALL;
- case android.net.NetworkStats.DEFAULT_NETWORK_NO: return DEFAULT_NETWORK_NO;
- case android.net.NetworkStats.DEFAULT_NETWORK_YES: return DEFAULT_NETWORK_YES;
- }
- return 0;
- }
-
- public Bucket() {
- }
-
- /**
- * Key of the bucket. Usually an app uid or one of the following special values:<p />
- * <ul>
- * <li>{@link #UID_REMOVED}</li>
- * <li>{@link #UID_TETHERING}</li>
- * <li>{@link android.os.Process#SYSTEM_UID}</li>
- * </ul>
- * @return Bucket key.
- */
- public int getUid() {
- return mUid;
- }
-
- /**
- * Tag of the bucket.<p />
- * @return Bucket tag.
- */
- public int getTag() {
- return mTag;
- }
-
- /**
- * Usage state. One of the following values:<p/>
- * <ul>
- * <li>{@link #STATE_ALL}</li>
- * <li>{@link #STATE_DEFAULT}</li>
- * <li>{@link #STATE_FOREGROUND}</li>
- * </ul>
- * @return Usage state.
- */
- public @State int getState() {
- return mState;
- }
-
- /**
- * Metered state. One of the following values:<p/>
- * <ul>
- * <li>{@link #METERED_ALL}</li>
- * <li>{@link #METERED_NO}</li>
- * <li>{@link #METERED_YES}</li>
- * </ul>
- * <p>A network is classified as metered when the user is sensitive to heavy data usage on
- * that connection. Apps may warn before using these networks for large downloads. The
- * metered state can be set by the user within data usage network restrictions.
- */
- public @Metered int getMetered() {
- return mMetered;
- }
-
- /**
- * Roaming state. One of the following values:<p/>
- * <ul>
- * <li>{@link #ROAMING_ALL}</li>
- * <li>{@link #ROAMING_NO}</li>
- * <li>{@link #ROAMING_YES}</li>
- * </ul>
- */
- public @Roaming int getRoaming() {
- return mRoaming;
- }
-
- /**
- * Default network status. One of the following values:<p/>
- * <ul>
- * <li>{@link #DEFAULT_NETWORK_ALL}</li>
- * <li>{@link #DEFAULT_NETWORK_NO}</li>
- * <li>{@link #DEFAULT_NETWORK_YES}</li>
- * </ul>
- */
- public @DefaultNetworkStatus int getDefaultNetworkStatus() {
- return mDefaultNetworkStatus;
- }
-
- /**
- * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @return Start of interval.
- */
- public long getStartTimeStamp() {
- return mBeginTimeStamp;
- }
-
- /**
- * End timestamp of the bucket's time interval. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @return End of interval.
- */
- public long getEndTimeStamp() {
- return mEndTimeStamp;
- }
-
- /**
- * Number of bytes received during the bucket's time interval. Statistics are measured at
- * the network layer, so they include both TCP and UDP usage.
- * @return Number of bytes.
- */
- public long getRxBytes() {
- return mRxBytes;
- }
-
- /**
- * Number of bytes transmitted during the bucket's time interval. Statistics are measured at
- * the network layer, so they include both TCP and UDP usage.
- * @return Number of bytes.
- */
- public long getTxBytes() {
- return mTxBytes;
- }
-
- /**
- * Number of packets received during the bucket's time interval. Statistics are measured at
- * the network layer, so they include both TCP and UDP usage.
- * @return Number of packets.
- */
- public long getRxPackets() {
- return mRxPackets;
- }
-
- /**
- * Number of packets transmitted during the bucket's time interval. Statistics are measured
- * at the network layer, so they include both TCP and UDP usage.
- * @return Number of packets.
- */
- public long getTxPackets() {
- return mTxPackets;
- }
- }
-
- /**
- * Fills the recycled bucket with data of the next bin in the enumeration.
- * @param bucketOut Bucket to be filled with data.
- * @return true if successfully filled the bucket, false otherwise.
- */
- public boolean getNextBucket(Bucket bucketOut) {
- if (mSummary != null) {
- return getNextSummaryBucket(bucketOut);
- } else {
- return getNextHistoryBucket(bucketOut);
- }
- }
-
- /**
- * Check if it is possible to ask for a next bucket in the enumeration.
- * @return true if there is at least one more bucket.
- */
- public boolean hasNextBucket() {
- if (mSummary != null) {
- return mEnumerationIndex < mSummary.size();
- } else if (mHistory != null) {
- return mEnumerationIndex < mHistory.size()
- || hasNextUid();
- }
- return false;
- }
-
- /**
- * Closes the enumeration. Call this method before this object gets out of scope.
- */
- @Override
- public void close() {
- if (mSession != null) {
- try {
- mSession.close();
- } catch (RemoteException e) {
- Log.w(TAG, e);
- // Otherwise, meh
- }
- }
- mSession = null;
- if (mCloseGuard != null) {
- mCloseGuard.close();
- }
- }
-
- // -------------------------END OF PUBLIC API-----------------------------------
-
- /**
- * Collects device summary results into a Bucket.
- * @throws RemoteException
- */
- Bucket getDeviceSummaryForNetwork() throws RemoteException {
- mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, mStartTimeStamp, mEndTimeStamp);
-
- // Setting enumeration index beyond end to avoid accidental enumeration over data that does
- // not belong to the calling user.
- mEnumerationIndex = mSummary.size();
-
- return getSummaryAggregate();
- }
-
- /**
- * Collects summary results and sets summary enumeration mode.
- * @throws RemoteException
- */
- void startSummaryEnumeration() throws RemoteException {
- mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
- false /* includeTags */);
- mEnumerationIndex = 0;
- }
-
- /**
- * Collects tagged summary results and sets summary enumeration mode.
- * @throws RemoteException
- */
- void startTaggedSummaryEnumeration() throws RemoteException {
- mSummary = mSession.getTaggedSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp);
- mEnumerationIndex = 0;
- }
-
- /**
- * Collects history results for uid and resets history enumeration index.
- */
- void startHistoryUidEnumeration(int uid, int tag, int state) {
- mHistory = null;
- try {
- mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
- Bucket.convertSet(state), tag, NetworkStatsHistory.FIELD_ALL,
- mStartTimeStamp, mEndTimeStamp);
- setSingleUidTagState(uid, tag, state);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- // Leaving mHistory null
- }
- mEnumerationIndex = 0;
- }
-
- /**
- * Collects history results for network and resets history enumeration index.
- */
- void startHistoryDeviceEnumeration() {
- try {
- mHistory = mSession.getHistoryIntervalForNetwork(
- mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- mHistory = null;
- }
- mEnumerationIndex = 0;
- }
-
- /**
- * Starts uid enumeration for current user.
- * @throws RemoteException
- */
- void startUserUidEnumeration() throws RemoteException {
- // TODO: getRelevantUids should be sensitive to time interval. When that's done,
- // the filtering logic below can be removed.
- int[] uids = mSession.getRelevantUids();
- // Filtering of uids with empty history.
- final ArrayList<Integer> filteredUids = new ArrayList<>();
- for (int uid : uids) {
- try {
- NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
- android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
- NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
- if (history != null && history.size() > 0) {
- filteredUids.add(uid);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Error while getting history of uid " + uid, e);
- }
- }
- mUids = CollectionUtils.toIntArray(filteredUids);
- mUidOrUidIndex = -1;
- stepHistory();
- }
-
- /**
- * Steps to next uid in enumeration and collects history for that.
- */
- private void stepHistory(){
- if (hasNextUid()) {
- stepUid();
- mHistory = null;
- try {
- mHistory = mSession.getHistoryIntervalForUid(mTemplate, getUid(),
- android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
- NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- // Leaving mHistory null
- }
- mEnumerationIndex = 0;
- }
- }
-
- private void fillBucketFromSummaryEntry(Bucket bucketOut) {
- bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
- bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
- bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
- bucketOut.mDefaultNetworkStatus = Bucket.convertDefaultNetworkStatus(
- mRecycledSummaryEntry.defaultNetwork);
- bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered);
- bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
- bucketOut.mBeginTimeStamp = mStartTimeStamp;
- bucketOut.mEndTimeStamp = mEndTimeStamp;
- bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
- bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets;
- bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes;
- bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets;
- }
-
- /**
- * Getting the next item in summary enumeration.
- * @param bucketOut Next item will be set here.
- * @return true if a next item could be set.
- */
- private boolean getNextSummaryBucket(Bucket bucketOut) {
- if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
- mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
- fillBucketFromSummaryEntry(bucketOut);
- return true;
- }
- return false;
- }
-
- Bucket getSummaryAggregate() {
- if (mSummary == null) {
- return null;
- }
- Bucket bucket = new Bucket();
- if (mRecycledSummaryEntry == null) {
- mRecycledSummaryEntry = new android.net.NetworkStats.Entry();
- }
- mSummary.getTotal(mRecycledSummaryEntry);
- fillBucketFromSummaryEntry(bucket);
- return bucket;
- }
-
- /**
- * Getting the next item in a history enumeration.
- * @param bucketOut Next item will be set here.
- * @return true if a next item could be set.
- */
- private boolean getNextHistoryBucket(Bucket bucketOut) {
- if (bucketOut != null && mHistory != null) {
- if (mEnumerationIndex < mHistory.size()) {
- mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
- mRecycledHistoryEntry);
- bucketOut.mUid = Bucket.convertUid(getUid());
- bucketOut.mTag = Bucket.convertTag(mTag);
- bucketOut.mState = mState;
- bucketOut.mDefaultNetworkStatus = Bucket.DEFAULT_NETWORK_ALL;
- bucketOut.mMetered = Bucket.METERED_ALL;
- bucketOut.mRoaming = Bucket.ROAMING_ALL;
- bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
- bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
- mRecycledHistoryEntry.bucketDuration;
- bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
- bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
- bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
- bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets;
- return true;
- } else if (hasNextUid()) {
- stepHistory();
- return getNextHistoryBucket(bucketOut);
- }
- }
- return false;
- }
-
- // ------------------ UID LOGIC------------------------
-
- private boolean isUidEnumeration() {
- return mUids != null;
- }
-
- private boolean hasNextUid() {
- return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length;
- }
-
- private int getUid() {
- // Check if uid enumeration.
- if (isUidEnumeration()) {
- if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) {
- throw new IndexOutOfBoundsException(
- "Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length);
- }
- return mUids[mUidOrUidIndex];
- }
- // Single uid mode.
- return mUidOrUidIndex;
- }
-
- private void setSingleUidTagState(int uid, int tag, int state) {
- mUidOrUidIndex = uid;
- mTag = tag;
- mState = state;
- }
-
- private void stepUid() {
- if (mUids != null) {
- ++mUidOrUidIndex;
- }
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
deleted file mode 100644
index bf518b2..0000000
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ /dev/null
@@ -1,1181 +0,0 @@
-/**
- * Copyright (C) 2015 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.app.usage;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-
-import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.annotation.WorkerThread;
-import android.app.usage.NetworkStats.Bucket;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.DataUsageRequest;
-import android.net.INetworkStatsService;
-import android.net.Network;
-import android.net.NetworkStack;
-import android.net.NetworkStateSnapshot;
-import android.net.NetworkTemplate;
-import android.net.UnderlyingNetworkInfo;
-import android.net.netstats.IUsageCallback;
-import android.net.netstats.NetworkStatsDataMigrationUtils;
-import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.Build;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * Provides access to network usage history and statistics. Usage data is collected in
- * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
- * <p />
- * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
- * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
- * data about themselves. See the below note for special cases in which apps can obtain data about
- * other applications.
- * <h3>
- * Summary queries
- * </h3>
- * {@link #querySummaryForDevice} <p />
- * {@link #querySummaryForUser} <p />
- * {@link #querySummary} <p />
- * These queries aggregate network usage across the whole interval. Therefore there will be only one
- * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
- * and device-wide summaries a single bucket containing the totalised network usage is returned.
- * <h3>
- * History queries
- * </h3>
- * {@link #queryDetailsForUid} <p />
- * {@link #queryDetails} <p />
- * These queries do not aggregate over time but do aggregate over state, metered and roaming.
- * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
- * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
- * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
- * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
- * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
- * <p />
- * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
- * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
- * which is a system-level permission and will not be granted to third-party apps. However,
- * declaring the permission implies intention to use the API and the user of the device can grant
- * permission through the Settings application.
- * <p />
- * Profile owner apps are automatically granted permission to query data on the profile they manage
- * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
- * privileged apps likewise get access to usage data for all users on the device.
- * <p />
- * In addition to tethering usage, usage by removed users and apps, and usage by the system
- * is also included in the results for callers with one of these higher levels of access.
- * <p />
- * <b>NOTE:</b> Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required
- * the above permission, even to access an app's own data usage, and carrier-privileged apps were
- * not included.
- */
-@SystemService(Context.NETWORK_STATS_SERVICE)
-public class NetworkStatsManager {
- private static final String TAG = "NetworkStatsManager";
- private static final boolean DBG = false;
-
- /** @hide */
- public static final int CALLBACK_LIMIT_REACHED = 0;
- /** @hide */
- public static final int CALLBACK_RELEASED = 1;
-
- /**
- * Minimum data usage threshold for registering usage callbacks.
- *
- * Requests registered with a threshold lower than this will only be triggered once this minimum
- * is reached.
- * @hide
- */
- public static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
-
- private final Context mContext;
- private final INetworkStatsService mService;
-
- /**
- * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT}
- * instead.
- * @hide
- */
- @Deprecated
- public static final String PREFIX_DEV = "dev";
-
- /** @hide */
- public static final int FLAG_POLL_ON_OPEN = 1 << 0;
- /** @hide */
- public static final int FLAG_POLL_FORCE = 1 << 1;
- /** @hide */
- public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
-
- /**
- * 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 is a concept added by NetworkStats on top of the telephony
- * constants for backward compatibility of metrics so this should not be overlapped with any of
- * the {@code TelephonyManager.NETWORK_TYPE_*} constants.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int NETWORK_TYPE_5G_NSA = -2;
-
- private int mFlags;
-
- /** @hide */
- @VisibleForTesting
- public NetworkStatsManager(Context context, INetworkStatsService service) {
- mContext = context;
- mService = service;
- setPollOnOpen(true);
- setAugmentWithSubscriptionPlan(true);
- }
-
- /** @hide */
- public INetworkStatsService getBinder() {
- return mService;
- }
-
- /**
- * Set poll on open flag to indicate the poll is needed before service gets statistics
- * result. This is default enabled. However, for any non-privileged caller, the poll might
- * be omitted in case of rate limiting.
- *
- * @param pollOnOpen true if poll is needed.
- * @hide
- */
- // The system will ignore any non-default values for non-privileged
- // processes, so processes that don't hold the appropriate permissions
- // can make no use of this API.
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- public void setPollOnOpen(boolean pollOnOpen) {
- if (pollOnOpen) {
- mFlags |= FLAG_POLL_ON_OPEN;
- } else {
- mFlags &= ~FLAG_POLL_ON_OPEN;
- }
- }
-
- /**
- * Set poll force flag to indicate that calling any subsequent query method will force a stats
- * poll.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @SystemApi(client = MODULE_LIBRARIES)
- public void setPollForce(boolean pollForce) {
- if (pollForce) {
- mFlags |= FLAG_POLL_FORCE;
- } else {
- mFlags &= ~FLAG_POLL_FORCE;
- }
- }
-
- /** @hide */
- public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
- if (augmentWithSubscriptionPlan) {
- mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
- } else {
- mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
- }
- }
-
- /**
- * 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) {
- Objects.requireNonNull(template);
- 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.
- }
-
- /**
- * 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 are going to be the same as the
- * 'startTime' and 'endTime' parameters. 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 networkType As defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
- * etc.
- * @param subscriberId If applicable, the subscriber id of the network interface.
- * <p>Starting with API level 29, the {@code subscriberId} is guarded by
- * additional restrictions. Calling apps that do not meet the new
- * requirements to access the {@code subscriberId} can provide a {@code
- * null} value when querying for the mobile network type to receive usage
- * for all mobile networks. For additional details see {@link
- * TelephonyManager#getSubscriberId()}.
- * <p>Starting with API level 31, calling apps can provide a
- * {@code subscriberId} with wifi network type to receive usage for
- * wifi networks which is under the given subscription if applicable.
- * Otherwise, pass {@code null} when querying all wifi networks.
- * @param startTime Start of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @param endTime End of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @return Bucket object or null if permissions are insufficient or error happened during
- * statistics collection.
- */
- @WorkerThread
- public Bucket querySummaryForDevice(int networkType, String subscriberId,
- long startTime, long endTime) throws SecurityException, RemoteException {
- NetworkTemplate template;
- try {
- template = createTemplate(networkType, subscriberId);
- } catch (IllegalArgumentException e) {
- if (DBG) Log.e(TAG, "Cannot create template", e);
- return null;
- }
-
- return querySummaryForDevice(template, startTime, endTime);
- }
-
- /**
- * Query network usage statistics summaries. Result is summarised data usage for all uids
- * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
- * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
- * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
- * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
- * 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 networkType As defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
- * etc.
- * @param subscriberId If applicable, the subscriber id of the network interface.
- * <p>Starting with API level 29, the {@code subscriberId} is guarded by
- * additional restrictions. Calling apps that do not meet the new
- * requirements to access the {@code subscriberId} can provide a {@code
- * null} value when querying for the mobile network type to receive usage
- * for all mobile networks. For additional details see {@link
- * TelephonyManager#getSubscriberId()}.
- * <p>Starting with API level 31, calling apps can provide a
- * {@code subscriberId} with wifi network type to receive usage for
- * wifi networks which is under the given subscription if applicable.
- * Otherwise, pass {@code null} when querying all wifi networks.
- * @param startTime Start of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @param endTime End of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @return Bucket object or null if permissions are insufficient or error happened during
- * statistics collection.
- */
- @WorkerThread
- public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
- NetworkTemplate template;
- try {
- template = createTemplate(networkType, subscriberId);
- } catch (IllegalArgumentException e) {
- if (DBG) Log.e(TAG, "Cannot create template", e);
- return null;
- }
-
- NetworkStats stats;
- stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- stats.startSummaryEnumeration();
-
- stats.close();
- return stats.getSummaryAggregate();
- }
-
- /**
- * Query network usage statistics summaries. Result filtered to include only uids belonging to
- * calling user. Result is aggregated over time, hence all buckets will have the same start and
- * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
- * means buckets' start and end timestamps are going to be the same as the 'startTime' and
- * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
- * be the same.
- * This may take a long time, and apps should avoid calling this on their main thread.
- *
- * @param networkType As defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
- * etc.
- * @param subscriberId If applicable, the subscriber id of the network interface.
- * <p>Starting with API level 29, the {@code subscriberId} is guarded by
- * additional restrictions. Calling apps that do not meet the new
- * requirements to access the {@code subscriberId} can provide a {@code
- * null} value when querying for the mobile network type to receive usage
- * for all mobile networks. For additional details see {@link
- * TelephonyManager#getSubscriberId()}.
- * <p>Starting with API level 31, calling apps can provide a
- * {@code subscriberId} with wifi network type to receive usage for
- * wifi networks which is under the given subscription if applicable.
- * Otherwise, pass {@code null} when querying all wifi networks.
- * @param startTime Start of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @param endTime End of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @return Statistics object or null if permissions are insufficient or error happened during
- * statistics collection.
- */
- @WorkerThread
- public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
- NetworkTemplate template;
- try {
- template = createTemplate(networkType, subscriberId);
- } catch (IllegalArgumentException e) {
- if (DBG) Log.e(TAG, "Cannot create template", e);
- return null;
- }
-
- return querySummary(template, startTime, endTime);
- }
-
- /**
- * 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
- */
- @NonNull
- @SystemApi(client = MODULE_LIBRARIES)
- @WorkerThread
- public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
- long endTime) throws SecurityException {
- Objects.requireNonNull(template);
- 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.
- }
-
- /**
- * Query tagged network usage statistics summaries.
- *
- * The results will only include tagged 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 System#currentTimeMillis}.
- * @param endTime End of period, in milliseconds since the Unix epoch, see
- * {@link System#currentTimeMillis}.
- * @return Statistics which is described above.
- * @hide
- */
- @NonNull
- @SystemApi(client = MODULE_LIBRARIES)
- @WorkerThread
- public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime,
- long endTime) throws SecurityException {
- Objects.requireNonNull(template);
- try {
- NetworkStats result =
- new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startTaggedSummaryEnumeration();
- return result;
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return null; // To make the compiler happy.
- }
-
- /**
- * Query usage statistics details for networks matching a given {@link NetworkTemplate}.
- *
- * Result is not aggregated over time. This means buckets' start and
- * end timestamps will be between 'startTime' and 'endTime' parameters.
- * <p>Only includes buckets whose entire time period is included between
- * startTime and endTime. Doesn't interpolate or return partial buckets.
- * Since bucket length is in the order of hours, this
- * method cannot be used to measure data usage on a fine grained time scale.
- * 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
- */
- @NonNull
- @SystemApi(client = MODULE_LIBRARIES)
- @WorkerThread
- public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
- long startTime, long endTime) {
- Objects.requireNonNull(template);
- try {
- final NetworkStats result =
- new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startHistoryDeviceEnumeration();
- return result;
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
-
- return null; // To make the compiler happy.
- }
-
- /**
- * Query network usage statistics details for a given uid.
- * This may take a long time, and apps should avoid calling this on their main thread.
- *
- * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
- */
- @WorkerThread
- public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
- long startTime, long endTime, int uid) throws SecurityException {
- return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
- NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
- }
-
- /** @hide */
- public NetworkStats queryDetailsForUid(NetworkTemplate template,
- long startTime, long endTime, int uid) throws SecurityException {
- return queryDetailsForUidTagState(template, startTime, endTime, uid,
- NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
- }
-
- /**
- * Query network usage statistics details for a given uid and tag.
- * This may take a long time, and apps should avoid calling this on their main thread.
- *
- * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
- */
- @WorkerThread
- public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
- long startTime, long endTime, int uid, int tag) throws SecurityException {
- return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
- tag, NetworkStats.Bucket.STATE_ALL);
- }
-
- /**
- * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
- * belonging to calling user. Result is not aggregated over time. This means buckets' start and
- * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
- * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
- * the same as the 'state' parameter.
- * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
- * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
- * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
- * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
- * interpolate across partial buckets. Since bucket length is in the order of hours, this
- * method cannot be used to measure data usage on a fine grained time scale.
- * This may take a long time, and apps should avoid calling this on their main thread.
- *
- * @param networkType As defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
- * etc.
- * @param subscriberId If applicable, the subscriber id of the network interface.
- * <p>Starting with API level 29, the {@code subscriberId} is guarded by
- * additional restrictions. Calling apps that do not meet the new
- * requirements to access the {@code subscriberId} can provide a {@code
- * null} value when querying for the mobile network type to receive usage
- * for all mobile networks. For additional details see {@link
- * TelephonyManager#getSubscriberId()}.
- * <p>Starting with API level 31, calling apps can provide a
- * {@code subscriberId} with wifi network type to receive usage for
- * wifi networks which is under the given subscription if applicable.
- * Otherwise, pass {@code null} when querying all wifi networks.
- * @param startTime Start of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @param endTime End of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @param uid UID of app
- * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
- * across all the tags.
- * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
- * traffic from all states.
- * @return Statistics object or null if an error happened during statistics collection.
- * @throws SecurityException if permissions are insufficient to read network statistics.
- */
- @WorkerThread
- public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
- long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
- NetworkTemplate template;
- template = createTemplate(networkType, subscriberId);
-
- return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
- }
-
- /**
- * Query network usage statistics details for a given template, uid, tag, and state.
- *
- * Only usable for uids belonging to calling user. Result is not aggregated over time.
- * This means buckets' start and end timestamps are going to be between 'startTime' and
- * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
- * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
- * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
- * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
- * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
- * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
- * interpolate across partial buckets. Since bucket length is in the order of hours, this
- * method cannot be used to measure data usage on a fine grained time scale.
- * 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}.
- * @param uid UID of app
- * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
- * across all the tags.
- * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
- * traffic from all states.
- * @return Statistics which is described above.
- * @hide
- */
- @NonNull
- @SystemApi(client = MODULE_LIBRARIES)
- @WorkerThread
- public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
- long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
- Objects.requireNonNull(template);
- try {
- final NetworkStats result = new NetworkStats(
- mContext, template, mFlags, startTime, endTime, mService);
- result.startHistoryUidEnumeration(uid, tag, state);
- return result;
- } catch (RemoteException e) {
- Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
- + " state=" + state, e);
- e.rethrowFromSystemServer();
- }
-
- return null; // To make the compiler happy.
- }
-
- /**
- * Query network usage statistics details. Result filtered to include only uids belonging to
- * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
- * metered, nor roaming. This means buckets' start and end timestamps are going to be between
- * 'startTime' and 'endTime' parameters. State is going to be
- * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
- * tag {@link NetworkStats.Bucket#TAG_NONE},
- * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
- * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
- * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
- * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
- * interpolate across partial buckets. Since bucket length is in the order of hours, this
- * method cannot be used to measure data usage on a fine grained time scale.
- * This may take a long time, and apps should avoid calling this on their main thread.
- *
- * @param networkType As defined in {@link ConnectivityManager}, e.g.
- * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
- * etc.
- * @param subscriberId If applicable, the subscriber id of the network interface.
- * <p>Starting with API level 29, the {@code subscriberId} is guarded by
- * additional restrictions. Calling apps that do not meet the new
- * requirements to access the {@code subscriberId} can provide a {@code
- * null} value when querying for the mobile network type to receive usage
- * for all mobile networks. For additional details see {@link
- * TelephonyManager#getSubscriberId()}.
- * <p>Starting with API level 31, calling apps can provide a
- * {@code subscriberId} with wifi network type to receive usage for
- * wifi networks which is under the given subscription if applicable.
- * Otherwise, pass {@code null} when querying all wifi networks.
- * @param startTime Start of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @param endTime End of period. Defined in terms of "Unix time", see
- * {@link java.lang.System#currentTimeMillis}.
- * @return Statistics object or null if permissions are insufficient or error happened during
- * statistics collection.
- */
- @WorkerThread
- public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
- NetworkTemplate template;
- try {
- template = createTemplate(networkType, subscriberId);
- } catch (IllegalArgumentException e) {
- if (DBG) Log.e(TAG, "Cannot create template", e);
- return null;
- }
-
- NetworkStats result;
- result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startUserUidEnumeration();
- return result;
- }
-
- /**
- * Query realtime mobile network usage statistics.
- *
- * Return a snapshot of current UID network statistics, as it applies
- * to the mobile radios of the device. The snapshot will include any
- * tethering traffic, video calling data usage and count of
- * network operations set by {@link TrafficStats#incrementOperationCount}
- * made over a mobile radio.
- * The snapshot will not include any statistics that cannot be seen by
- * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- @NonNull public android.net.NetworkStats getMobileUidStats() {
- try {
- return mService.getUidStatsForTransport(TRANSPORT_CELLULAR);
- } catch (RemoteException e) {
- if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats");
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Query realtime Wi-Fi network usage statistics.
- *
- * Return a snapshot of current UID network statistics, as it applies
- * to the Wi-Fi radios of the device. The snapshot will include any
- * tethering traffic, video calling data usage and count of
- * network operations set by {@link TrafficStats#incrementOperationCount}
- * made over a Wi-Fi radio.
- * The snapshot will not include any statistics that cannot be seen by
- * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- @NonNull public android.net.NetworkStats getWifiUidStats() {
- try {
- return mService.getUidStatsForTransport(TRANSPORT_WIFI);
- } catch (RemoteException e) {
- if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats");
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Registers to receive notifications about data usage on specified networks.
- *
- * <p>The callbacks will continue to be called as long as the process is alive or
- * {@link #unregisterUsageCallback} is called.
- *
- * @param template Template used to match networks. See {@link NetworkTemplate}.
- * @param thresholdBytes Threshold in bytes to be notified on. Provided values lower than 2MiB
- * will be clamped for callers except callers with the NETWORK_STACK
- * permission.
- * @param executor The executor on which callback will be invoked. The provided {@link Executor}
- * must run callback sequentially, otherwise the order of callbacks cannot be
- * guaranteed.
- * @param callback The {@link UsageCallback} that the system will call when data usage
- * has exceeded the specified threshold.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK}, conditional = true)
- public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
- @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
- Objects.requireNonNull(template, "NetworkTemplate cannot be null");
- Objects.requireNonNull(callback, "UsageCallback cannot be null");
- Objects.requireNonNull(executor, "Executor cannot be null");
-
- final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
- template, thresholdBytes);
- try {
- final UsageCallbackWrapper callbackWrapper =
- new UsageCallbackWrapper(executor, callback);
- callback.request = mService.registerUsageCallback(
- mContext.getOpPackageName(), request, callbackWrapper);
- if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
-
- if (callback.request == null) {
- Log.e(TAG, "Request from callback is null; should not happen");
- }
- } catch (RemoteException e) {
- if (DBG) Log.d(TAG, "Remote exception when registering callback");
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Registers to receive notifications about data usage on specified networks.
- *
- * @see #registerUsageCallback(int, String, long, UsageCallback, Handler)
- */
- public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
- UsageCallback callback) {
- registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
- null /* handler */);
- }
-
- /**
- * Registers to receive notifications about data usage on specified networks.
- *
- * <p>The callbacks will continue to be called as long as the process is live or
- * {@link #unregisterUsageCallback} is called.
- *
- * @param networkType Type of network to monitor. Either
- {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
- * @param subscriberId If applicable, the subscriber id of the network interface.
- * <p>Starting with API level 29, the {@code subscriberId} is guarded by
- * additional restrictions. Calling apps that do not meet the new
- * requirements to access the {@code subscriberId} can provide a {@code
- * null} value when registering for the mobile network type to receive
- * notifications for all mobile networks. For additional details see {@link
- * TelephonyManager#getSubscriberId()}.
- * <p>Starting with API level 31, calling apps can provide a
- * {@code subscriberId} with wifi network type to receive usage for
- * wifi networks which is under the given subscription if applicable.
- * Otherwise, pass {@code null} when querying all wifi networks.
- * @param thresholdBytes Threshold in bytes to be notified on.
- * @param callback The {@link UsageCallback} that the system will call when data usage
- * has exceeded the specified threshold.
- * @param handler to dispatch callback events through, otherwise if {@code null} it uses
- * the calling thread.
- */
- public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
- UsageCallback callback, @Nullable Handler handler) {
- NetworkTemplate template = createTemplate(networkType, subscriberId);
- if (DBG) {
- Log.d(TAG, "registerUsageCallback called with: {"
- + " networkType=" + networkType
- + " subscriberId=" + subscriberId
- + " thresholdBytes=" + thresholdBytes
- + " }");
- }
-
- final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r);
-
- registerUsageCallback(template, thresholdBytes, executor, callback);
- }
-
- /**
- * Unregisters callbacks on data usage.
- *
- * @param callback The {@link UsageCallback} used when registering.
- */
- public void unregisterUsageCallback(UsageCallback callback) {
- if (callback == null || callback.request == null
- || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
- throw new IllegalArgumentException("Invalid UsageCallback");
- }
- try {
- mService.unregisterUsageRequest(callback.request);
- } catch (RemoteException e) {
- if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Base class for usage callbacks. Should be extended by applications wanting notifications.
- */
- public static abstract class UsageCallback {
- /**
- * Called when data usage has reached the given threshold.
- *
- * Called by {@code NetworkStatsService} when the registered threshold is reached.
- * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system
- * will not call {@link #onThresholdReached(int, String)}.
- *
- * @param template The {@link NetworkTemplate} that associated with this callback.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public void onThresholdReached(@NonNull NetworkTemplate template) {
- // Backward compatibility for those who didn't override this function.
- final int networkType = networkTypeForTemplate(template);
- if (networkType != ConnectivityManager.TYPE_NONE) {
- final String subscriberId = template.getSubscriberIds().isEmpty() ? null
- : template.getSubscriberIds().iterator().next();
- onThresholdReached(networkType, subscriberId);
- }
- }
-
- /**
- * Called when data usage has reached the given threshold.
- */
- public abstract void onThresholdReached(int networkType, String subscriberId);
-
- /**
- * @hide used for internal bookkeeping
- */
- private DataUsageRequest request;
-
- /**
- * Get network type from a template if feasible.
- *
- * @param template the target {@link NetworkTemplate}.
- * @return legacy network type, only supports for the types which is already supported in
- * {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}.
- * {@link ConnectivityManager#TYPE_NONE} for other types.
- */
- private static int networkTypeForTemplate(@NonNull NetworkTemplate template) {
- switch (template.getMatchRule()) {
- case NetworkTemplate.MATCH_MOBILE:
- return ConnectivityManager.TYPE_MOBILE;
- case NetworkTemplate.MATCH_WIFI:
- return ConnectivityManager.TYPE_WIFI;
- default:
- return ConnectivityManager.TYPE_NONE;
- }
- }
- }
-
- /**
- * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
- * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}.
- * Note that no de-duplication of statistics between providers is performed, so each provider
- * must only report network traffic that is not being reported by any other provider. Also note
- * that the provider cannot be re-registered after unregistering.
- *
- * @param tag a human readable identifier of the custom network stats provider. This is only
- * used for debugging.
- * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
- * registered to the system.
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- android.Manifest.permission.NETWORK_STATS_PROVIDER,
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
- @NonNull public void registerNetworkStatsProvider(
- @NonNull String tag,
- @NonNull NetworkStatsProvider provider) {
- try {
- if (provider.getProviderCallbackBinder() != null) {
- throw new IllegalArgumentException("provider is already registered");
- }
- final INetworkStatsProviderCallback cbBinder =
- mService.registerNetworkStatsProvider(tag, provider.getProviderBinder());
- provider.setProviderCallbackBinder(cbBinder);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Unregisters an instance of {@link NetworkStatsProvider}.
- *
- * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
- * unregistered to the system.
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- android.Manifest.permission.NETWORK_STATS_PROVIDER,
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
- @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
- try {
- provider.getProviderCallbackBinderOrThrow().unregister();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
- final NetworkTemplate template;
- switch (networkType) {
- case ConnectivityManager.TYPE_MOBILE:
- template = subscriberId == null
- ? NetworkTemplate.buildTemplateMobileWildcard()
- : NetworkTemplate.buildTemplateMobileAll(subscriberId);
- break;
- case ConnectivityManager.TYPE_WIFI:
- template = TextUtils.isEmpty(subscriberId)
- ? NetworkTemplate.buildTemplateWifiWildcard()
- : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL,
- subscriberId);
- break;
- default:
- throw new IllegalArgumentException("Cannot create template for network type "
- + networkType + ", subscriberId '"
- + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + "'.");
- }
- return template;
- }
-
- /**
- * Notify {@code NetworkStatsService} about network status changed.
- *
- * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
- *
- * To avoid races that attribute data usage to wrong network, such as new network with
- * the same interface after SIM hot-swap, this function will not return until
- * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
- * all data sources.
- *
- * @param defaultNetworks the list of all networks that could be used by network traffic that
- * does not explicitly select a network.
- * @param networkStateSnapshots a list of {@link NetworkStateSnapshot}s, one for
- * each network that is currently connected.
- * @param activeIface the active (i.e., connected) default network interface for the calling
- * uid. Used to determine on which network future calls to
- * {@link android.net.TrafficStats#incrementOperationCount} applies to.
- * @param underlyingNetworkInfos the list of underlying network information for all
- * currently-connected VPNs.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- public void notifyNetworkStatus(
- @NonNull List<Network> defaultNetworks,
- @NonNull List<NetworkStateSnapshot> networkStateSnapshots,
- @Nullable String activeIface,
- @NonNull List<UnderlyingNetworkInfo> underlyingNetworkInfos) {
- try {
- Objects.requireNonNull(defaultNetworks);
- Objects.requireNonNull(networkStateSnapshots);
- Objects.requireNonNull(underlyingNetworkInfos);
- mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]),
- networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface,
- underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0]));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- private static class UsageCallbackWrapper extends IUsageCallback.Stub {
- // Null if unregistered.
- private volatile UsageCallback mCallback;
-
- private final Executor mExecutor;
-
- UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) {
- mCallback = callback;
- mExecutor = executor;
- }
-
- @Override
- public void onThresholdReached(DataUsageRequest request) {
- // Copy it to a local variable in case mCallback changed inside the if condition.
- final UsageCallback callback = mCallback;
- if (callback != null) {
- mExecutor.execute(() -> callback.onThresholdReached(request.template));
- } else {
- Log.e(TAG, "onThresholdReached with released callback for " + request);
- }
- }
-
- @Override
- public void onCallbackReleased(DataUsageRequest request) {
- if (DBG) Log.d(TAG, "callback released for " + request);
- mCallback = null;
- }
- }
-
- /**
- * Mark given UID as being in foreground for stats purposes.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- public void noteUidForeground(int uid, boolean uidForeground) {
- try {
- mService.noteUidForeground(uid, uidForeground);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Set default value of global alert bytes, the value will be clamped to [128kB, 2MB].
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- Manifest.permission.NETWORK_STACK})
- public void setDefaultGlobalAlert(long alertBytes) {
- try {
- // TODO: Sync internal naming with the API surface.
- mService.advisePersistThreshold(alertBytes);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Force update of statistics.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- public void forceUpdate() {
- try {
- mService.forceUpdate();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Set the warning and limit to all registered custom network stats providers.
- * Note that invocation of any interface will be sent to all providers.
- *
- * Asynchronicity notes : because traffic may be happening on the device at the same time, it
- * doesn't make sense to wait for the warning and limit to be set – a caller still wouldn't
- * know when exactly it was effective. All that can matter is that it's done quickly. Also,
- * this method can't fail, so there is no status to return. All providers will see the new
- * values soon.
- * As such, this method returns immediately and sends the warning and limit to all providers
- * as soon as possible through a one-way binder call.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- public void setStatsProviderWarningAndLimitAsync(@NonNull String iface, long warning,
- long limit) {
- try {
- mService.setStatsProviderWarningAndLimitAsync(iface, warning, limit);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get a RAT type representative of a group of RAT types for network statistics.
- *
- * Collapse the given Radio Access Technology (RAT) type into a bucket that
- * is representative of the original RAT type for network statistics. The
- * mapping mostly corresponds to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}
- * but with adaptations specific to the virtual types introduced by
- * networks stats.
- *
- * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- 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 NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
- case NetworkStatsManager.NETWORK_TYPE_5G_NSA:
- return NetworkStatsManager.NETWORK_TYPE_5G_NSA;
- default:
- return TelephonyManager.NETWORK_TYPE_UNKNOWN;
- }
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
deleted file mode 100644
index 61b34d0..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.app.usage.NetworkStatsManager;
-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 NetworkStats, nsd,
- * ipsec and ethernet 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);
- }
- );
-
- SystemServiceRegistry.registerContextAwareService(
- Context.IPSEC_SERVICE,
- IpSecManager.class,
- (context, serviceBinder) -> {
- IIpSecService service = IIpSecService.Stub.asInterface(serviceBinder);
- return new IpSecManager(context, service);
- }
- );
-
- SystemServiceRegistry.registerContextAwareService(
- Context.NETWORK_STATS_SERVICE,
- NetworkStatsManager.class,
- (context, serviceBinder) -> {
- INetworkStatsService service =
- INetworkStatsService.Stub.asInterface(serviceBinder);
- return new NetworkStatsManager(context, service);
- }
- );
-
- SystemServiceRegistry.registerContextAwareService(
- Context.ETHERNET_SERVICE,
- EthernetManager.class,
- (context, serviceBinder) -> {
- IEthernetManager service = IEthernetManager.Stub.asInterface(serviceBinder);
- return new EthernetManager(context, service);
- }
- );
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl
deleted file mode 100644
index d1937c7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2016, 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 DataUsageRequest;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
deleted file mode 100644
index b06d515..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * Copyright (C) 2016 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.Nullable;
-import android.net.NetworkTemplate;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Defines a request to register a callbacks. Used to be notified on data usage via
- * {@link android.app.usage.NetworkStatsManager#registerDataUsageCallback}.
- * If no {@code uid}s are set, callbacks are restricted to device-owners,
- * carrier-privileged apps, or system apps.
- *
- * @hide
- */
-public final class DataUsageRequest implements Parcelable {
-
- public static final String PARCELABLE_KEY = "DataUsageRequest";
- public static final int REQUEST_ID_UNSET = 0;
-
- /**
- * Identifies the request. {@link DataUsageRequest}s should only be constructed by
- * the Framework and it is used internally to identify the request.
- */
- public final int requestId;
-
- /**
- * {@link NetworkTemplate} describing the network to monitor.
- */
- public final NetworkTemplate template;
-
- /**
- * Threshold in bytes to be notified on.
- */
- public final long thresholdInBytes;
-
- public DataUsageRequest(int requestId, NetworkTemplate template, long thresholdInBytes) {
- this.requestId = requestId;
- this.template = template;
- this.thresholdInBytes = thresholdInBytes;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(requestId);
- dest.writeParcelable(template, flags);
- dest.writeLong(thresholdInBytes);
- }
-
- public static final @android.annotation.NonNull Creator<DataUsageRequest> CREATOR =
- new Creator<DataUsageRequest>() {
- @Override
- public DataUsageRequest createFromParcel(Parcel in) {
- int requestId = in.readInt();
- NetworkTemplate template = in.readParcelable(null);
- long thresholdInBytes = in.readLong();
- DataUsageRequest result = new DataUsageRequest(requestId, template,
- thresholdInBytes);
- return result;
- }
-
- @Override
- public DataUsageRequest[] newArray(int size) {
- return new DataUsageRequest[size];
- }
- };
-
- @Override
- public String toString() {
- return "DataUsageRequest [ requestId=" + requestId
- + ", networkTemplate=" + template
- + ", thresholdInBytes=" + thresholdInBytes + " ]";
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (obj instanceof DataUsageRequest == false) return false;
- DataUsageRequest that = (DataUsageRequest) obj;
- return that.requestId == this.requestId
- && Objects.equals(that.template, this.template)
- && that.thresholdInBytes == this.thresholdInBytes;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(requestId, template, thresholdInBytes);
- }
-
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
deleted file mode 100644
index 793f28d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.RemoteException;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.modules.utils.BackgroundThread;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.function.BiConsumer;
-
-/**
- * A class that manages and configures Ethernet interfaces.
- *
- * @hide
- */
-@SystemApi
-@SystemService(Context.ETHERNET_SERVICE)
-public class EthernetManager {
- private static final String TAG = "EthernetManager";
-
- private final IEthernetManager mService;
- @GuardedBy("mListeners")
- private final ArrayList<ListenerInfo> mListeners = new ArrayList<>();
- private final IEthernetServiceListener.Stub mServiceListener =
- new IEthernetServiceListener.Stub() {
- @Override
- public void onInterfaceStateChanged(String iface, int state, int role,
- IpConfiguration configuration) {
- synchronized (mListeners) {
- for (ListenerInfo li : mListeners) {
- li.executor.execute(() ->
- li.listener.onInterfaceStateChanged(iface, state, role,
- configuration));
- }
- }
- }
- };
-
- private static class ListenerInfo {
- @NonNull
- public final Executor executor;
- @NonNull
- public final InterfaceStateListener listener;
-
- private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) {
- this.executor = executor;
- this.listener = listener;
- }
- }
-
- /**
- * The interface is absent.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int STATE_ABSENT = 0;
-
- /**
- * The interface is present but link is down.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int STATE_LINK_DOWN = 1;
-
- /**
- * The interface is present and link is up.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int STATE_LINK_UP = 2;
-
- /** @hide */
- @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
- @Retention(RetentionPolicy.SOURCE)
- public @interface InterfaceState {}
-
- /**
- * The interface currently does not have any specific role.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int ROLE_NONE = 0;
-
- /**
- * The interface is in client mode (e.g., connected to the Internet).
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int ROLE_CLIENT = 1;
-
- /**
- * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int ROLE_SERVER = 2;
-
- /** @hide */
- @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Role {}
-
- /**
- * A listener that receives notifications about the state of Ethernet interfaces on the system.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public interface InterfaceStateListener {
- /**
- * Called when an Ethernet interface changes state.
- *
- * @param iface the name of the interface.
- * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
- * interface was removed.
- * @param role whether the interface is in client mode or server mode.
- * @param configuration the current IP configuration of the interface.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
- @Role int role, @Nullable IpConfiguration configuration);
- }
-
- /**
- * A listener interface to receive notification on changes in Ethernet.
- * This has never been a supported API. Use {@link InterfaceStateListener} instead.
- * @hide
- */
- public interface Listener extends InterfaceStateListener {
- /**
- * Called when Ethernet port's availability is changed.
- * @param iface Ethernet interface name
- * @param isAvailable {@code true} if Ethernet port exists.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- void onAvailabilityChanged(String iface, boolean isAvailable);
-
- /** Default implementation for backwards compatibility. Only calls the legacy listener. */
- default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
- @Role int role, @Nullable IpConfiguration configuration) {
- onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
- }
-
- }
-
- /**
- * Create a new EthernetManager instance.
- * Applications will almost always want to use
- * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
- * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
- * @hide
- */
- public EthernetManager(Context context, IEthernetManager service) {
- mService = service;
- }
-
- /**
- * Get Ethernet configuration.
- * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public IpConfiguration getConfiguration(String iface) {
- try {
- return mService.getConfiguration(iface);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Set Ethernet configuration.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
- try {
- mService.setConfiguration(iface, config);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Indicates whether the system currently has one or more Ethernet interfaces.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean isAvailable() {
- return getAvailableInterfaces().length > 0;
- }
-
- /**
- * Indicates whether the system has given interface.
- *
- * @param iface Ethernet interface name
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean isAvailable(String iface) {
- try {
- return mService.isAvailable(iface);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Adds a listener.
- * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
- *
- * @param listener A {@link Listener} to add.
- * @throws IllegalArgumentException If the listener is null.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void addListener(@NonNull Listener listener) {
- addListener(listener, BackgroundThread.getExecutor());
- }
-
- /**
- * Adds a listener.
- * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
- *
- * @param listener A {@link Listener} to add.
- * @param executor Executor to run callbacks on.
- * @throws IllegalArgumentException If the listener or executor is null.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
- addInterfaceStateListener(executor, listener);
- }
-
- /**
- * Listen to changes in the state of Ethernet interfaces.
- *
- * Adds a listener to receive notification for any state change of all existing Ethernet
- * interfaces.
- * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
- * existing interfaces upon adding a listener. The same method will be called on the
- * listener every time any of the interface changes state. In particular, if an
- * interface is removed, it will be called with state {@link #STATE_ABSENT}.
- * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
- *
- * @param executor Executor to run callbacks on.
- * @param listener A {@link Listener} to add.
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
- @SystemApi(client = MODULE_LIBRARIES)
- public void addInterfaceStateListener(@NonNull Executor executor,
- @NonNull InterfaceStateListener listener) {
- if (listener == null || executor == null) {
- throw new NullPointerException("listener and executor must not be null");
- }
- synchronized (mListeners) {
- mListeners.add(new ListenerInfo(executor, listener));
- if (mListeners.size() == 1) {
- try {
- mService.addListener(mServiceListener);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- }
-
- /**
- * Returns an array of available Ethernet interface names.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public String[] getAvailableInterfaces() {
- try {
- return mService.getAvailableInterfaces();
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Removes a listener.
- *
- * @param listener A {@link Listener} to remove.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
- Objects.requireNonNull(listener);
- synchronized (mListeners) {
- mListeners.removeIf(l -> l.listener == listener);
- if (mListeners.isEmpty()) {
- try {
- mService.removeListener(mServiceListener);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- }
-
- /**
- * Removes a listener.
- * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
- * @param listener A {@link Listener} to remove.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void removeListener(@NonNull Listener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
- removeInterfaceStateListener(listener);
- }
-
- /**
- * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
- * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
- * already present on the system.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public void setIncludeTestInterfaces(boolean include) {
- try {
- mService.setIncludeTestInterfaces(include);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * A request for a tethered interface.
- */
- public static class TetheredInterfaceRequest {
- private final IEthernetManager mService;
- private final ITetheredInterfaceCallback mCb;
-
- private TetheredInterfaceRequest(@NonNull IEthernetManager service,
- @NonNull ITetheredInterfaceCallback cb) {
- this.mService = service;
- this.mCb = cb;
- }
-
- /**
- * Release the request, causing the interface to revert back from tethering mode if there
- * is no other requestor.
- */
- public void release() {
- try {
- mService.releaseTetheredInterface(mCb);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
- */
- public interface TetheredInterfaceCallback {
- /**
- * Called when the tethered interface is available.
- * @param iface The name of the interface.
- */
- void onAvailable(@NonNull String iface);
-
- /**
- * Called when the tethered interface is now unavailable.
- */
- void onUnavailable();
- }
-
- /**
- * Request a tethered interface in tethering mode.
- *
- * <p>When this method is called and there is at least one ethernet interface available, the
- * system will designate one to act as a tethered interface. If there is already a tethered
- * interface, the existing interface will be used.
- * @param callback A callback to be called once the request has been fulfilled.
- */
- @RequiresPermission(anyOf = {
- android.Manifest.permission.NETWORK_STACK,
- android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
- })
- @NonNull
- public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
- @NonNull final TetheredInterfaceCallback callback) {
- Objects.requireNonNull(callback, "Callback must be non-null");
- Objects.requireNonNull(executor, "Executor must be non-null");
- final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
- @Override
- public void onAvailable(String iface) {
- executor.execute(() -> callback.onAvailable(iface));
- }
-
- @Override
- public void onUnavailable() {
- executor.execute(() -> callback.onUnavailable());
- }
- };
-
- try {
- mService.requestTetheredInterface(cbInternal);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- return new TetheredInterfaceRequest(mService, cbInternal);
- }
-
- private static final class InternalNetworkManagementListener
- extends IEthernetNetworkManagementListener.Stub {
- @NonNull
- private final Executor mExecutor;
- @NonNull
- private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
-
- InternalNetworkManagementListener(
- @NonNull final Executor executor,
- @NonNull final BiConsumer<Network, EthernetNetworkManagementException> 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 EthernetNetworkManagementException e) {
- mExecutor.execute(() -> mListener.accept(network, e));
- }
- }
-
- private InternalNetworkManagementListener getInternalNetworkManagementListener(
- @Nullable final Executor executor,
- @Nullable final BiConsumer<Network, EthernetNetworkManagementException> 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;
- }
-
- /**
- * Updates the configuration of an automotive device's ethernet network.
- *
- * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
- * configuration for this network.
- * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
- * this network to put inside the {@code request}.
- * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
- * object for this network to put inside the {@code request}.
- *
- * If non-null, the listener will be called exactly once after this is called, unless
- * a synchronous exception was thrown.
- *
- * @param iface the name of the interface to act upon.
- * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
- * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
- * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
- * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
- * @throws SecurityException if the process doesn't hold
- * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
- * @throws UnsupportedOperationException if called on a non-automotive device or on an
- * unsupported interface.
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK,
- android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
- public void updateConfiguration(
- @NonNull String iface,
- @NonNull EthernetNetworkUpdateRequest request,
- @Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
- Objects.requireNonNull(iface, "iface must be non-null");
- Objects.requireNonNull(request, "request must be non-null");
- final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
- executor, listener);
- try {
- mService.updateConfiguration(iface, request, proxy);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Set an ethernet network's link state up.
- *
- * When the link is successfully turned up, the listener will be called with the resulting
- * network. If any error or unexpected condition happens while the system tries to turn the
- * interface up, the listener will be called with an appropriate exception.
- * The listener is guaranteed to be called exactly once for each call to this method, but this
- * may take an unbounded amount of time depending on the actual network conditions.
- *
- * @param iface the name of the interface to act upon.
- * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
- * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
- * @throws SecurityException if the process doesn't hold
- * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
- * @throws UnsupportedOperationException if called on a non-automotive device.
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK,
- android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
- @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
- public void connectNetwork(
- @NonNull String iface,
- @Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
- Objects.requireNonNull(iface, "iface must be non-null");
- final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
- executor, listener);
- try {
- mService.connectNetwork(iface, proxy);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Set an ethernet network's link state down.
- *
- * When the link is successfully turned down, the listener will be called with the network that
- * was torn down, if any. If any error or unexpected condition happens while the system tries to
- * turn the interface down, the listener will be called with an appropriate exception.
- * The listener is guaranteed to be called exactly once for each call to this method.
- *
- * @param iface the name of the interface to act upon.
- * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
- * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
- * @throws SecurityException if the process doesn't hold
- * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
- * @throws UnsupportedOperationException if called on a non-automotive device.
- * @hide
- */
- @SystemApi
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK,
- android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
- @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
- public void disconnectNetwork(
- @NonNull String iface,
- @Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
- Objects.requireNonNull(iface, "iface must be non-null");
- final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
- executor, listener);
- try {
- mService.disconnectNetwork(iface, proxy);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
deleted file mode 100644
index adf9e5a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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 EthernetNetworkManagementException;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
deleted file mode 100644
index a69cc55..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/** @hide */
-@SystemApi
-public final class EthernetNetworkManagementException
- extends RuntimeException implements Parcelable {
-
- /* @hide */
- public EthernetNetworkManagementException(@NonNull final String errorMessage) {
- super(errorMessage);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getMessage());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null || getClass() != obj.getClass()) return false;
- final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj;
-
- return Objects.equals(getMessage(), that.getMessage());
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(getMessage());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR =
- new Parcelable.Creator<EthernetNetworkManagementException>() {
- @Override
- public EthernetNetworkManagementException[] newArray(int size) {
- return new EthernetNetworkManagementException[size];
- }
-
- @Override
- public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) {
- return new EthernetNetworkManagementException(source.readString());
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
deleted file mode 100644
index e4d6e24..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 android.text.TextUtils;
-
-import java.util.Objects;
-
-/**
- * A {@link NetworkSpecifier} used to identify ethernet interfaces.
- *
- * @see EthernetManager
- */
-public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable {
-
- /**
- * Name of the network interface.
- */
- @NonNull
- private final String mInterfaceName;
-
- /**
- * Create a new EthernetNetworkSpecifier.
- * @param interfaceName Name of the ethernet interface the specifier refers to.
- */
- public EthernetNetworkSpecifier(@NonNull String interfaceName) {
- if (TextUtils.isEmpty(interfaceName)) {
- throw new IllegalArgumentException();
- }
- mInterfaceName = interfaceName;
- }
-
- /**
- * Get the name of the ethernet interface the specifier refers to.
- */
- @Nullable
- public String getInterfaceName() {
- // This may be null in the future to support specifiers based on data other than the
- // interface name.
- return mInterfaceName;
- }
-
- /** @hide */
- @Override
- public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
- return equals(other);
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (!(o instanceof EthernetNetworkSpecifier)) return false;
- return TextUtils.equals(mInterfaceName, ((EthernetNetworkSpecifier) o).mInterfaceName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(mInterfaceName);
- }
-
- @Override
- public String toString() {
- return "EthernetNetworkSpecifier (" + mInterfaceName + ")";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mInterfaceName);
- }
-
- public static final @NonNull Parcelable.Creator<EthernetNetworkSpecifier> CREATOR =
- new Parcelable.Creator<EthernetNetworkSpecifier>() {
- public EthernetNetworkSpecifier createFromParcel(Parcel in) {
- return new EthernetNetworkSpecifier(in.readString());
- }
- public EthernetNetworkSpecifier[] newArray(int size) {
- return new EthernetNetworkSpecifier[size];
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
deleted file mode 100644
index 1691942..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Represents a request to update an existing Ethernet interface.
- *
- * @see EthernetManager#updateConfiguration
- *
- * @hide
- */
-@SystemApi
-public final class EthernetNetworkUpdateRequest implements Parcelable {
- @Nullable
- private final IpConfiguration mIpConfig;
- @Nullable
- private final NetworkCapabilities mNetworkCapabilities;
-
- /**
- * Setting the {@link IpConfiguration} is optional in {@link EthernetNetworkUpdateRequest}.
- * When set to null, the existing IpConfiguration is not updated.
- *
- * @return the new {@link IpConfiguration} or null.
- */
- @Nullable
- public IpConfiguration getIpConfiguration() {
- return mIpConfig == null ? null : new IpConfiguration(mIpConfig);
- }
-
- /**
- * Setting the {@link NetworkCapabilities} is optional in {@link EthernetNetworkUpdateRequest}.
- * When set to null, the existing NetworkCapabilities are not updated.
- *
- * @return the new {@link NetworkCapabilities} or null.
- */
- @Nullable
- public NetworkCapabilities getNetworkCapabilities() {
- return mNetworkCapabilities == null ? null : new NetworkCapabilities(mNetworkCapabilities);
- }
-
- private EthernetNetworkUpdateRequest(@Nullable final IpConfiguration ipConfig,
- @Nullable final NetworkCapabilities networkCapabilities) {
- mIpConfig = ipConfig;
- mNetworkCapabilities = networkCapabilities;
- }
-
- private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
- Objects.requireNonNull(source);
- mIpConfig = source.readParcelable(IpConfiguration.class.getClassLoader(),
- IpConfiguration.class);
- mNetworkCapabilities = source.readParcelable(NetworkCapabilities.class.getClassLoader(),
- NetworkCapabilities.class);
- }
-
- /**
- * Builder used to create {@link EthernetNetworkUpdateRequest} objects.
- */
- public static final class Builder {
- @Nullable
- private IpConfiguration mBuilderIpConfig;
- @Nullable
- private NetworkCapabilities mBuilderNetworkCapabilities;
-
- public Builder(){}
-
- /**
- * Constructor to populate the builder's values with an already built
- * {@link EthernetNetworkUpdateRequest}.
- * @param request the {@link EthernetNetworkUpdateRequest} to populate with.
- */
- public Builder(@NonNull final EthernetNetworkUpdateRequest request) {
- Objects.requireNonNull(request);
- mBuilderIpConfig = null == request.mIpConfig
- ? null : new IpConfiguration(request.mIpConfig);
- mBuilderNetworkCapabilities = null == request.mNetworkCapabilities
- ? null : new NetworkCapabilities(request.mNetworkCapabilities);
- }
-
- /**
- * Set the {@link IpConfiguration} to be used with the {@code Builder}.
- * @param ipConfig the {@link IpConfiguration} to set.
- * @return The builder to facilitate chaining.
- */
- @NonNull
- public Builder setIpConfiguration(@Nullable final IpConfiguration ipConfig) {
- mBuilderIpConfig = ipConfig == null ? null : new IpConfiguration(ipConfig);
- return this;
- }
-
- /**
- * Set the {@link NetworkCapabilities} to be used with the {@code Builder}.
- * @param nc the {@link NetworkCapabilities} to set.
- * @return The builder to facilitate chaining.
- */
- @NonNull
- public Builder setNetworkCapabilities(@Nullable final NetworkCapabilities nc) {
- mBuilderNetworkCapabilities = nc == null ? null : new NetworkCapabilities(nc);
- return this;
- }
-
- /**
- * Build {@link EthernetNetworkUpdateRequest} return the current update request.
- *
- * @throws IllegalStateException when both mBuilderNetworkCapabilities and mBuilderIpConfig
- * are null.
- */
- @NonNull
- public EthernetNetworkUpdateRequest build() {
- if (mBuilderIpConfig == null && mBuilderNetworkCapabilities == null) {
- throw new IllegalStateException(
- "Cannot construct an empty EthernetNetworkUpdateRequest");
- }
- return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities);
- }
- }
-
- @Override
- public String toString() {
- return "EthernetNetworkUpdateRequest{"
- + "mIpConfig=" + mIpConfig
- + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
-
- return Objects.equals(that.getIpConfiguration(), mIpConfig)
- && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mIpConfig, mNetworkCapabilities);
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mIpConfig, flags);
- dest.writeParcelable(mNetworkCapabilities, flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR =
- new Parcelable.Creator<EthernetNetworkUpdateRequest>() {
- @Override
- public EthernetNetworkUpdateRequest[] newArray(int size) {
- return new EthernetNetworkUpdateRequest[size];
- }
-
- @Override
- public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
- return new EthernetNetworkUpdateRequest(source);
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
deleted file mode 100644
index 544d02b..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2014 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.net.IpConfiguration;
-import android.net.IEthernetServiceListener;
-import android.net.IEthernetNetworkManagementListener;
-import android.net.EthernetNetworkUpdateRequest;
-import android.net.ITetheredInterfaceCallback;
-
-/**
- * Interface that answers queries about, and allows changing
- * ethernet configuration.
- */
-/** {@hide} */
-interface IEthernetManager
-{
- String[] getAvailableInterfaces();
- IpConfiguration getConfiguration(String iface);
- void setConfiguration(String iface, in IpConfiguration config);
- boolean isAvailable(String iface);
- void addListener(in IEthernetServiceListener listener);
- void removeListener(in IEthernetServiceListener listener);
- void setIncludeTestInterfaces(boolean include);
- void requestTetheredInterface(in ITetheredInterfaceCallback callback);
- void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
- void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
- in IEthernetNetworkManagementListener listener);
- void connectNetwork(String iface, in IEthernetNetworkManagementListener listener);
- void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
deleted file mode 100644
index 93edccf..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * 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.net.EthernetNetworkManagementException;
-import android.net.Network;
-
-/** @hide */
-oneway interface IEthernetNetworkManagementListener {
- void onComplete(in Network network, in EthernetNetworkManagementException exception);
-}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
deleted file mode 100644
index 6d2ba03..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2014 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.net.IpConfiguration;
-
-/** @hide */
-oneway interface IEthernetServiceListener
-{
- void onInterfaceStateChanged(String iface, int state, int role,
- in IpConfiguration configuration);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl b/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl
deleted file mode 100644
index 933256a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-** Copyright 2017, 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.net.LinkAddress;
-import android.net.Network;
-import android.net.IpSecConfig;
-import android.net.IpSecUdpEncapResponse;
-import android.net.IpSecSpiResponse;
-import android.net.IpSecTransformResponse;
-import android.net.IpSecTunnelInterfaceResponse;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-
-/**
- * @hide
- */
-interface IIpSecService
-{
- IpSecSpiResponse allocateSecurityParameterIndex(
- in String destinationAddress, int requestedSpi, in IBinder binder);
-
- void releaseSecurityParameterIndex(int resourceId);
-
- IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, in IBinder binder);
-
- void closeUdpEncapsulationSocket(int resourceId);
-
- IpSecTunnelInterfaceResponse createTunnelInterface(
- in String localAddr,
- in String remoteAddr,
- in Network underlyingNetwork,
- in IBinder binder,
- in String callingPackage);
-
- void addAddressToTunnelInterface(
- int tunnelResourceId,
- in LinkAddress localAddr,
- in String callingPackage);
-
- void removeAddressFromTunnelInterface(
- int tunnelResourceId,
- in LinkAddress localAddr,
- in String callingPackage);
-
- void setNetworkForTunnelInterface(
- int tunnelResourceId, in Network underlyingNetwork, in String callingPackage);
-
- void deleteTunnelInterface(int resourceId, in String callingPackage);
-
- IpSecTransformResponse createTransform(
- in IpSecConfig c, in IBinder binder, in String callingPackage);
-
- void deleteTransform(int transformId);
-
- void applyTransportModeTransform(
- in ParcelFileDescriptor socket, int direction, int transformId);
-
- void applyTunnelModeTransform(
- int tunnelResourceId, int direction, int transformResourceId, in String callingPackage);
-
- void removeTransportModeTransforms(in ParcelFileDescriptor socket);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
deleted file mode 100644
index c86f7fd..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
+++ /dev/null
@@ -1,104 +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 android.net.DataUsageRequest;
-import android.net.INetworkStatsSession;
-import android.net.Network;
-import android.net.NetworkStateSnapshot;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.UnderlyingNetworkInfo;
-import android.net.netstats.IUsageCallback;
-import android.net.netstats.provider.INetworkStatsProvider;
-import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.os.IBinder;
-import android.os.Messenger;
-
-/** {@hide} */
-interface INetworkStatsService {
-
- /** Start a statistics query session. */
- @UnsupportedAppUsage
- INetworkStatsSession openSession();
-
- /** Start a statistics query session. If calling package is profile or device owner then it is
- * granted automatic access if apiLevel is NetworkStatsManager.API_LEVEL_DPC_ALLOWED. If
- * apiLevel is at least NetworkStatsManager.API_LEVEL_REQUIRES_PACKAGE_USAGE_STATS then
- * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted
- * READ_NETWORK_USAGE_STATS is checked for.
- */
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage);
-
- /** Return data layer snapshot of UID network usage. */
- @UnsupportedAppUsage
- NetworkStats getDataLayerSnapshotForUid(int uid);
-
- /** Get the transport NetworkStats for all UIDs since boot. */
- NetworkStats getUidStatsForTransport(int transport);
-
- /** Return set of any ifaces associated with mobile networks since boot. */
- @UnsupportedAppUsage
- String[] getMobileIfaces();
-
- /** Increment data layer count of operations performed for UID and tag. */
- void incrementOperationCount(int uid, int tag, int operationCount);
-
- /** Notify {@code NetworkStatsService} about network status changed. */
- void notifyNetworkStatus(
- in Network[] defaultNetworks,
- in NetworkStateSnapshot[] snapshots,
- in String activeIface,
- in UnderlyingNetworkInfo[] underlyingNetworkInfos);
- /** Force update of statistics. */
- @UnsupportedAppUsage
- void forceUpdate();
-
- /** Registers a callback on data usage. */
- DataUsageRequest registerUsageCallback(String callingPackage,
- in DataUsageRequest request, in IUsageCallback callback);
-
- /** Unregisters a callback on data usage. */
- void unregisterUsageRequest(in DataUsageRequest request);
-
- /** Get the uid stats information since boot */
- long getUidStats(int uid, int type);
-
- /** Get the iface stats information since boot */
- long getIfaceStats(String iface, int type);
-
- /** Get the total network stats information since boot */
- long getTotalStats(int type);
-
- /** Registers a network stats provider */
- INetworkStatsProviderCallback registerNetworkStatsProvider(String tag,
- in INetworkStatsProvider provider);
-
- /** Mark given UID as being in foreground for stats purposes. */
- void noteUidForeground(int uid, boolean uidForeground);
-
- /** Advise persistence threshold; may be overridden internally. */
- void advisePersistThreshold(long thresholdBytes);
-
- /**
- * Set the warning and limit to all registered custom network stats providers.
- * Note that invocation of any interface will be sent to all providers.
- */
- void setStatsProviderWarningAndLimitAsync(String iface, long warning, long limit);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
deleted file mode 100644
index ab70be8..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 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.net.NetworkStats;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-
-/** {@hide} */
-interface INetworkStatsSession {
-
- /** Return device aggregated network layer usage summary for traffic that matches template. */
- NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end);
-
- /** Return network layer usage summary for traffic that matches template. */
- @UnsupportedAppUsage
- NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
- /** Return historical network layer stats for traffic that matches template. */
- @UnsupportedAppUsage
- NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
- /**
- * Return historical network layer stats for traffic that matches template, start and end
- * timestamp.
- */
- NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end);
-
- /**
- * 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 network layer usage summary per UID for tagged traffic that matches template. */
- NetworkStats getTaggedSummaryForAllUid(in NetworkTemplate template, long start, long end);
-
- /** Return historical network layer stats for specific UID traffic that matches template. */
- @UnsupportedAppUsage
- NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
- /** Return historical network layer stats for specific UID traffic that matches template. */
- NetworkStatsHistory getHistoryIntervalForUid(in NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end);
-
- /** Return array of uids that have stats and are accessible to the calling user */
- int[] getRelevantUids();
-
- @UnsupportedAppUsage
- void close();
-
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
deleted file mode 100644
index 14aa023..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-/** @hide */
-oneway interface ITetheredInterfaceCallback {
- void onAvailable(in String iface);
- void onUnavailable();
-}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
deleted file mode 100644
index 10a22ac..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2017 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.StringDef;
-import android.content.res.Resources;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * This class represents a single algorithm that can be used by an {@link IpSecTransform}.
- *
- * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
- * Internet Protocol</a>
- */
-public final class IpSecAlgorithm implements Parcelable {
- private static final String TAG = "IpSecAlgorithm";
-
- /**
- * Null cipher.
- *
- * @hide
- */
- public static final String CRYPT_NULL = "ecb(cipher_null)";
-
- /**
- * AES-CBC Encryption/Ciphering Algorithm.
- *
- * <p>Valid lengths for this key are {128, 192, 256}.
- */
- public static final String CRYPT_AES_CBC = "cbc(aes)";
-
- /**
- * AES-CTR Encryption/Ciphering Algorithm.
- *
- * <p>Valid lengths for keying material are {160, 224, 288}.
- *
- * <p>As per <a href="https://tools.ietf.org/html/rfc3686#section-5.1">RFC3686 (Section
- * 5.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
- * nonce. RFC compliance requires that the nonce must be unique per security association.
- *
- * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
- * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
- * included in the returned algorithm set. The returned algorithm set will not change unless the
- * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
- * requested on an unsupported device.
- *
- * <p>@see {@link #getSupportedAlgorithms()}
- */
- // This algorithm may be available on devices released before Android 12, and is guaranteed
- // to be available on devices first shipped with Android 12 or later.
- public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
-
- /**
- * MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
- * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
- *
- * <p>Keys for this algorithm must be 128 bits in length.
- *
- * <p>Valid truncation lengths are multiples of 8 bits from 96 to 128.
- */
- public static final String AUTH_HMAC_MD5 = "hmac(md5)";
-
- /**
- * SHA1 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
- * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
- *
- * <p>Keys for this algorithm must be 160 bits in length.
- *
- * <p>Valid truncation lengths are multiples of 8 bits from 96 to 160.
- */
- public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
-
- /**
- * SHA256 HMAC Authentication/Integrity Algorithm.
- *
- * <p>Keys for this algorithm must be 256 bits in length.
- *
- * <p>Valid truncation lengths are multiples of 8 bits from 96 to 256.
- */
- public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
-
- /**
- * SHA384 HMAC Authentication/Integrity Algorithm.
- *
- * <p>Keys for this algorithm must be 384 bits in length.
- *
- * <p>Valid truncation lengths are multiples of 8 bits from 192 to 384.
- */
- public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
-
- /**
- * SHA512 HMAC Authentication/Integrity Algorithm.
- *
- * <p>Keys for this algorithm must be 512 bits in length.
- *
- * <p>Valid truncation lengths are multiples of 8 bits from 256 to 512.
- */
- public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
-
- /**
- * AES-XCBC Authentication/Integrity Algorithm.
- *
- * <p>Keys for this algorithm must be 128 bits in length.
- *
- * <p>The only valid truncation length is 96 bits.
- *
- * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
- * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
- * included in the returned algorithm set. The returned algorithm set will not change unless the
- * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
- * requested on an unsupported device.
- *
- * <p>@see {@link #getSupportedAlgorithms()}
- */
- // This algorithm may be available on devices released before Android 12, and is guaranteed
- // to be available on devices first shipped with Android 12 or later.
- public static final String AUTH_AES_XCBC = "xcbc(aes)";
-
- /**
- * AES-CMAC Authentication/Integrity Algorithm.
- *
- * <p>Keys for this algorithm must be 128 bits in length.
- *
- * <p>The only valid truncation length is 96 bits.
- *
- * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
- * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
- * included in the returned algorithm set. The returned algorithm set will not change unless the
- * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
- * requested on an unsupported device.
- *
- * <p>@see {@link #getSupportedAlgorithms()}
- */
- // This algorithm may be available on devices released before Android 12, and is guaranteed
- // to be available on devices first shipped with Android 12 or later.
- public static final String AUTH_AES_CMAC = "cmac(aes)";
-
- /**
- * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
- *
- * <p>Valid lengths for keying material are {160, 224, 288}.
- *
- * <p>As per <a href="https://tools.ietf.org/html/rfc4106#section-8.1">RFC4106 (Section
- * 8.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
- * salt. RFC compliance requires that the salt must be unique per invocation with the same key.
- *
- * <p>Valid ICV (truncation) lengths are {64, 96, 128}.
- */
- public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
-
- /**
- * ChaCha20-Poly1305 Authentication/Integrity + Encryption/Ciphering Algorithm.
- *
- * <p>Keys for this algorithm must be 288 bits in length.
- *
- * <p>As per <a href="https://tools.ietf.org/html/rfc7634#section-2">RFC7634 (Section 2)</a>,
- * keying material consists of a 256 bit key followed by a 32-bit salt. The salt is fixed per
- * security association.
- *
- * <p>The only valid ICV (truncation) length is 128 bits.
- *
- * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
- * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
- * included in the returned algorithm set. The returned algorithm set will not change unless the
- * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
- * requested on an unsupported device.
- *
- * <p>@see {@link #getSupportedAlgorithms()}
- */
- // This algorithm may be available on devices released before Android 12, and is guaranteed
- // to be available on devices first shipped with Android 12 or later.
- public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
-
- /** @hide */
- @StringDef({
- CRYPT_AES_CBC,
- CRYPT_AES_CTR,
- AUTH_HMAC_MD5,
- AUTH_HMAC_SHA1,
- AUTH_HMAC_SHA256,
- AUTH_HMAC_SHA384,
- AUTH_HMAC_SHA512,
- AUTH_AES_XCBC,
- AUTH_AES_CMAC,
- AUTH_CRYPT_AES_GCM,
- AUTH_CRYPT_CHACHA20_POLY1305
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface AlgorithmName {}
-
- /** @hide */
- @VisibleForTesting
- public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
-
- private static final int SDK_VERSION_ZERO = 0;
-
- static {
- ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, SDK_VERSION_ZERO);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, SDK_VERSION_ZERO);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, SDK_VERSION_ZERO);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, SDK_VERSION_ZERO);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, SDK_VERSION_ZERO);
- 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);
-
- 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 =
- Collections.unmodifiableSet(loadAlgos(Resources.getSystem()));
-
- private final String mName;
- private final byte[] mKey;
- private final int mTruncLenBits;
-
- /**
- * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
- * defined as constants in this class.
- *
- * <p>For algorithms that produce an integrity check value, the truncation length is a required
- * parameter. See {@link #IpSecAlgorithm(String algorithm, byte[] key, int truncLenBits)}
- *
- * @param algorithm name of the algorithm.
- * @param key key padded to a multiple of 8 bits.
- * @throws IllegalArgumentException if algorithm or key length is invalid.
- */
- public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
- this(algorithm, key, 0);
- }
-
- /**
- * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
- * defined as constants in this class.
- *
- * <p>This constructor only supports algorithms that use a truncation length. i.e.
- * Authentication and Authenticated Encryption algorithms.
- *
- * @param algorithm name of the algorithm.
- * @param key key padded to a multiple of 8 bits.
- * @param truncLenBits number of bits of output hash to use.
- * @throws IllegalArgumentException if algorithm, key length or truncation length is invalid.
- */
- public IpSecAlgorithm(
- @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
- mName = algorithm;
- mKey = key.clone();
- mTruncLenBits = truncLenBits;
- checkValidOrThrow(mName, mKey.length * 8, mTruncLenBits);
- }
-
- /** Get the algorithm name */
- @NonNull
- public String getName() {
- return mName;
- }
-
- /** Get the key for this algorithm */
- @NonNull
- public byte[] getKey() {
- return mKey.clone();
- }
-
- /** Get the truncation length of this algorithm, in bits */
- public int getTruncationLengthBits() {
- return mTruncLenBits;
- }
-
- /** Parcelable Implementation */
- public int describeContents() {
- return 0;
- }
-
- /** Write to parcel */
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mName);
- out.writeByteArray(mKey);
- out.writeInt(mTruncLenBits);
- }
-
- /** Parcelable Creator */
- public static final @android.annotation.NonNull Parcelable.Creator<IpSecAlgorithm> CREATOR =
- new Parcelable.Creator<IpSecAlgorithm>() {
- public IpSecAlgorithm createFromParcel(Parcel in) {
- final String name = in.readString();
- final byte[] key = in.createByteArray();
- final int truncLenBits = in.readInt();
-
- return new IpSecAlgorithm(name, key, truncLenBits);
- }
-
- public IpSecAlgorithm[] newArray(int size) {
- return new IpSecAlgorithm[size];
- }
- };
-
- /**
- * Returns supported IPsec algorithms for the current device.
- *
- * <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
- * supported before using it.
- */
- @NonNull
- public static Set<String> getSupportedAlgorithms() {
- return ENABLED_ALGOS;
- }
-
- /** @hide */
- @VisibleForTesting
- public static Set<String> loadAlgos(Resources systemResources) {
- final Set<String> enabledAlgos = new HashSet<>();
-
- // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
- // the resource are not allowed.
- final String[] resourceAlgos = systemResources.getStringArray(
- android.R.array.config_optionalIpSecAlgorithms);
- for (String str : resourceAlgos) {
- if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
- // This error should be caught by CTS and never be thrown to API callers
- throw new IllegalArgumentException("Invalid or repeated algorithm " + str);
- }
- }
-
- for (Entry<String, Integer> entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) {
- if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= entry.getValue()) {
- enabledAlgos.add(entry.getKey());
- }
- }
-
- return enabledAlgos;
- }
-
- private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
- final boolean isValidLen;
- final boolean isValidTruncLen;
-
- if (!getSupportedAlgorithms().contains(name)) {
- throw new IllegalArgumentException("Unsupported algorithm: " + name);
- }
-
- switch (name) {
- case CRYPT_AES_CBC:
- isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
- isValidTruncLen = true;
- break;
- case CRYPT_AES_CTR:
- // The keying material for AES-CTR is a key plus a 32-bit salt
- isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
- isValidTruncLen = true;
- break;
- case AUTH_HMAC_MD5:
- isValidLen = keyLen == 128;
- isValidTruncLen = truncLen >= 96 && truncLen <= 128;
- break;
- case AUTH_HMAC_SHA1:
- isValidLen = keyLen == 160;
- isValidTruncLen = truncLen >= 96 && truncLen <= 160;
- break;
- case AUTH_HMAC_SHA256:
- isValidLen = keyLen == 256;
- isValidTruncLen = truncLen >= 96 && truncLen <= 256;
- break;
- case AUTH_HMAC_SHA384:
- isValidLen = keyLen == 384;
- isValidTruncLen = truncLen >= 192 && truncLen <= 384;
- break;
- case AUTH_HMAC_SHA512:
- isValidLen = keyLen == 512;
- isValidTruncLen = truncLen >= 256 && truncLen <= 512;
- break;
- case AUTH_AES_XCBC:
- isValidLen = keyLen == 128;
- isValidTruncLen = truncLen == 96;
- break;
- case AUTH_AES_CMAC:
- isValidLen = keyLen == 128;
- isValidTruncLen = truncLen == 96;
- break;
- case AUTH_CRYPT_AES_GCM:
- // The keying material for GCM is a key plus a 32-bit salt
- isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
- isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
- break;
- case AUTH_CRYPT_CHACHA20_POLY1305:
- // The keying material for ChaCha20Poly1305 is a key plus a 32-bit salt
- isValidLen = keyLen == 256 + 32;
- isValidTruncLen = truncLen == 128;
- break;
- default:
- // Should never hit here.
- throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
- }
-
- if (!isValidLen) {
- throw new IllegalArgumentException("Invalid key material keyLength: " + keyLen);
- }
- if (!isValidTruncLen) {
- throw new IllegalArgumentException("Invalid truncation keyLength: " + truncLen);
- }
- }
-
- /** @hide */
- public boolean isAuthentication() {
- switch (getName()) {
- // Fallthrough
- case AUTH_HMAC_MD5:
- case AUTH_HMAC_SHA1:
- case AUTH_HMAC_SHA256:
- case AUTH_HMAC_SHA384:
- case AUTH_HMAC_SHA512:
- case AUTH_AES_XCBC:
- case AUTH_AES_CMAC:
- return true;
- default:
- return false;
- }
- }
-
- /** @hide */
- public boolean isEncryption() {
- switch (getName()) {
- case CRYPT_AES_CBC: // fallthrough
- case CRYPT_AES_CTR:
- return true;
- default:
- return false;
- }
- }
-
- /** @hide */
- public boolean isAead() {
- switch (getName()) {
- case AUTH_CRYPT_AES_GCM: // fallthrough
- case AUTH_CRYPT_CHACHA20_POLY1305:
- return true;
- default:
- return false;
- }
- }
-
- @Override
- @NonNull
- public String toString() {
- return new StringBuilder()
- .append("{mName=")
- .append(mName)
- .append(", mTruncLenBits=")
- .append(mTruncLenBits)
- .append("}")
- .toString();
- }
-
- /** @hide */
- @VisibleForTesting
- public static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
- if (lhs == null || rhs == null) return (lhs == rhs);
- return (lhs.mName.equals(rhs.mName)
- && Arrays.equals(lhs.mKey, rhs.mKey)
- && lhs.mTruncLenBits == rhs.mTruncLenBits);
- }
-};
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl
deleted file mode 100644
index eaefca7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/** @hide */
-parcelable IpSecConfig;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
deleted file mode 100644
index 575c5ed..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2017 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.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * This class encapsulates all the configuration parameters needed to create IPsec transforms and
- * policies.
- *
- * @hide
- */
-public final class IpSecConfig implements Parcelable {
- private static final String TAG = "IpSecConfig";
-
- // MODE_TRANSPORT or MODE_TUNNEL
- private int mMode = IpSecTransform.MODE_TRANSPORT;
-
- // Preventing this from being null simplifies Java->Native binder
- private String mSourceAddress = "";
-
- // Preventing this from being null simplifies Java->Native binder
- private String mDestinationAddress = "";
-
- // The underlying Network that represents the "gateway" Network
- // for outbound packets. It may also be used to select packets.
- private Network mNetwork;
-
- // Minimum requirements for identifying a transform
- // SPI identifying the IPsec SA in packet processing
- // and a destination IP address
- private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
-
- // Encryption Algorithm
- private IpSecAlgorithm mEncryption;
-
- // Authentication Algorithm
- private IpSecAlgorithm mAuthentication;
-
- // Authenticated Encryption Algorithm
- private IpSecAlgorithm mAuthenticatedEncryption;
-
- // For tunnel mode IPv4 UDP Encapsulation
- // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
- private int mEncapType = IpSecTransform.ENCAP_NONE;
- private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID;
- private int mEncapRemotePort;
-
- // An interval, in seconds between the NattKeepalive packets
- private int mNattKeepaliveInterval;
-
- // XFRM mark and mask; defaults to 0 (no mark/mask)
- private int mMarkValue;
- private int mMarkMask;
-
- // XFRM interface id
- private int mXfrmInterfaceId;
-
- /** Set the mode for this IPsec transform */
- public void setMode(int mode) {
- mMode = mode;
- }
-
- /** Set the source IP addres for this IPsec transform */
- public void setSourceAddress(String sourceAddress) {
- mSourceAddress = sourceAddress;
- }
-
- /** Set the destination IP address for this IPsec transform */
- public void setDestinationAddress(String destinationAddress) {
- mDestinationAddress = destinationAddress;
- }
-
- /** Set the SPI by resource ID */
- public void setSpiResourceId(int resourceId) {
- mSpiResourceId = resourceId;
- }
-
- /** Set the encryption algorithm */
- public void setEncryption(IpSecAlgorithm encryption) {
- mEncryption = encryption;
- }
-
- /** Set the authentication algorithm */
- public void setAuthentication(IpSecAlgorithm authentication) {
- mAuthentication = authentication;
- }
-
- /** Set the authenticated encryption algorithm */
- public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) {
- mAuthenticatedEncryption = authenticatedEncryption;
- }
-
- /** Set the underlying network that will carry traffic for this transform */
- public void setNetwork(Network network) {
- mNetwork = network;
- }
-
- public void setEncapType(int encapType) {
- mEncapType = encapType;
- }
-
- public void setEncapSocketResourceId(int resourceId) {
- mEncapSocketResourceId = resourceId;
- }
-
- public void setEncapRemotePort(int port) {
- mEncapRemotePort = port;
- }
-
- public void setNattKeepaliveInterval(int interval) {
- mNattKeepaliveInterval = interval;
- }
-
- /**
- * Sets the mark value
- *
- * <p>Internal (System server) use only. Marks passed in by users will be overwritten or
- * ignored.
- */
- public void setMarkValue(int mark) {
- mMarkValue = mark;
- }
-
- /**
- * Sets the mark mask
- *
- * <p>Internal (System server) use only. Marks passed in by users will be overwritten or
- * ignored.
- */
- public void setMarkMask(int mask) {
- mMarkMask = mask;
- }
-
- public void setXfrmInterfaceId(int xfrmInterfaceId) {
- mXfrmInterfaceId = xfrmInterfaceId;
- }
-
- // Transport or Tunnel
- public int getMode() {
- return mMode;
- }
-
- public String getSourceAddress() {
- return mSourceAddress;
- }
-
- public int getSpiResourceId() {
- return mSpiResourceId;
- }
-
- public String getDestinationAddress() {
- return mDestinationAddress;
- }
-
- public IpSecAlgorithm getEncryption() {
- return mEncryption;
- }
-
- public IpSecAlgorithm getAuthentication() {
- return mAuthentication;
- }
-
- public IpSecAlgorithm getAuthenticatedEncryption() {
- return mAuthenticatedEncryption;
- }
-
- public Network getNetwork() {
- return mNetwork;
- }
-
- public int getEncapType() {
- return mEncapType;
- }
-
- public int getEncapSocketResourceId() {
- return mEncapSocketResourceId;
- }
-
- public int getEncapRemotePort() {
- return mEncapRemotePort;
- }
-
- public int getNattKeepaliveInterval() {
- return mNattKeepaliveInterval;
- }
-
- public int getMarkValue() {
- return mMarkValue;
- }
-
- public int getMarkMask() {
- return mMarkMask;
- }
-
- public int getXfrmInterfaceId() {
- return mXfrmInterfaceId;
- }
-
- // Parcelable Methods
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mMode);
- out.writeString(mSourceAddress);
- out.writeString(mDestinationAddress);
- out.writeParcelable(mNetwork, flags);
- out.writeInt(mSpiResourceId);
- out.writeParcelable(mEncryption, flags);
- out.writeParcelable(mAuthentication, flags);
- out.writeParcelable(mAuthenticatedEncryption, flags);
- out.writeInt(mEncapType);
- out.writeInt(mEncapSocketResourceId);
- out.writeInt(mEncapRemotePort);
- out.writeInt(mNattKeepaliveInterval);
- out.writeInt(mMarkValue);
- out.writeInt(mMarkMask);
- out.writeInt(mXfrmInterfaceId);
- }
-
- @VisibleForTesting
- public IpSecConfig() {}
-
- /** Copy constructor */
- @VisibleForTesting
- public IpSecConfig(IpSecConfig c) {
- mMode = c.mMode;
- mSourceAddress = c.mSourceAddress;
- mDestinationAddress = c.mDestinationAddress;
- mNetwork = c.mNetwork;
- mSpiResourceId = c.mSpiResourceId;
- mEncryption = c.mEncryption;
- mAuthentication = c.mAuthentication;
- mAuthenticatedEncryption = c.mAuthenticatedEncryption;
- mEncapType = c.mEncapType;
- mEncapSocketResourceId = c.mEncapSocketResourceId;
- mEncapRemotePort = c.mEncapRemotePort;
- mNattKeepaliveInterval = c.mNattKeepaliveInterval;
- mMarkValue = c.mMarkValue;
- mMarkMask = c.mMarkMask;
- mXfrmInterfaceId = c.mXfrmInterfaceId;
- }
-
- private IpSecConfig(Parcel in) {
- mMode = in.readInt();
- mSourceAddress = in.readString();
- mDestinationAddress = in.readString();
- mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
- mSpiResourceId = in.readInt();
- mEncryption =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mAuthentication =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mAuthenticatedEncryption =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mEncapType = in.readInt();
- mEncapSocketResourceId = in.readInt();
- mEncapRemotePort = in.readInt();
- mNattKeepaliveInterval = in.readInt();
- mMarkValue = in.readInt();
- mMarkMask = in.readInt();
- mXfrmInterfaceId = in.readInt();
- }
-
- @Override
- public String toString() {
- StringBuilder strBuilder = new StringBuilder();
- strBuilder
- .append("{mMode=")
- .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
- .append(", mSourceAddress=")
- .append(mSourceAddress)
- .append(", mDestinationAddress=")
- .append(mDestinationAddress)
- .append(", mNetwork=")
- .append(mNetwork)
- .append(", mEncapType=")
- .append(mEncapType)
- .append(", mEncapSocketResourceId=")
- .append(mEncapSocketResourceId)
- .append(", mEncapRemotePort=")
- .append(mEncapRemotePort)
- .append(", mNattKeepaliveInterval=")
- .append(mNattKeepaliveInterval)
- .append("{mSpiResourceId=")
- .append(mSpiResourceId)
- .append(", mEncryption=")
- .append(mEncryption)
- .append(", mAuthentication=")
- .append(mAuthentication)
- .append(", mAuthenticatedEncryption=")
- .append(mAuthenticatedEncryption)
- .append(", mMarkValue=")
- .append(mMarkValue)
- .append(", mMarkMask=")
- .append(mMarkMask)
- .append(", mXfrmInterfaceId=")
- .append(mXfrmInterfaceId)
- .append("}");
-
- return strBuilder.toString();
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<IpSecConfig> CREATOR =
- new Parcelable.Creator<IpSecConfig>() {
- public IpSecConfig createFromParcel(Parcel in) {
- return new IpSecConfig(in);
- }
-
- public IpSecConfig[] newArray(int size) {
- return new IpSecConfig[size];
- }
- };
-
- @Override
- public boolean equals(@Nullable Object other) {
- if (!(other instanceof IpSecConfig)) return false;
- final IpSecConfig rhs = (IpSecConfig) other;
- return (mMode == rhs.mMode
- && mSourceAddress.equals(rhs.mSourceAddress)
- && mDestinationAddress.equals(rhs.mDestinationAddress)
- && ((mNetwork != null && mNetwork.equals(rhs.mNetwork))
- || (mNetwork == rhs.mNetwork))
- && mEncapType == rhs.mEncapType
- && mEncapSocketResourceId == rhs.mEncapSocketResourceId
- && mEncapRemotePort == rhs.mEncapRemotePort
- && mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
- && mSpiResourceId == rhs.mSpiResourceId
- && IpSecAlgorithm.equals(mEncryption, rhs.mEncryption)
- && IpSecAlgorithm.equals(mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
- && IpSecAlgorithm.equals(mAuthentication, rhs.mAuthentication)
- && mMarkValue == rhs.mMarkValue
- && mMarkMask == rhs.mMarkMask
- && mXfrmInterfaceId == rhs.mXfrmInterfaceId);
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
deleted file mode 100644
index 9cb0947..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
+++ /dev/null
@@ -1,1065 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.annotation.TestApi;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.util.AndroidException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import dalvik.system.CloseGuard;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-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
- * confidentiality (encryption) and integrity (authentication) to IP traffic.
- *
- * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
- * transport mode security associations and apply them to individual sockets. Applications looking
- * to create an IPsec VPN should use {@link VpnManager} and {@link Ikev2VpnProfile}.
- *
- * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
- * Internet Protocol</a>
- */
-@SystemService(Context.IPSEC_SERVICE)
-public class IpSecManager {
- private static final String TAG = "IpSecManager";
-
- /**
- * Used when applying a transform to direct traffic through an {@link IpSecTransform}
- * towards the host.
- *
- * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
- */
- public static final int DIRECTION_IN = 0;
-
- /**
- * Used when applying a transform to direct traffic through an {@link IpSecTransform}
- * away from the host.
- *
- * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
- */
- public static final int DIRECTION_OUT = 1;
-
- /**
- * Used when applying a transform to direct traffic through an {@link IpSecTransform} for
- * forwarding between interfaces.
- *
- * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final int DIRECTION_FWD = 2;
-
- /** @hide */
- @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
- @Retention(RetentionPolicy.SOURCE)
- public @interface PolicyDirection {}
-
- /**
- * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
- *
- * <p>No IPsec packet may contain an SPI of 0.
- *
- * @hide
- */
- @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
-
- /** @hide */
- public interface Status {
- int OK = 0;
- int RESOURCE_UNAVAILABLE = 1;
- int SPI_UNAVAILABLE = 2;
- }
-
- /** @hide */
- public static final int INVALID_RESOURCE_ID = -1;
-
- /**
- * Thrown to indicate that a requested SPI is in use.
- *
- * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on
- * one device. If this error is encountered, a new SPI is required before a transform may be
- * created. This error can be avoided by calling {@link
- * IpSecManager#allocateSecurityParameterIndex}.
- */
- public static final class SpiUnavailableException extends AndroidException {
- private final int mSpi;
-
- /**
- * Construct an exception indicating that a transform with the given SPI is already in use
- * or otherwise unavailable.
- *
- * @param msg description indicating the colliding SPI
- * @param spi the SPI that could not be used due to a collision
- */
- SpiUnavailableException(String msg, int spi) {
- super(msg + " (spi: " + spi + ")");
- mSpi = spi;
- }
-
- /** Get the SPI that caused a collision. */
- public int getSpi() {
- return mSpi;
- }
- }
-
- /**
- * Thrown to indicate that an IPsec resource is unavailable.
- *
- * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link
- * IpSecTransform}, or other system resources. If this exception is thrown, users should release
- * allocated objects of the type requested.
- */
- public static final class ResourceUnavailableException extends AndroidException {
-
- ResourceUnavailableException(String msg) {
- super(msg);
- }
- }
-
- private final Context mContext;
- private final IIpSecService mService;
-
- /**
- * This class represents a reserved SPI.
- *
- * <p>Objects of this type are used to track reserved security parameter indices. They can be
- * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released
- * by calling {@link #close()} when they are no longer needed.
- */
- public static final class SecurityParameterIndex implements AutoCloseable {
- private final IIpSecService mService;
- private final InetAddress mDestinationAddress;
- private final CloseGuard mCloseGuard = CloseGuard.get();
- private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
- private int mResourceId = INVALID_RESOURCE_ID;
-
- /** Get the underlying SPI held by this object. */
- public int getSpi() {
- return mSpi;
- }
-
- /**
- * Release an SPI that was previously reserved.
- *
- * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
- * applied to an IpSecTransform, it will become unusable for future transforms but should
- * still be closed to ensure system resources are released.
- */
- @Override
- public void close() {
- try {
- mService.releaseSecurityParameterIndex(mResourceId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (Exception e) {
- // On close we swallow all random exceptions since failure to close is not
- // actionable by the user.
- Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
- } finally {
- mResourceId = INVALID_RESOURCE_ID;
- mCloseGuard.close();
- }
- }
-
- /** Check that the SPI was closed properly. */
- @Override
- protected void finalize() throws Throwable {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
-
- close();
- }
-
- private SecurityParameterIndex(
- @NonNull IIpSecService service, InetAddress destinationAddress, int spi)
- throws ResourceUnavailableException, SpiUnavailableException {
- mService = service;
- mDestinationAddress = destinationAddress;
- try {
- IpSecSpiResponse result =
- mService.allocateSecurityParameterIndex(
- destinationAddress.getHostAddress(), spi, new Binder());
-
- if (result == null) {
- throw new NullPointerException("Received null response from IpSecService");
- }
-
- int status = result.status;
- switch (status) {
- case Status.OK:
- break;
- case Status.RESOURCE_UNAVAILABLE:
- throw new ResourceUnavailableException(
- "No more SPIs may be allocated by this requester.");
- case Status.SPI_UNAVAILABLE:
- throw new SpiUnavailableException("Requested SPI is unavailable", spi);
- default:
- throw new RuntimeException(
- "Unknown status returned by IpSecService: " + status);
- }
- mSpi = result.spi;
- mResourceId = result.resourceId;
-
- if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
- throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
- }
-
- if (mResourceId == INVALID_RESOURCE_ID) {
- throw new RuntimeException(
- "Invalid Resource ID returned by IpSecService: " + status);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- mCloseGuard.open("open");
- }
-
- /** @hide */
- @VisibleForTesting
- public int getResourceId() {
- return mResourceId;
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("SecurityParameterIndex{spi=")
- .append(mSpi)
- .append(",resourceId=")
- .append(mResourceId)
- .append("}")
- .toString();
- }
- }
-
- /**
- * Reserve a random SPI for traffic bound to or from the specified destination address.
- *
- * <p>If successful, this SPI is guaranteed available until released by a call to {@link
- * SecurityParameterIndex#close()}.
- *
- * @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 ResourceUnavailableException indicating that too many SPIs are
- * currently allocated for this user
- */
- @NonNull
- public SecurityParameterIndex allocateSecurityParameterIndex(
- @NonNull InetAddress destinationAddress) throws ResourceUnavailableException {
- try {
- return new SecurityParameterIndex(
- mService,
- destinationAddress,
- IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
- } catch (ServiceSpecificException e) {
- throw rethrowUncheckedExceptionFromServiceSpecificException(e);
- } catch (SpiUnavailableException unlikely) {
- // Because this function allocates a totally random SPI, it really shouldn't ever
- // fail to allocate an SPI; we simply need this because the exception is checked.
- throw new ResourceUnavailableException("No SPIs available");
- }
- }
-
- /**
- * Reserve the requested SPI for traffic bound to or from the specified destination address.
- *
- * <p>If successful, this SPI is guaranteed available until released by a call to {@link
- * SecurityParameterIndex#close()}.
- *
- * @param destinationAddress the destination address for traffic bearing the requested SPI.
- * For inbound traffic, the destination should be an address currently assigned on-device.
- * @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 ResourceUnavailableException indicating that too many SPIs are
- * currently allocated for this user
- * @throws SpiUnavailableException indicating that the requested SPI could not be
- * reserved
- */
- @NonNull
- public SecurityParameterIndex allocateSecurityParameterIndex(
- @NonNull InetAddress destinationAddress, int requestedSpi)
- throws SpiUnavailableException, ResourceUnavailableException {
- if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
- throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
- }
- try {
- return new SecurityParameterIndex(mService, destinationAddress, requestedSpi);
- } catch (ServiceSpecificException e) {
- throw rethrowUncheckedExceptionFromServiceSpecificException(e);
- }
- }
-
- /**
- * Apply an IPsec transform to a stream socket.
- *
- * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
- * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
- * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
- * unprotected traffic can resume on that socket.
- *
- * <p>For security reasons, the destination address of any traffic on the socket must match the
- * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
- * other IP address will result in an IOException. In addition, reads and writes on the socket
- * will throw IOException if the user deactivates the transform (by calling {@link
- * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
- *
- * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an
- * applied transform before completion of graceful shutdown may result in the shutdown sequence
- * failing to complete. As such, applications requiring graceful shutdown MUST close the socket
- * prior to deactivating the applied transform. Socket closure may be performed asynchronously
- * (in batches), so the returning of a close function does not guarantee shutdown of a socket.
- * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is
- * sufficient to ensure shutdown.
- *
- * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}),
- * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST]
- * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the
- * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped.
- *
- * <h4>Rekey Procedure</h4>
- *
- * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
- * will be removed and the new transform will take effect immediately, sending all traffic on
- * the new transform; however, when applying a transform in the inbound direction, traffic
- * on the old transform will continue to be decrypted and delivered until that transform is
- * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
- * procedures where both transforms are valid until both endpoints are using the new transform
- * and all in-flight packets have been received.
- *
- * @param socket a stream socket
- * @param direction the direction in which the transform should be applied
- * @param transform a transport mode {@code IpSecTransform}
- * @throws IOException indicating that the transform could not be applied
- */
- public void applyTransportModeTransform(@NonNull Socket socket,
- @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
- // Ensure creation of FD. See b/77548890 for more details.
- socket.getSoLinger();
-
- applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
- }
-
- /**
- * Apply an IPsec transform to a datagram socket.
- *
- * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
- * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
- * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
- * unprotected traffic can resume on that socket.
- *
- * <p>For security reasons, the destination address of any traffic on the socket must match the
- * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
- * other IP address will result in an IOException. In addition, reads and writes on the socket
- * will throw IOException if the user deactivates the transform (by calling {@link
- * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
- *
- * <h4>Rekey Procedure</h4>
- *
- * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
- * will be removed and the new transform will take effect immediately, sending all traffic on
- * the new transform; however, when applying a transform in the inbound direction, traffic
- * on the old transform will continue to be decrypted and delivered until that transform is
- * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
- * procedures where both transforms are valid until both endpoints are using the new transform
- * and all in-flight packets have been received.
- *
- * @param socket a datagram socket
- * @param direction the direction in which the transform should be applied
- * @param transform a transport mode {@code IpSecTransform}
- * @throws IOException indicating that the transform could not be applied
- */
- public void applyTransportModeTransform(@NonNull DatagramSocket socket,
- @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
- applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
- }
-
- /**
- * Apply an IPsec transform to a socket.
- *
- * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
- * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
- * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
- * unprotected traffic can resume on that socket.
- *
- * <p>For security reasons, the destination address of any traffic on the socket must match the
- * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
- * other IP address will result in an IOException. In addition, reads and writes on the socket
- * will throw IOException if the user deactivates the transform (by calling {@link
- * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
- *
- * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an
- * applied transform before completion of graceful shutdown may result in the shutdown sequence
- * failing to complete. As such, applications requiring graceful shutdown MUST close the socket
- * prior to deactivating the applied transform. Socket closure may be performed asynchronously
- * (in batches), so the returning of a close function does not guarantee shutdown of a socket.
- * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is
- * sufficient to ensure shutdown.
- *
- * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}),
- * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST]
- * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the
- * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped.
- *
- * <h4>Rekey Procedure</h4>
- *
- * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
- * will be removed and the new transform will take effect immediately, sending all traffic on
- * the new transform; however, when applying a transform in the inbound direction, traffic
- * on the old transform will continue to be decrypted and delivered until that transform is
- * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
- * procedures where both transforms are valid until both endpoints are using the new transform
- * and all in-flight packets have been received.
- *
- * @param socket a socket file descriptor
- * @param direction the direction in which the transform should be applied
- * @param transform a transport mode {@code IpSecTransform}
- * @throws IOException indicating that the transform could not be applied
- */
- public void applyTransportModeTransform(@NonNull FileDescriptor socket,
- @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
- // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
- // constructor takes control and closes the user's FD when we exit the method.
- try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
- mService.applyTransportModeTransform(pfd, direction, transform.getResourceId());
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Remove an IPsec transform from a stream socket.
- *
- * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
- * socket allows the socket to be reused for communication in the clear.
- *
- * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
- * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
- * is called.
- *
- * @param socket a socket that previously had a transform applied to it
- * @throws IOException indicating that the transform could not be removed from the socket
- */
- public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException {
- // Ensure creation of FD. See b/77548890 for more details.
- socket.getSoLinger();
-
- removeTransportModeTransforms(socket.getFileDescriptor$());
- }
-
- /**
- * Remove an IPsec transform from a datagram socket.
- *
- * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
- * socket allows the socket to be reused for communication in the clear.
- *
- * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
- * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
- * is called.
- *
- * @param socket a socket that previously had a transform applied to it
- * @throws IOException indicating that the transform could not be removed from the socket
- */
- public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException {
- removeTransportModeTransforms(socket.getFileDescriptor$());
- }
-
- /**
- * Remove an IPsec transform from a socket.
- *
- * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
- * socket allows the socket to be reused for communication in the clear.
- *
- * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
- * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
- * is called.
- *
- * @param socket a socket that previously had a transform applied to it
- * @throws IOException indicating that the transform could not be removed from the socket
- */
- public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException {
- try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
- mService.removeTransportModeTransforms(pfd);
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
- * cleanup if a tunneled Network experiences a change in default route. The Network will drop
- * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
- * lost, all traffic will drop.
- *
- * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
- *
- * @param net a network that currently has transform applied to it.
- * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
- * network
- * @hide
- */
- public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
-
- /**
- * This class provides access to a UDP encapsulation Socket.
- *
- * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2
- * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link
- * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the
- * caller. The caller should not close the {@code FileDescriptor} returned by {@link
- * #getFileDescriptor}, but should use {@link #close} instead.
- *
- * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic
- * of the next user who binds to that port. To prevent this scenario, these sockets are held
- * open by the system so that they may only be closed by calling {@link #close} or when the user
- * process exits.
- */
- public static final class UdpEncapsulationSocket implements AutoCloseable {
- private final ParcelFileDescriptor mPfd;
- private final IIpSecService mService;
- private int mResourceId = INVALID_RESOURCE_ID;
- private final int mPort;
- private final CloseGuard mCloseGuard = CloseGuard.get();
-
- private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
- throws ResourceUnavailableException, IOException {
- mService = service;
- try {
- IpSecUdpEncapResponse result =
- mService.openUdpEncapsulationSocket(port, new Binder());
- switch (result.status) {
- case Status.OK:
- break;
- case Status.RESOURCE_UNAVAILABLE:
- throw new ResourceUnavailableException(
- "No more Sockets may be allocated by this requester.");
- default:
- throw new RuntimeException(
- "Unknown status returned by IpSecService: " + result.status);
- }
- mResourceId = result.resourceId;
- mPort = result.port;
- mPfd = result.fileDescriptor;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- mCloseGuard.open("constructor");
- }
-
- /** Get the encapsulation socket's file descriptor. */
- public FileDescriptor getFileDescriptor() {
- if (mPfd == null) {
- return null;
- }
- return mPfd.getFileDescriptor();
- }
-
- /** Get the bound port of the wrapped socket. */
- public int getPort() {
- return mPort;
- }
-
- /**
- * Close this socket.
- *
- * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's
- * resource limits, and forgetting to close them eventually will result in {@link
- * ResourceUnavailableException} being thrown.
- */
- @Override
- public void close() throws IOException {
- try {
- mService.closeUdpEncapsulationSocket(mResourceId);
- mResourceId = INVALID_RESOURCE_ID;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (Exception e) {
- // On close we swallow all random exceptions since failure to close is not
- // actionable by the user.
- Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
- } finally {
- mResourceId = INVALID_RESOURCE_ID;
- mCloseGuard.close();
- }
-
- try {
- mPfd.close();
- } catch (IOException e) {
- Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort);
- throw e;
- }
- }
-
- /** Check that the socket was closed properly. */
- @Override
- protected void finalize() throws Throwable {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- /** @hide */
- @SystemApi(client = MODULE_LIBRARIES)
- public int getResourceId() {
- return mResourceId;
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("UdpEncapsulationSocket{port=")
- .append(mPort)
- .append(",resourceId=")
- .append(mResourceId)
- .append("}")
- .toString();
- }
- };
-
- /**
- * Open a socket for UDP encapsulation and bind to the given port.
- *
- * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
- *
- * @param port a local UDP port
- * @return a socket that is bound to the given port
- * @throws IOException indicating that the socket could not be opened or bound
- * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
- */
- // Returning a socket in this fashion that has been created and bound by the system
- // is the only safe way to ensure that a socket is both accessible to the user and
- // safely usable for Encapsulation without allowing a user to possibly unbind from/close
- // the port, which could potentially impact the traffic of the next user who binds to that
- // socket.
- @NonNull
- public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
- throws IOException, ResourceUnavailableException {
- /*
- * Most range checking is done in the service, but this version of the constructor expects
- * a valid port number, and zero cannot be checked after being passed to the service.
- */
- if (port == 0) {
- throw new IllegalArgumentException("Specified port must be a valid port number!");
- }
- try {
- return new UdpEncapsulationSocket(mService, port);
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- }
- }
-
- /**
- * Open a socket for UDP encapsulation.
- *
- * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
- *
- * <p>The local port of the returned socket can be obtained by calling {@link
- * UdpEncapsulationSocket#getPort()}.
- *
- * @return a socket that is bound to a local port
- * @throws IOException indicating that the socket could not be opened or bound
- * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
- */
- // Returning a socket in this fashion that has been created and bound by the system
- // is the only safe way to ensure that a socket is both accessible to the user and
- // safely usable for Encapsulation without allowing a user to possibly unbind from/close
- // the port, which could potentially impact the traffic of the next user who binds to that
- // socket.
- @NonNull
- public UdpEncapsulationSocket openUdpEncapsulationSocket()
- throws IOException, ResourceUnavailableException {
- try {
- return new UdpEncapsulationSocket(mService, 0);
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- }
- }
-
- /**
- * This class represents an IpSecTunnelInterface
- *
- * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as
- * local endpoints for IPsec tunnels.
- *
- * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be
- * applied to provide IPsec security to packets sent through the tunnel. While a tunnel
- * cannot be used in standalone mode within Android, the higher layers may use the tunnel
- * to create Network objects which are accessible to the Android system.
- * @hide
- */
- @SystemApi
- public static final class IpSecTunnelInterface implements AutoCloseable {
- private final String mOpPackageName;
- private final IIpSecService mService;
- private final InetAddress mRemoteAddress;
- private final InetAddress mLocalAddress;
- private final Network mUnderlyingNetwork;
- private final CloseGuard mCloseGuard = CloseGuard.get();
- private String mInterfaceName;
- private int mResourceId = INVALID_RESOURCE_ID;
-
- /** Get the underlying SPI held by this object. */
- @NonNull
- public String getInterfaceName() {
- return mInterfaceName;
- }
-
- /**
- * Add an address to the IpSecTunnelInterface
- *
- * <p>Add an address which may be used as the local inner address for
- * tunneled traffic.
- *
- * @param address the local address for traffic inside the tunnel
- * @param prefixLen length of the InetAddress prefix
- * @hide
- */
- @SystemApi
- @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
- try {
- mService.addAddressToTunnelInterface(
- mResourceId, new LinkAddress(address, prefixLen), mOpPackageName);
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Remove an address from the IpSecTunnelInterface
- *
- * <p>Remove an address which was previously added to the IpSecTunnelInterface
- *
- * @param address to be removed
- * @param prefixLen length of the InetAddress prefix
- * @hide
- */
- @SystemApi
- @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
- try {
- mService.removeAddressFromTunnelInterface(
- mResourceId, new LinkAddress(address, prefixLen), mOpPackageName);
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Update the underlying network for this IpSecTunnelInterface.
- *
- * <p>This new underlying network will be used for all transforms applied AFTER this call is
- * complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to
- * this tunnel interface, traffic will still use the old SA, and be routed on the old
- * underlying network.
- *
- * <p>To migrate IPsec tunnel mode traffic, a caller should:
- *
- * <ol>
- * <li>Update the IpSecTunnelInterface’s underlying network.
- * <li>Apply {@link IpSecTransform}(s) with matching addresses to this
- * IpSecTunnelInterface.
- * </ol>
- *
- * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel.
- * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise
- * this method will throw an {@link IllegalArgumentException}. If the
- * IpSecTunnelInterface is later added to this network, all outbound traffic will be
- * blackholed.
- */
- // TODO: b/169171001 Update the documentation when transform migration is supported.
- // The purpose of making updating network and applying transforms separate is to leave open
- // the possibility to support lossless migration procedures. To do that, Android platform
- // will need to support multiple inbound tunnel mode transforms, just like it can support
- // multiple transport mode transforms.
- @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException {
- try {
- mService.setNetworkForTunnelInterface(
- mResourceId, underlyingNetwork, mOpPackageName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service,
- @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
- @NonNull Network underlyingNetwork)
- throws ResourceUnavailableException, IOException {
- mOpPackageName = ctx.getOpPackageName();
- mService = service;
- mLocalAddress = localAddress;
- mRemoteAddress = remoteAddress;
- mUnderlyingNetwork = underlyingNetwork;
-
- try {
- IpSecTunnelInterfaceResponse result =
- mService.createTunnelInterface(
- localAddress.getHostAddress(),
- remoteAddress.getHostAddress(),
- underlyingNetwork,
- new Binder(),
- mOpPackageName);
- switch (result.status) {
- case Status.OK:
- break;
- case Status.RESOURCE_UNAVAILABLE:
- throw new ResourceUnavailableException(
- "No more tunnel interfaces may be allocated by this requester.");
- default:
- throw new RuntimeException(
- "Unknown status returned by IpSecService: " + result.status);
- }
- mResourceId = result.resourceId;
- mInterfaceName = result.interfaceName;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- mCloseGuard.open("constructor");
- }
-
- /**
- * Delete an IpSecTunnelInterface
- *
- * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system
- * resources. Any packets bound for this interface either inbound or outbound will
- * all be lost.
- */
- @Override
- public void close() {
- try {
- mService.deleteTunnelInterface(mResourceId, mOpPackageName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (Exception e) {
- // On close we swallow all random exceptions since failure to close is not
- // actionable by the user.
- Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
- } finally {
- mResourceId = INVALID_RESOURCE_ID;
- mCloseGuard.close();
- }
- }
-
- /** Check that the Interface was closed properly. */
- @Override
- protected void finalize() throws Throwable {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- /** @hide */
- @VisibleForTesting
- public int getResourceId() {
- return mResourceId;
- }
-
- @NonNull
- @Override
- public String toString() {
- return new StringBuilder()
- .append("IpSecTunnelInterface{ifname=")
- .append(mInterfaceName)
- .append(",resourceId=")
- .append(mResourceId)
- .append("}")
- .toString();
- }
- }
-
- /**
- * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic.
- *
- * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the
- * underlying network goes away, and the onLost() callback is received.
- *
- * @param localAddress The local addres of the tunnel
- * @param remoteAddress The local addres of the tunnel
- * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel.
- * This network should almost certainly be a network such as WiFi with an L2 address.
- * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties
- * @throws IOException indicating that the socket could not be opened or bound
- * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
- * @hide
- */
- @SystemApi
- @NonNull
- @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
- @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
- throws ResourceUnavailableException, IOException {
- try {
- return new IpSecTunnelInterface(
- mContext, mService, localAddress, remoteAddress, underlyingNetwork);
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- }
- }
-
- /**
- * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will
- * tunnel all traffic for the given direction through the underlying network's interface with
- * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional
- * IP header and IPsec Header on all inbound traffic).
- * <p>Applications should probably not use this API directly.
- *
- *
- * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
- * transform.
- * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
- * the transform will be used.
- * @param transform an {@link IpSecTransform} created in tunnel mode
- * @throws IOException indicating that the transform could not be applied due to a lower
- * layer failure.
- * @hide
- */
- @SystemApi
- @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
- @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
- try {
- mService.applyTunnelModeTransform(
- tunnel.getResourceId(), direction,
- transform.getResourceId(), mContext.getOpPackageName());
- } catch (ServiceSpecificException e) {
- throw rethrowCheckedExceptionFromServiceSpecificException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
- public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder,
- String callingPackage) {
- try {
- return mService.createTransform(config, binder, callingPackage);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
- public void deleteTransform(int resourceId) {
- try {
- mService.deleteTransform(resourceId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Construct an instance of IpSecManager within an application context.
- *
- * @param context the application context for this manager
- * @hide
- */
- public IpSecManager(Context ctx, IIpSecService service) {
- mContext = ctx;
- mService = Objects.requireNonNull(service, "missing service");
- }
-
- private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) {
- // OsConstants are late binding, so switch statements can't be used.
- if (sse.errorCode == OsConstants.EINVAL) {
- throw new IllegalArgumentException(sse);
- } else if (sse.errorCode == OsConstants.EAGAIN) {
- throw new IllegalStateException(sse);
- } else if (sse.errorCode == OsConstants.EOPNOTSUPP
- || sse.errorCode == OsConstants.EPROTONOSUPPORT) {
- throw new UnsupportedOperationException(sse);
- }
- }
-
- /**
- * Convert an Errno SSE to the correct Unchecked exception type.
- *
- * This method never actually returns.
- */
- // package
- static RuntimeException
- rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) {
- maybeHandleServiceSpecificException(sse);
- throw new RuntimeException(sse);
- }
-
- /**
- * Convert an Errno SSE to the correct Checked or Unchecked exception type.
- *
- * This method may throw IOException, or it may throw an unchecked exception; it will never
- * actually return.
- */
- // package
- static IOException rethrowCheckedExceptionFromServiceSpecificException(
- ServiceSpecificException sse) throws IOException {
- // First see if this is an unchecked exception of a type we know.
- // If so, then we prefer the unchecked (specific) type of exception.
- maybeHandleServiceSpecificException(sse);
- // If not, then all we can do is provide the SSE in the form of an IOException.
- throw new ErrnoException(
- "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException();
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl
deleted file mode 100644
index 6484a00..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/** @hide */
-parcelable IpSecSpiResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java
deleted file mode 100644
index f99e570..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to return an SPI and corresponding status from the IpSecService to an
- * IpSecManager.SecurityParameterIndex.
- *
- * @hide
- */
-public final class IpSecSpiResponse implements Parcelable {
- private static final String TAG = "IpSecSpiResponse";
-
- public final int resourceId;
- public final int status;
- public final int spi;
- // Parcelable Methods
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(status);
- out.writeInt(resourceId);
- out.writeInt(spi);
- }
-
- public IpSecSpiResponse(int inStatus, int inResourceId, int inSpi) {
- status = inStatus;
- resourceId = inResourceId;
- spi = inSpi;
- }
-
- public IpSecSpiResponse(int inStatus) {
- if (inStatus == IpSecManager.Status.OK) {
- throw new IllegalArgumentException("Valid status implies other args must be provided");
- }
- status = inStatus;
- resourceId = IpSecManager.INVALID_RESOURCE_ID;
- spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
- }
-
- private IpSecSpiResponse(Parcel in) {
- status = in.readInt();
- resourceId = in.readInt();
- spi = in.readInt();
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<IpSecSpiResponse> CREATOR =
- new Parcelable.Creator<IpSecSpiResponse>() {
- public IpSecSpiResponse createFromParcel(Parcel in) {
- return new IpSecSpiResponse(in);
- }
-
- public IpSecSpiResponse[] newArray(int size) {
- return new IpSecSpiResponse[size];
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
deleted file mode 100644
index 68ae5de..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2017 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.IpSecManager.INVALID_RESOURCE_ID;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.ServiceSpecificException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import dalvik.system.CloseGuard;
-
-import java.io.IOException;
-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.
- *
- * <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
- * object encapsulates the properties and state of an IPsec security association. That includes,
- * but is not limited to, algorithm choice, key material, and allocated system resources.
- *
- * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
- * Internet Protocol</a>
- */
-public final class IpSecTransform implements AutoCloseable {
- private static final String TAG = "IpSecTransform";
-
- /** @hide */
- public static final int MODE_TRANSPORT = 0;
-
- /** @hide */
- public static final int MODE_TUNNEL = 1;
-
- /** @hide */
- public static final int ENCAP_NONE = 0;
-
- /**
- * IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP
- * header and payload. This prevents traffic from being interpreted as ESP or IKEv2.
- *
- * @hide
- */
- public static final int ENCAP_ESPINUDP_NON_IKE = 1;
-
- /**
- * IPsec traffic will be encapsulated within UDP as per
- * <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
- *
- * @hide
- */
- public static final int ENCAP_ESPINUDP = 2;
-
- /** @hide */
- @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface EncapType {}
-
- /** @hide */
- @VisibleForTesting
- public IpSecTransform(Context context, IpSecConfig config) {
- mContext = context;
- mConfig = new IpSecConfig(config);
- mResourceId = INVALID_RESOURCE_ID;
- }
-
- private IpSecManager getIpSecManager(Context context) {
- return context.getSystemService(IpSecManager.class);
- }
- /**
- * Checks the result status and throws an appropriate exception if the status is not Status.OK.
- */
- private void checkResultStatus(int status)
- throws IOException, IpSecManager.ResourceUnavailableException,
- IpSecManager.SpiUnavailableException {
- switch (status) {
- case IpSecManager.Status.OK:
- return;
- // TODO: Pass Error string back from bundle so that errors can be more specific
- case IpSecManager.Status.RESOURCE_UNAVAILABLE:
- throw new IpSecManager.ResourceUnavailableException(
- "Failed to allocate a new IpSecTransform");
- case IpSecManager.Status.SPI_UNAVAILABLE:
- Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
- // Fall through
- default:
- throw new IllegalStateException(
- "Failed to Create a Transform with status code " + status);
- }
- }
-
- private IpSecTransform activate()
- throws IOException, IpSecManager.ResourceUnavailableException,
- IpSecManager.SpiUnavailableException {
- synchronized (this) {
- try {
- IpSecTransformResponse result = getIpSecManager(mContext).createTransform(
- mConfig, new Binder(), mContext.getOpPackageName());
- int status = result.status;
- checkResultStatus(status);
- mResourceId = result.resourceId;
- Log.d(TAG, "Added Transform with Id " + mResourceId);
- mCloseGuard.open("build");
- } catch (ServiceSpecificException e) {
- throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
- }
- }
-
- return this;
- }
-
- /**
- * Standard equals.
- */
- public boolean equals(@Nullable Object other) {
- if (this == other) return true;
- if (!(other instanceof IpSecTransform)) return false;
- final IpSecTransform rhs = (IpSecTransform) other;
- return getConfig().equals(rhs.getConfig()) && mResourceId == rhs.mResourceId;
- }
-
- /**
- * Deactivate this {@code IpSecTransform} and free allocated resources.
- *
- * <p>Deactivating a transform while it is still applied to a socket will result in errors on
- * that socket. Make sure to remove transforms by calling {@link
- * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
- * socket will not deactivate it (because one transform may be applied to multiple sockets).
- *
- * <p>It is safe to call this method on a transform that has already been deactivated.
- */
- public void close() {
- Log.d(TAG, "Removing Transform with Id " + mResourceId);
-
- // Always safe to attempt cleanup
- if (mResourceId == INVALID_RESOURCE_ID) {
- mCloseGuard.close();
- return;
- }
- try {
- getIpSecManager(mContext).deleteTransform(mResourceId);
- } catch (Exception e) {
- // On close we swallow all random exceptions since failure to close is not
- // actionable by the user.
- Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
- } finally {
- mResourceId = INVALID_RESOURCE_ID;
- mCloseGuard.close();
- }
- }
-
- /** Check that the transform was closed properly. */
- @Override
- protected void finalize() throws Throwable {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- /* Package */
- IpSecConfig getConfig() {
- return mConfig;
- }
-
- private final IpSecConfig mConfig;
- private int mResourceId;
- private final Context mContext;
- private final CloseGuard mCloseGuard = CloseGuard.get();
-
- /** @hide */
- @VisibleForTesting
- public int getResourceId() {
- return mResourceId;
- }
-
- /**
- * A callback class to provide status information regarding a NAT-T keepalive session
- *
- * <p>Use this callback to receive status information regarding a NAT-T keepalive session
- * by registering it when calling {@link #startNattKeepalive}.
- *
- * @hide
- */
- public static class NattKeepaliveCallback {
- /** The specified {@code Network} is not connected. */
- public static final int ERROR_INVALID_NETWORK = 1;
- /** The hardware does not support this request. */
- public static final int ERROR_HARDWARE_UNSUPPORTED = 2;
- /** The hardware returned an error. */
- public static final int ERROR_HARDWARE_ERROR = 3;
-
- /** The requested keepalive was successfully started. */
- public void onStarted() {}
- /** The keepalive was successfully stopped. */
- public void onStopped() {}
- /** An error occurred. */
- public void onError(int error) {}
- }
-
- /** This class is used to build {@link IpSecTransform} objects. */
- public static class Builder {
- private Context mContext;
- private IpSecConfig mConfig;
-
- /**
- * Set the encryption algorithm.
- *
- * <p>Encryption is mutually exclusive with authenticated encryption.
- *
- * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
- */
- @NonNull
- public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
- // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
- Objects.requireNonNull(algo);
- mConfig.setEncryption(algo);
- return this;
- }
-
- /**
- * Set the authentication (integrity) algorithm.
- *
- * <p>Authentication is mutually exclusive with authenticated encryption.
- *
- * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
- */
- @NonNull
- public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
- // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
- Objects.requireNonNull(algo);
- mConfig.setAuthentication(algo);
- return this;
- }
-
- /**
- * Set the authenticated encryption algorithm.
- *
- * <p>The Authenticated Encryption (AE) class of algorithms are also known as
- * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
- * algorithms (as referred to in
- * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
- *
- * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
- *
- * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
- * be applied.
- */
- @NonNull
- public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
- Objects.requireNonNull(algo);
- mConfig.setAuthenticatedEncryption(algo);
- return this;
- }
-
- /**
- * Add UDP encapsulation to an IPv4 transform.
- *
- * <p>This allows IPsec traffic to pass through a NAT.
- *
- * @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
- * ESP Packets</a>
- * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
- * NAT Traversal of IKEv2</a>
- * @param localSocket a socket for sending and receiving encapsulated traffic
- * @param remotePort the UDP port number of the remote host that will send and receive
- * encapsulated traffic. In the case of IKEv2, this should be port 4500.
- */
- @NonNull
- public IpSecTransform.Builder setIpv4Encapsulation(
- @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
- Objects.requireNonNull(localSocket);
- mConfig.setEncapType(ENCAP_ESPINUDP);
- if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
- throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
- }
- mConfig.setEncapSocketResourceId(localSocket.getResourceId());
- mConfig.setEncapRemotePort(remotePort);
- return this;
- }
-
- /**
- * Build a transport mode {@link IpSecTransform}.
- *
- * <p>This builds and activates a transport mode transform. Note that an active transform
- * will not affect any network traffic until it has been applied to one or more sockets.
- *
- * @see IpSecManager#applyTransportModeTransform
- * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
- * this transform; this address must belong to the Network used by all sockets that
- * utilize this transform; if provided, then only traffic originating from the
- * specified source address will be processed.
- * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
- * traffic
- * @throws IllegalArgumentException indicating that a particular combination of transform
- * properties is invalid
- * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
- * are active
- * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
- * collides with an existing transform
- * @throws IOException indicating other errors
- */
- @NonNull
- public IpSecTransform buildTransportModeTransform(
- @NonNull InetAddress sourceAddress,
- @NonNull IpSecManager.SecurityParameterIndex spi)
- throws IpSecManager.ResourceUnavailableException,
- IpSecManager.SpiUnavailableException, IOException {
- Objects.requireNonNull(sourceAddress);
- Objects.requireNonNull(spi);
- if (spi.getResourceId() == INVALID_RESOURCE_ID) {
- throw new IllegalArgumentException("Invalid SecurityParameterIndex");
- }
- mConfig.setMode(MODE_TRANSPORT);
- mConfig.setSourceAddress(sourceAddress.getHostAddress());
- mConfig.setSpiResourceId(spi.getResourceId());
- // FIXME: modifying a builder after calling build can change the built transform.
- return new IpSecTransform(mContext, mConfig).activate();
- }
-
- /**
- * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
- * parameters have interdependencies that are checked at build time.
- *
- * @param sourceAddress the {@link InetAddress} that provides the source address for this
- * IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
- * that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
- * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
- * traffic
- * @throws IllegalArgumentException indicating that a particular combination of transform
- * properties is invalid.
- * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
- * are active
- * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
- * collides with an existing transform
- * @throws IOException indicating other errors
- * @hide
- */
- @SystemApi
- @NonNull
- @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public IpSecTransform buildTunnelModeTransform(
- @NonNull InetAddress sourceAddress,
- @NonNull IpSecManager.SecurityParameterIndex spi)
- throws IpSecManager.ResourceUnavailableException,
- IpSecManager.SpiUnavailableException, IOException {
- Objects.requireNonNull(sourceAddress);
- Objects.requireNonNull(spi);
- if (spi.getResourceId() == INVALID_RESOURCE_ID) {
- throw new IllegalArgumentException("Invalid SecurityParameterIndex");
- }
- mConfig.setMode(MODE_TUNNEL);
- mConfig.setSourceAddress(sourceAddress.getHostAddress());
- mConfig.setSpiResourceId(spi.getResourceId());
- return new IpSecTransform(mContext, mConfig).activate();
- }
-
- /**
- * Create a new IpSecTransform.Builder.
- *
- * @param context current context
- */
- public Builder(@NonNull Context context) {
- Objects.requireNonNull(context);
- mContext = context;
- mConfig = new IpSecConfig();
- }
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("IpSecTransform{resourceId=")
- .append(mResourceId)
- .append("}")
- .toString();
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl
deleted file mode 100644
index 546230d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/** @hide */
-parcelable IpSecTransformResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java
deleted file mode 100644
index 363f316..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to return an IpSecTransform resource Id and and corresponding status from the
- * IpSecService to an IpSecTransform object.
- *
- * @hide
- */
-public final class IpSecTransformResponse implements Parcelable {
- private static final String TAG = "IpSecTransformResponse";
-
- public final int resourceId;
- public final int status;
- // Parcelable Methods
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(status);
- out.writeInt(resourceId);
- }
-
- public IpSecTransformResponse(int inStatus) {
- if (inStatus == IpSecManager.Status.OK) {
- throw new IllegalArgumentException("Valid status implies other args must be provided");
- }
- status = inStatus;
- resourceId = IpSecManager.INVALID_RESOURCE_ID;
- }
-
- public IpSecTransformResponse(int inStatus, int inResourceId) {
- status = inStatus;
- resourceId = inResourceId;
- }
-
- private IpSecTransformResponse(Parcel in) {
- status = in.readInt();
- resourceId = in.readInt();
- }
-
- @android.annotation.NonNull
- public static final Parcelable.Creator<IpSecTransformResponse> CREATOR =
- new Parcelable.Creator<IpSecTransformResponse>() {
- public IpSecTransformResponse createFromParcel(Parcel in) {
- return new IpSecTransformResponse(in);
- }
-
- public IpSecTransformResponse[] newArray(int size) {
- return new IpSecTransformResponse[size];
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
deleted file mode 100644
index 7239221..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2018 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;
-
-/** @hide */
-parcelable IpSecTunnelInterfaceResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
deleted file mode 100644
index 127e30a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to return an IpSecTunnelInterface resource Id and and corresponding status
- * from the IpSecService to an IpSecTunnelInterface object.
- *
- * @hide
- */
-public final class IpSecTunnelInterfaceResponse implements Parcelable {
- private static final String TAG = "IpSecTunnelInterfaceResponse";
-
- public final int resourceId;
- public final String interfaceName;
- public final int status;
- // Parcelable Methods
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(status);
- out.writeInt(resourceId);
- out.writeString(interfaceName);
- }
-
- public IpSecTunnelInterfaceResponse(int inStatus) {
- if (inStatus == IpSecManager.Status.OK) {
- throw new IllegalArgumentException("Valid status implies other args must be provided");
- }
- status = inStatus;
- resourceId = IpSecManager.INVALID_RESOURCE_ID;
- interfaceName = "";
- }
-
- public IpSecTunnelInterfaceResponse(int inStatus, int inResourceId, String inInterfaceName) {
- status = inStatus;
- resourceId = inResourceId;
- interfaceName = inInterfaceName;
- }
-
- private IpSecTunnelInterfaceResponse(Parcel in) {
- status = in.readInt();
- resourceId = in.readInt();
- interfaceName = in.readString();
- }
-
- @android.annotation.NonNull
- public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
- new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
- public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
- return new IpSecTunnelInterfaceResponse(in);
- }
-
- public IpSecTunnelInterfaceResponse[] newArray(int size) {
- return new IpSecTunnelInterfaceResponse[size];
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl
deleted file mode 100644
index 5e451f3..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/** @hide */
-parcelable IpSecUdpEncapResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
deleted file mode 100644
index 732cf19..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * This class is used to return a UDP Socket and corresponding status from the IpSecService to an
- * IpSecManager.UdpEncapsulationSocket.
- *
- * @hide
- */
-public final class IpSecUdpEncapResponse implements Parcelable {
- private static final String TAG = "IpSecUdpEncapResponse";
-
- public final int resourceId;
- public final int port;
- public final int status;
- // There is a weird asymmetry with FileDescriptor: you can write a FileDescriptor
- // but you read a ParcelFileDescriptor. To circumvent this, when we receive a FD
- // from the user, we immediately create a ParcelFileDescriptor DUP, which we invalidate
- // on writeParcel() by setting the flag to do close-on-write.
- // TODO: tests to ensure this doesn't leak
- public final ParcelFileDescriptor fileDescriptor;
-
- // Parcelable Methods
-
- @Override
- public int describeContents() {
- return (fileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(status);
- out.writeInt(resourceId);
- out.writeInt(port);
- out.writeParcelable(fileDescriptor, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- }
-
- public IpSecUdpEncapResponse(int inStatus) {
- if (inStatus == IpSecManager.Status.OK) {
- throw new IllegalArgumentException("Valid status implies other args must be provided");
- }
- status = inStatus;
- resourceId = IpSecManager.INVALID_RESOURCE_ID;
- port = -1;
- fileDescriptor = null; // yes I know it's redundant, but readability
- }
-
- public IpSecUdpEncapResponse(int inStatus, int inResourceId, int inPort, FileDescriptor inFd)
- throws IOException {
- if (inStatus == IpSecManager.Status.OK && inFd == null) {
- throw new IllegalArgumentException("Valid status implies FD must be non-null");
- }
- status = inStatus;
- resourceId = inResourceId;
- port = inPort;
- fileDescriptor = (status == IpSecManager.Status.OK) ? ParcelFileDescriptor.dup(inFd) : null;
- }
-
- private IpSecUdpEncapResponse(Parcel in) {
- status = in.readInt();
- resourceId = in.readInt();
- port = in.readInt();
- fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
- }
-
- @android.annotation.NonNull
- public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
- new Parcelable.Creator<IpSecUdpEncapResponse>() {
- public IpSecUdpEncapResponse createFromParcel(Parcel in) {
- return new IpSecUdpEncapResponse(in);
- }
-
- public IpSecUdpEncapResponse[] newArray(int size) {
- return new IpSecUdpEncapResponse[size];
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
deleted file mode 100644
index a48f94b..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ /dev/null
@@ -1,594 +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.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.app.usage.NetworkStatsManager;
-import android.content.Context;
-import android.net.wifi.WifiInfo;
-import android.service.NetworkIdentityProto;
-import android.telephony.TelephonyManager;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkCapabilitiesUtils;
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Objects;
-
-/**
- * Network definition that includes strong identity. Analogous to combining
- * {@link NetworkCapabilities} and an IMSI.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public class NetworkIdentity {
- private static final String TAG = "NetworkIdentity";
-
- /** @hide */
- // TODO: Remove this after migrating all callers to use
- // {@link NetworkTemplate#NETWORK_TYPE_ALL} instead.
- public static final int SUBTYPE_COMBINED = -1;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = {
- NetworkTemplate.OEM_MANAGED_NO,
- NetworkTemplate.OEM_MANAGED_PAID,
- NetworkTemplate.OEM_MANAGED_PRIVATE
- })
- public @interface OemManaged{}
-
- /**
- * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
- * @hide
- */
- public static final int OEM_NONE = 0x0;
- /**
- * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
- * @hide
- */
- public static final int OEM_PAID = 1 << 0;
- /**
- * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
- * @hide
- */
- public static final int OEM_PRIVATE = 1 << 1;
-
- private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
-
- final int mType;
- final int mRatType;
- final int mSubId;
- final String mSubscriberId;
- final String mWifiNetworkKey;
- final boolean mRoaming;
- final boolean mMetered;
- final boolean mDefaultNetwork;
- final int mOemManaged;
-
- /** @hide */
- public NetworkIdentity(
- int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
- boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId) {
- mType = type;
- mRatType = ratType;
- mSubscriberId = subscriberId;
- mWifiNetworkKey = wifiNetworkKey;
- mRoaming = roaming;
- mMetered = metered;
- mDefaultNetwork = defaultNetwork;
- mOemManaged = oemManaged;
- mSubId = subId;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
- mDefaultNetwork, mOemManaged, mSubId);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (obj instanceof NetworkIdentity) {
- final NetworkIdentity ident = (NetworkIdentity) obj;
- return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming
- && Objects.equals(mSubscriberId, ident.mSubscriberId)
- && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
- && mMetered == ident.mMetered
- && mDefaultNetwork == ident.mDefaultNetwork
- && mOemManaged == ident.mOemManaged
- && mSubId == ident.mSubId;
- }
- return false;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder("{");
- builder.append("type=").append(mType);
- builder.append(", ratType=");
- if (mRatType == NETWORK_TYPE_ALL) {
- builder.append("COMBINED");
- } else {
- builder.append(mRatType);
- }
- if (mSubscriberId != null) {
- builder.append(", subscriberId=")
- .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
- }
- if (mWifiNetworkKey != null) {
- builder.append(", wifiNetworkKey=").append(mWifiNetworkKey);
- }
- if (mRoaming) {
- builder.append(", ROAMING");
- }
- builder.append(", metered=").append(mMetered);
- builder.append(", defaultNetwork=").append(mDefaultNetwork);
- builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
- builder.append(", subId=").append(mSubId);
- 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 + ")";
- }
- }
-
- /** @hide */
- public void dumpDebug(ProtoOutputStream proto, long tag) {
- final long start = proto.start(tag);
-
- proto.write(NetworkIdentityProto.TYPE_FIELD_NUMBER, mType);
-
- // TODO: dump mRatType as well.
-
- proto.write(NetworkIdentityProto.ROAMING_FIELD_NUMBER, mRoaming);
- proto.write(NetworkIdentityProto.METERED_FIELD_NUMBER, mMetered);
- proto.write(NetworkIdentityProto.DEFAULT_NETWORK_FIELD_NUMBER, mDefaultNetwork);
- proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK_FIELD_NUMBER, mOemManaged);
-
- proto.end(start);
- }
-
- /** Get the network type of this instance. */
- public int getType() {
- return mType;
- }
-
- /** Get the Radio Access Technology(RAT) type of this instance. */
- public int getRatType() {
- return mRatType;
- }
-
- /** Get the Subscriber Id of this instance. */
- @Nullable
- public String getSubscriberId() {
- return mSubscriberId;
- }
-
- /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */
- @Nullable
- public String getWifiNetworkKey() {
- return mWifiNetworkKey;
- }
-
- /** @hide */
- // TODO: Remove this function after all callers are removed.
- public boolean getRoaming() {
- return mRoaming;
- }
-
- /** Return whether this network is roaming. */
- public boolean isRoaming() {
- return mRoaming;
- }
-
- /** @hide */
- // TODO: Remove this function after all callers are removed.
- public boolean getMetered() {
- return mMetered;
- }
-
- /** Return whether this network is metered. */
- public boolean isMetered() {
- return mMetered;
- }
-
- /** @hide */
- // TODO: Remove this function after all callers are removed.
- public boolean getDefaultNetwork() {
- return mDefaultNetwork;
- }
-
- /** Return whether this network is the default network. */
- public boolean isDefaultNetwork() {
- return mDefaultNetwork;
- }
-
- /** Get the OEM managed type of this instance. */
- public int getOemManaged() {
- return mOemManaged;
- }
-
- /** Get the SubId of this instance. */
- public int getSubId() {
- return mSubId;
- }
-
- /**
- * Assemble a {@link NetworkIdentity} from the passed arguments.
- *
- * This methods builds an identity based on the capabilities of the network in the
- * snapshot and other passed arguments. The identity is used as a key to record data usage.
- *
- * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}.
- * @param defaultNetwork whether the network is a default network.
- * @param ratType the Radio Access Technology(RAT) type of the network. Or
- * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable.
- * See {@code TelephonyManager.NETWORK_TYPE_*}.
- * @hide
- * @deprecated See {@link NetworkIdentity.Builder}.
- */
- // TODO: Remove this after all callers are migrated to use new Api.
- @Deprecated
- @NonNull
- public static NetworkIdentity buildNetworkIdentity(Context context,
- @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
- final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
- .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork)
- .setSubId(snapshot.getSubId());
- if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
- builder.setRatType(ratType);
- }
- return builder.build();
- }
-
- /**
- * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
- * @hide
- */
- public static int getOemBitfield(@NonNull NetworkCapabilities nc) {
- int oemManaged = OEM_NONE;
-
- if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
- oemManaged |= OEM_PAID;
- }
- if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) {
- oemManaged |= OEM_PRIVATE;
- }
-
- return oemManaged;
- }
-
- /** @hide */
- public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) {
- Objects.requireNonNull(right);
- int res = Integer.compare(left.mType, right.mType);
- if (res == 0) {
- res = Integer.compare(left.mRatType, right.mRatType);
- }
- if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) {
- res = left.mSubscriberId.compareTo(right.mSubscriberId);
- }
- if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) {
- res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey);
- }
- if (res == 0) {
- res = Boolean.compare(left.mRoaming, right.mRoaming);
- }
- if (res == 0) {
- res = Boolean.compare(left.mMetered, right.mMetered);
- }
- if (res == 0) {
- res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork);
- }
- if (res == 0) {
- res = Integer.compare(left.mOemManaged, right.mOemManaged);
- }
- if (res == 0) {
- res = Integer.compare(left.mSubId, right.mSubId);
- }
- return res;
- }
-
- /**
- * Builder class for {@link NetworkIdentity}.
- */
- public static final class Builder {
- // Need to be synchronized with ConnectivityManager.
- // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module.
- private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST
- private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
-
- private int mType;
- private int mRatType;
- private String mSubscriberId;
- private String mWifiNetworkKey;
- private boolean mRoaming;
- private boolean mMetered;
- private boolean mDefaultNetwork;
- private int mOemManaged;
- private int mSubId;
-
- /**
- * Creates a new Builder.
- */
- public Builder() {
- // Initialize with default values. Will be overwritten by setters.
- mType = ConnectivityManager.TYPE_NONE;
- mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
- mSubscriberId = null;
- mWifiNetworkKey = null;
- mRoaming = false;
- mMetered = false;
- mDefaultNetwork = false;
- mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
- mSubId = INVALID_SUBSCRIPTION_ID;
- }
-
- /**
- * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance.
- * This is a useful shorthand that will read from the snapshot and set the
- * following fields, if they are set in the snapshot :
- * - type
- * - subscriberId
- * - roaming
- * - metered
- * - oemManaged
- * - wifiNetworkKey
- *
- * @param snapshot The target {@link NetworkStateSnapshot} object.
- * @return The builder object.
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- @NonNull
- public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) {
- setType(snapshot.getLegacyType());
-
- setSubscriberId(snapshot.getSubscriberId());
- setRoaming(!snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING));
- setMetered(!(snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
- || snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)));
-
- setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
-
- if (mType == TYPE_WIFI) {
- final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
- .getTransportInfo();
- if (transportInfo instanceof WifiInfo) {
- final WifiInfo info = (WifiInfo) transportInfo;
- setWifiNetworkKey(info.getNetworkKey());
- }
- }
- return this;
- }
-
- /**
- * Set the network type of the network.
- *
- * @param type the network type. See {@link ConnectivityManager#TYPE_*}.
- *
- * @return this builder.
- */
- @NonNull
- public Builder setType(int type) {
- // Include TYPE_NONE for compatibility, type field might not be filled by some
- // networks such as test networks.
- if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type)
- && type != ConnectivityManager.TYPE_NONE) {
- throw new IllegalArgumentException("Invalid network type: " + type);
- }
- mType = type;
- return this;
- }
-
- /**
- * Set the Radio Access Technology(RAT) type of the network.
- *
- * No RAT type is specified by default. Call clearRatType to reset.
- *
- * @param ratType the Radio Access Technology(RAT) type if applicable. See
- * {@code TelephonyManager.NETWORK_TYPE_*}.
- *
- * @return this builder.
- */
- @NonNull
- public Builder setRatType(int ratType) {
- if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
- && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN
- && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) {
- throw new IllegalArgumentException("Invalid ratType " + ratType);
- }
- mRatType = ratType;
- return this;
- }
-
- /**
- * Clear the Radio Access Technology(RAT) type of the network.
- *
- * @return this builder.
- */
- @NonNull
- public Builder clearRatType() {
- mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
- return this;
- }
-
- /**
- * Set the Subscriber Id.
- *
- * @param subscriberId the Subscriber Id of the network. Or null if not applicable.
- * @return this builder.
- */
- @NonNull
- public Builder setSubscriberId(@Nullable String subscriberId) {
- mSubscriberId = subscriberId;
- return this;
- }
-
- /**
- * Set the Wifi Network Key.
- *
- * @param wifiNetworkKey Wifi Network Key of the network,
- * see {@link WifiInfo#getNetworkKey()}.
- * Or null if not applicable.
- * @return this builder.
- */
- @NonNull
- public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
- mWifiNetworkKey = wifiNetworkKey;
- return this;
- }
-
- /**
- * Set whether this network is roaming.
- *
- * This field is false by default. Call with false to reset.
- *
- * @param roaming the roaming status of the network.
- * @return this builder.
- */
- @NonNull
- public Builder setRoaming(boolean roaming) {
- mRoaming = roaming;
- return this;
- }
-
- /**
- * Set whether this network is metered.
- *
- * This field is false by default. Call with false to reset.
- *
- * @param metered the meteredness of the network.
- * @return this builder.
- */
- @NonNull
- public Builder setMetered(boolean metered) {
- mMetered = metered;
- return this;
- }
-
- /**
- * Set whether this network is the default network.
- *
- * This field is false by default. Call with false to reset.
- *
- * @param defaultNetwork the default network status of the network.
- * @return this builder.
- */
- @NonNull
- public Builder setDefaultNetwork(boolean defaultNetwork) {
- mDefaultNetwork = defaultNetwork;
- return this;
- }
-
- /**
- * Set the OEM managed type.
- *
- * @param oemManaged Type of OEM managed network or unmanaged networks.
- * See {@code NetworkTemplate#OEM_MANAGED_*}.
- * @return this builder.
- */
- @NonNull
- public Builder setOemManaged(@OemManaged int oemManaged) {
- // Assert input does not contain illegal oemManage bits.
- if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) {
- throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged);
- }
- mOemManaged = oemManaged;
- return this;
- }
-
- /**
- * Set the Subscription Id.
- *
- * @param subId the Subscription Id of the network. Or INVALID_SUBSCRIPTION_ID if not
- * applicable.
- * @return this builder.
- */
- @NonNull
- public Builder setSubId(int subId) {
- mSubId = subId;
- return this;
- }
-
- private void ensureValidParameters() {
- // Assert non-mobile network cannot have a ratType.
- if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
- throw new IllegalArgumentException(
- "Invalid ratType " + mRatType + " for type " + mType);
- }
-
- // Assert non-wifi network cannot have a wifi network key.
- if (mType != TYPE_WIFI && mWifiNetworkKey != null) {
- throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
- }
- }
-
- /**
- * Builds the instance of the {@link NetworkIdentity}.
- *
- * @return the built instance of {@link NetworkIdentity}.
- */
- @NonNull
- public NetworkIdentity build() {
- ensureValidParameters();
- return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
- mRoaming, mMetered, mDefaultNetwork, mOemManaged, mSubId);
- }
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
deleted file mode 100644
index 56461ba..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
+++ /dev/null
@@ -1,230 +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_MOBILE;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.annotation.NonNull;
-import android.service.NetworkIdentitySetProto;
-import android.util.proto.ProtoOutputStream;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
- * active on that interface.
- *
- * @hide
- */
-public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
- private static final int VERSION_INIT = 1;
- private static final int VERSION_ADD_ROAMING = 2;
- private static final int VERSION_ADD_NETWORK_ID = 3;
- private static final int VERSION_ADD_METERED = 4;
- private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
- private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
- private static final int VERSION_ADD_SUB_ID = 7;
-
- /**
- * Construct a {@link NetworkIdentitySet} object.
- */
- public NetworkIdentitySet() {
- super();
- }
-
- /** @hide */
- public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) {
- super(ident);
- }
-
- /** @hide */
- public NetworkIdentitySet(DataInput in) throws IOException {
- final int version = in.readInt();
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- if (version <= VERSION_INIT) {
- final int ignored = in.readInt();
- }
- final int type = in.readInt();
- final int ratType = in.readInt();
- final String subscriberId = readOptionalString(in);
- final String networkId;
- if (version >= VERSION_ADD_NETWORK_ID) {
- networkId = readOptionalString(in);
- } else {
- networkId = null;
- }
- final boolean roaming;
- if (version >= VERSION_ADD_ROAMING) {
- roaming = in.readBoolean();
- } else {
- roaming = false;
- }
-
- final boolean metered;
- if (version >= VERSION_ADD_METERED) {
- metered = in.readBoolean();
- } else {
- // If this is the old data and the type is mobile, treat it as metered. (Note that
- // if this is a mobile network, TYPE_MOBILE is the only possible type that could be
- // used.)
- metered = (type == TYPE_MOBILE);
- }
-
- final boolean defaultNetwork;
- if (version >= VERSION_ADD_DEFAULT_NETWORK) {
- defaultNetwork = in.readBoolean();
- } else {
- defaultNetwork = true;
- }
-
- final int oemNetCapabilities;
- if (version >= VERSION_ADD_OEM_MANAGED_NETWORK) {
- oemNetCapabilities = in.readInt();
- } else {
- oemNetCapabilities = NetworkIdentity.OEM_NONE;
- }
-
- final int subId;
- if (version >= VERSION_ADD_SUB_ID) {
- subId = in.readInt();
- } else {
- subId = INVALID_SUBSCRIPTION_ID;
- }
-
- add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
- defaultNetwork, oemNetCapabilities, subId));
- }
- }
-
- /**
- * Method to serialize this object into a {@code DataOutput}.
- * @hide
- */
- public void writeToStream(DataOutput out) throws IOException {
- out.writeInt(VERSION_ADD_SUB_ID);
- out.writeInt(size());
- for (NetworkIdentity ident : this) {
- out.writeInt(ident.getType());
- out.writeInt(ident.getRatType());
- writeOptionalString(out, ident.getSubscriberId());
- writeOptionalString(out, ident.getWifiNetworkKey());
- out.writeBoolean(ident.isRoaming());
- out.writeBoolean(ident.isMetered());
- out.writeBoolean(ident.isDefaultNetwork());
- out.writeInt(ident.getOemManaged());
- out.writeInt(ident.getSubId());
- }
- }
-
- /**
- * @return whether any {@link NetworkIdentity} in this set is considered metered.
- * @hide
- */
- public boolean isAnyMemberMetered() {
- if (isEmpty()) {
- return false;
- }
- for (NetworkIdentity ident : this) {
- if (ident.isMetered()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * @return whether any {@link NetworkIdentity} in this set is considered roaming.
- * @hide
- */
- public boolean isAnyMemberRoaming() {
- if (isEmpty()) {
- return false;
- }
- for (NetworkIdentity ident : this) {
- if (ident.isRoaming()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * @return whether any {@link NetworkIdentity} in this set is considered on the default
- * network.
- * @hide
- */
- public boolean areAllMembersOnDefaultNetwork() {
- if (isEmpty()) {
- return true;
- }
- for (NetworkIdentity ident : this) {
- if (!ident.isDefaultNetwork()) {
- return false;
- }
- }
- return true;
- }
-
- private static void writeOptionalString(DataOutput out, String value) throws IOException {
- if (value != null) {
- out.writeByte(1);
- out.writeUTF(value);
- } else {
- out.writeByte(0);
- }
- }
-
- private static String readOptionalString(DataInput in) throws IOException {
- if (in.readByte() != 0) {
- return in.readUTF();
- } else {
- return null;
- }
- }
-
- public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) {
- Objects.requireNonNull(left);
- Objects.requireNonNull(right);
- if (left.isEmpty()) return -1;
- if (right.isEmpty()) return 1;
-
- final NetworkIdentity leftIdent = left.iterator().next();
- final NetworkIdentity rightIdent = right.iterator().next();
- return NetworkIdentity.compare(leftIdent, rightIdent);
- }
-
- /**
- * Method to dump this object into proto debug file.
- * @hide
- */
- public void dumpDebug(ProtoOutputStream proto, long tag) {
- final long start = proto.start(tag);
-
- for (NetworkIdentity ident : this) {
- ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES_FIELD_NUMBER);
- }
-
- proto.end(start);
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
deleted file mode 100644
index d3f785a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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 static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.util.Objects;
-
-/**
- * Snapshot of network state.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class NetworkStateSnapshot implements Parcelable {
- /** The network associated with this snapshot. */
- @NonNull
- private final Network mNetwork;
-
- /** The {@link NetworkCapabilities} of the network associated with this snapshot. */
- @NonNull
- private final NetworkCapabilities mNetworkCapabilities;
-
- /** The {@link LinkProperties} of the network associated with this snapshot. */
- @NonNull
- private final LinkProperties mLinkProperties;
-
- /**
- * The Subscriber Id of the network associated with this snapshot. See
- * {@link android.telephony.TelephonyManager#getSubscriberId()}.
- */
- @Nullable
- private final String mSubscriberId;
-
- /**
- * The legacy type of the network associated with this snapshot. See
- * {@code ConnectivityManager#TYPE_*}.
- */
- private final int mLegacyType;
-
- public NetworkStateSnapshot(@NonNull Network network,
- @NonNull NetworkCapabilities networkCapabilities,
- @NonNull LinkProperties linkProperties,
- @Nullable String subscriberId, int legacyType) {
- mNetwork = Objects.requireNonNull(network);
- mNetworkCapabilities = Objects.requireNonNull(networkCapabilities);
- mLinkProperties = Objects.requireNonNull(linkProperties);
- mSubscriberId = subscriberId;
- mLegacyType = legacyType;
- }
-
- /** @hide */
- public NetworkStateSnapshot(@NonNull Parcel in) {
- mNetwork = in.readParcelable(null);
- mNetworkCapabilities = in.readParcelable(null);
- mLinkProperties = in.readParcelable(null);
- mSubscriberId = in.readString();
- mLegacyType = in.readInt();
- }
-
- /** Get the network associated with this snapshot */
- @NonNull
- public Network getNetwork() {
- return mNetwork;
- }
-
- /** Get {@link NetworkCapabilities} of the network associated with this snapshot. */
- @NonNull
- public NetworkCapabilities getNetworkCapabilities() {
- return mNetworkCapabilities;
- }
-
- /** Get the {@link LinkProperties} of the network associated with this snapshot. */
- @NonNull
- public LinkProperties getLinkProperties() {
- return mLinkProperties;
- }
-
- /**
- * Get the Subscriber Id of the network associated with this snapshot.
- * @deprecated Please use #getSubId, which doesn't return personally identifiable
- * information.
- */
- @Deprecated
- @Nullable
- public String getSubscriberId() {
- return mSubscriberId;
- }
-
- /** Get the subId of the network associated with this snapshot. */
- public int getSubId() {
- if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
- final NetworkSpecifier spec = mNetworkCapabilities.getNetworkSpecifier();
- if (spec instanceof TelephonyNetworkSpecifier) {
- return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
- }
- }
- return INVALID_SUBSCRIPTION_ID;
- }
-
-
- /**
- * Get the legacy type of the network associated with this snapshot.
- * @return the legacy network type. See {@code ConnectivityManager#TYPE_*}.
- */
- public int getLegacyType() {
- return mLegacyType;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeParcelable(mNetwork, flags);
- out.writeParcelable(mNetworkCapabilities, flags);
- out.writeParcelable(mLinkProperties, flags);
- out.writeString(mSubscriberId);
- out.writeInt(mLegacyType);
- }
-
- @NonNull
- public static final Creator<NetworkStateSnapshot> CREATOR =
- new Creator<NetworkStateSnapshot>() {
- @NonNull
- @Override
- public NetworkStateSnapshot createFromParcel(@NonNull Parcel in) {
- return new NetworkStateSnapshot(in);
- }
-
- @NonNull
- @Override
- public NetworkStateSnapshot[] newArray(int size) {
- return new NetworkStateSnapshot[size];
- }
- };
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof NetworkStateSnapshot)) return false;
- NetworkStateSnapshot that = (NetworkStateSnapshot) o;
- return mLegacyType == that.mLegacyType
- && Objects.equals(mNetwork, that.mNetwork)
- && Objects.equals(mNetworkCapabilities, that.mNetworkCapabilities)
- && Objects.equals(mLinkProperties, that.mLinkProperties)
- && Objects.equals(mSubscriberId, that.mSubscriberId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mNetwork,
- mNetworkCapabilities, mLinkProperties, mSubscriberId, mLegacyType);
- }
-
- @Override
- public String toString() {
- return "NetworkStateSnapshot{"
- + "network=" + mNetwork
- + ", networkCapabilities=" + mNetworkCapabilities
- + ", linkProperties=" + mLinkProperties
- + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(mSubscriberId) + '\''
- + ", legacyType=" + mLegacyType
- + '}';
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
deleted file mode 100644
index 06f2a62..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ /dev/null
@@ -1,1834 +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 com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.SparseBooleanArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.CollectionUtils;
-
-import libcore.util.EmptyArray;
-
-import java.io.CharArrayWriter;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Predicate;
-
-/**
- * Collection of active network statistics. Can contain summary details across
- * all interfaces, or details with per-UID granularity. Internally stores data
- * as a large table, closely matching {@code /proc/} data format. This structure
- * optimizes for rapid in-memory comparison, but consider using
- * {@link NetworkStatsHistory} when persisting.
- *
- * @hide
- */
-// @NotThreadSafe
-@SystemApi
-public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Entry> {
- private static final String TAG = "NetworkStats";
-
- /**
- * {@link #iface} value when interface details unavailable.
- * @hide
- */
- @Nullable public static final String IFACE_ALL = null;
-
- /**
- * Virtual network interface for video telephony. This is for VT data usage counting
- * purpose.
- */
- public static final String IFACE_VT = "vt_data0";
-
- /** {@link #uid} value when UID details unavailable. */
- public static final int UID_ALL = -1;
- /** Special UID value for data usage by tethering. */
- public static final int UID_TETHERING = -5;
-
- /**
- * {@link #tag} value matching any tag.
- * @hide
- */
- // 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. */
- public static final int SET_ALL = -1;
- /** {@link #set} value where background data is accounted. */
- public static final int SET_DEFAULT = 0;
- /** {@link #set} value where foreground data is accounted. */
- public static final int SET_FOREGROUND = 1;
- /**
- * All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values.
- * @hide
- */
- public static final int SET_DEBUG_START = 1000;
- /**
- * Debug {@link #set} value when the VPN stats are moved in.
- * @hide
- */
- public static final int SET_DBG_VPN_IN = 1001;
- /**
- * Debug {@link #set} value when the VPN stats are moved out of a vpn UID.
- * @hide
- */
- public static final int SET_DBG_VPN_OUT = 1002;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "SET_" }, value = {
- SET_ALL,
- SET_DEFAULT,
- SET_FOREGROUND,
- })
- public @interface State {
- }
-
- /**
- * Include all interfaces when filtering
- * @hide
- */
- public @Nullable static final String[] INTERFACES_ALL = null;
-
- /** {@link #tag} value for total data across all tags. */
- // TODO: Rename TAG_NONE to TAG_ALL.
- public static final int TAG_NONE = 0;
-
- /** {@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;
- /** {@link #metered} value where metered data is accounted. */
- public static final int METERED_YES = 1;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "METERED_" }, value = {
- METERED_ALL,
- METERED_NO,
- METERED_YES
- })
- public @interface Meteredness {
- }
-
-
- /** {@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;
- /** {@link #roaming} value where roaming data is accounted. */
- public static final int ROAMING_YES = 1;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "ROAMING_" }, value = {
- ROAMING_ALL,
- ROAMING_NO,
- ROAMING_YES
- })
- public @interface Roaming {
- }
-
- /** {@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;
- /** {@link #onDefaultNetwork} value to account for usage while the default network. */
- public static final int DEFAULT_NETWORK_YES = 1;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = {
- DEFAULT_NETWORK_ALL,
- DEFAULT_NETWORK_NO,
- DEFAULT_NETWORK_YES
- })
- public @interface DefaultNetwork {
- }
-
- /**
- * Denotes a request for stats at the interface level.
- * @hide
- */
- public static final int STATS_PER_IFACE = 0;
- /**
- * Denotes a request for stats at the interface and UID level.
- * @hide
- */
- public static final int STATS_PER_UID = 1;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "STATS_PER_" }, value = {
- STATS_PER_IFACE,
- STATS_PER_UID
- })
- public @interface StatsType {
- }
-
- private static final String CLATD_INTERFACE_PREFIX = "v4-";
- // Delta between IPv4 header (20b) and IPv6 header (40b).
- // Used for correct stats accounting on clatd interfaces.
- private static final int IPV4V6_HEADER_DELTA = 20;
-
- // TODO: move fields to "mVariable" notation
-
- /**
- * {@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)
- private int size;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private int capacity;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String[] iface;
- @UnsupportedAppUsage
- private int[] uid;
- @UnsupportedAppUsage
- private int[] set;
- @UnsupportedAppUsage
- private int[] tag;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private int[] metered;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private int[] roaming;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private int[] defaultNetwork;
- @UnsupportedAppUsage
- private long[] rxBytes;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private long[] rxPackets;
- @UnsupportedAppUsage
- private long[] txBytes;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private long[] txPackets;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private long[] operations;
-
- /**
- * Basic element of network statistics. Contains the number of packets and number of bytes
- * transferred on both directions in a given set of conditions. See
- * {@link Entry#Entry(String, int, int, int, int, int, int, long, long, long, long, long)}.
- *
- * @hide
- */
- @SystemApi
- public static class Entry {
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public String iface;
- /** @hide */
- @UnsupportedAppUsage
- public int uid;
- /** @hide */
- @UnsupportedAppUsage
- public int set;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int tag;
- /**
- * Note that this is only populated w/ the default value when read from /proc or written
- * to disk. We merge in the correct value when reporting this value to clients of
- * getSummary().
- * @hide
- */
- public int metered;
- /**
- * Note that this is only populated w/ the default value when read from /proc or written
- * to disk. We merge in the correct value when reporting this value to clients of
- * getSummary().
- * @hide
- */
- public int roaming;
- /**
- * Note that this is only populated w/ the default value when read from /proc or written
- * to disk. We merge in the correct value when reporting this value to clients of
- * getSummary().
- * @hide
- */
- public int defaultNetwork;
- /** @hide */
- @UnsupportedAppUsage
- public long rxBytes;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long rxPackets;
- /** @hide */
- @UnsupportedAppUsage
- public long txBytes;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long txPackets;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long operations;
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public Entry() {
- this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
- }
-
- /** @hide */
- public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
- this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
- operations);
- }
-
- /** @hide */
- public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
- long txBytes, long txPackets, long operations) {
- this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
- rxBytes, rxPackets, txBytes, txPackets, operations);
- }
-
- /**
- * Construct a {@link Entry} object by giving statistics of packet and byte transferred on
- * both direction, and associated with a set of given conditions.
- *
- * @param iface interface name of this {@link Entry}. Or null if not specified.
- * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
- * for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
- * counting iface stats.
- * @param set usage state of this {@link Entry}.
- * @param tag tag of this {@link Entry}.
- * @param metered metered state of this {@link Entry}.
- * @param roaming roaming state of this {@link Entry}.
- * @param defaultNetwork default network status of this {@link Entry}.
- * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param operations count of network operations performed for this {@link Entry}. This can
- * be used to derive bytes-per-operation.
- */
- public Entry(@Nullable String iface, int uid, @State int set, int tag,
- @Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork,
- long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
- this.iface = iface;
- this.uid = uid;
- this.set = set;
- this.tag = tag;
- this.metered = metered;
- this.roaming = roaming;
- this.defaultNetwork = defaultNetwork;
- this.rxBytes = rxBytes;
- this.rxPackets = rxPackets;
- this.txBytes = txBytes;
- this.txPackets = txPackets;
- this.operations = operations;
- }
-
- /** @hide */
- public boolean isNegative() {
- return rxBytes < 0 || rxPackets < 0 || txBytes < 0 || txPackets < 0 || operations < 0;
- }
-
- /** @hide */
- public boolean isEmpty() {
- return rxBytes == 0 && rxPackets == 0 && txBytes == 0 && txPackets == 0
- && operations == 0;
- }
-
- /** @hide */
- public void add(Entry another) {
- this.rxBytes += another.rxBytes;
- this.rxPackets += another.rxPackets;
- this.txBytes += another.txBytes;
- this.txPackets += another.txPackets;
- this.operations += another.operations;
- }
-
- /**
- * @return interface name of this entry.
- * @hide
- */
- @Nullable public String getIface() {
- return iface;
- }
-
- /**
- * @return the uid of this entry.
- */
- public int getUid() {
- return uid;
- }
-
- /**
- * @return the set state of this entry.
- */
- @State public int getSet() {
- return set;
- }
-
- /**
- * @return the tag value of this entry.
- */
- public int getTag() {
- return tag;
- }
-
- /**
- * @return the metered state.
- */
- @Meteredness public int getMetered() {
- return metered;
- }
-
- /**
- * @return the roaming state.
- */
- @Roaming public int getRoaming() {
- return roaming;
- }
-
- /**
- * @return the default network state.
- */
- @DefaultNetwork public int getDefaultNetwork() {
- return defaultNetwork;
- }
-
- /**
- * @return the number of received bytes.
- */
- public long getRxBytes() {
- return rxBytes;
- }
-
- /**
- * @return the number of received packets.
- */
- public long getRxPackets() {
- return rxPackets;
- }
-
- /**
- * @return the number of transmitted bytes.
- */
- public long getTxBytes() {
- return txBytes;
- }
-
- /**
- * @return the number of transmitted packets.
- */
- public long getTxPackets() {
- return txPackets;
- }
-
- /**
- * @return the count of network operations performed for this entry.
- */
- public long getOperations() {
- return operations;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("iface=").append(iface);
- builder.append(" uid=").append(uid);
- builder.append(" set=").append(setToString(set));
- builder.append(" tag=").append(tagToString(tag));
- builder.append(" metered=").append(meteredToString(metered));
- builder.append(" roaming=").append(roamingToString(roaming));
- builder.append(" defaultNetwork=").append(defaultNetworkToString(defaultNetwork));
- builder.append(" rxBytes=").append(rxBytes);
- builder.append(" rxPackets=").append(rxPackets);
- builder.append(" txBytes=").append(txBytes);
- builder.append(" txPackets=").append(txPackets);
- builder.append(" operations=").append(operations);
- return builder.toString();
- }
-
- /** @hide */
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof Entry) {
- final Entry e = (Entry) o;
- return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered
- && roaming == e.roaming && defaultNetwork == e.defaultNetwork
- && rxBytes == e.rxBytes && rxPackets == e.rxPackets
- && txBytes == e.txBytes && txPackets == e.txPackets
- && operations == e.operations && TextUtils.equals(iface, e.iface);
- }
- return false;
- }
-
- /** @hide */
- @Override
- public int hashCode() {
- return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface);
- }
- }
-
- public NetworkStats(long elapsedRealtime, int initialSize) {
- this.elapsedRealtime = elapsedRealtime;
- this.size = 0;
- if (initialSize > 0) {
- this.capacity = initialSize;
- this.iface = new String[initialSize];
- this.uid = new int[initialSize];
- this.set = new int[initialSize];
- this.tag = new int[initialSize];
- this.metered = new int[initialSize];
- this.roaming = new int[initialSize];
- this.defaultNetwork = new int[initialSize];
- this.rxBytes = new long[initialSize];
- this.rxPackets = new long[initialSize];
- this.txBytes = new long[initialSize];
- this.txPackets = new long[initialSize];
- this.operations = new long[initialSize];
- } else {
- // Special case for use by NetworkStatsFactory to start out *really* empty.
- clear();
- }
- }
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public NetworkStats(Parcel parcel) {
- elapsedRealtime = parcel.readLong();
- size = parcel.readInt();
- capacity = parcel.readInt();
- iface = parcel.createStringArray();
- uid = parcel.createIntArray();
- set = parcel.createIntArray();
- tag = parcel.createIntArray();
- metered = parcel.createIntArray();
- roaming = parcel.createIntArray();
- defaultNetwork = parcel.createIntArray();
- rxBytes = parcel.createLongArray();
- rxPackets = parcel.createLongArray();
- txBytes = parcel.createLongArray();
- txPackets = parcel.createLongArray();
- operations = parcel.createLongArray();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeLong(elapsedRealtime);
- dest.writeInt(size);
- dest.writeInt(capacity);
- dest.writeStringArray(iface);
- dest.writeIntArray(uid);
- dest.writeIntArray(set);
- dest.writeIntArray(tag);
- dest.writeIntArray(metered);
- dest.writeIntArray(roaming);
- dest.writeIntArray(defaultNetwork);
- dest.writeLongArray(rxBytes);
- dest.writeLongArray(rxPackets);
- dest.writeLongArray(txBytes);
- dest.writeLongArray(txPackets);
- dest.writeLongArray(operations);
- }
-
- /**
- * @hide
- */
- @Override
- public NetworkStats clone() {
- final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
- NetworkStats.Entry entry = null;
- for (int i = 0; i < size; i++) {
- entry = getValues(i, entry);
- clone.insertEntry(entry);
- }
- return clone;
- }
-
- /**
- * Clear all data stored in this object.
- * @hide
- */
- public void clear() {
- this.capacity = 0;
- this.iface = EmptyArray.STRING;
- this.uid = EmptyArray.INT;
- this.set = EmptyArray.INT;
- this.tag = EmptyArray.INT;
- this.metered = EmptyArray.INT;
- this.roaming = EmptyArray.INT;
- this.defaultNetwork = EmptyArray.INT;
- this.rxBytes = EmptyArray.LONG;
- this.rxPackets = EmptyArray.LONG;
- this.txBytes = EmptyArray.LONG;
- this.txPackets = EmptyArray.LONG;
- this.operations = EmptyArray.LONG;
- }
-
- /** @hide */
- @VisibleForTesting
- public NetworkStats insertEntry(
- String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- return insertEntry(
- iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
- }
-
- /** @hide */
- @VisibleForTesting
- public NetworkStats insertEntry(String iface, int uid, int set, int tag, long rxBytes,
- long rxPackets, long txBytes, long txPackets, long operations) {
- return insertEntry(new Entry(
- iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
- }
-
- /** @hide */
- @VisibleForTesting
- public NetworkStats insertEntry(String iface, int uid, int set, int tag, int metered,
- int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes,
- long txPackets, long operations) {
- return insertEntry(new Entry(
- iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
- txBytes, txPackets, operations));
- }
-
- /**
- * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
- * object can be recycled across multiple calls.
- * @hide
- */
- public NetworkStats insertEntry(Entry entry) {
- if (size >= capacity) {
- final int newLength = Math.max(size, 10) * 3 / 2;
- iface = Arrays.copyOf(iface, newLength);
- uid = Arrays.copyOf(uid, newLength);
- set = Arrays.copyOf(set, newLength);
- tag = Arrays.copyOf(tag, newLength);
- metered = Arrays.copyOf(metered, newLength);
- roaming = Arrays.copyOf(roaming, newLength);
- defaultNetwork = Arrays.copyOf(defaultNetwork, newLength);
- rxBytes = Arrays.copyOf(rxBytes, newLength);
- rxPackets = Arrays.copyOf(rxPackets, newLength);
- txBytes = Arrays.copyOf(txBytes, newLength);
- txPackets = Arrays.copyOf(txPackets, newLength);
- operations = Arrays.copyOf(operations, newLength);
- capacity = newLength;
- }
-
- setValues(size, entry);
- size++;
-
- return this;
- }
-
- private void setValues(int i, Entry entry) {
- iface[i] = entry.iface;
- uid[i] = entry.uid;
- set[i] = entry.set;
- tag[i] = entry.tag;
- metered[i] = entry.metered;
- roaming[i] = entry.roaming;
- defaultNetwork[i] = entry.defaultNetwork;
- rxBytes[i] = entry.rxBytes;
- rxPackets[i] = entry.rxPackets;
- txBytes[i] = entry.txBytes;
- txPackets[i] = entry.txPackets;
- operations[i] = entry.operations;
- }
-
- /**
- * Iterate over Entry objects.
- *
- * Return an iterator of this object that will iterate through all contained Entry objects.
- *
- * This iterator does not support concurrent modification and makes no guarantee of fail-fast
- * behavior. If any method that can mutate the contents of this object is called while
- * iteration is in progress, either inside the loop or in another thread, then behavior is
- * undefined.
- * The remove() method is not implemented and will throw UnsupportedOperationException.
- * @hide
- */
- @SystemApi
- @NonNull public Iterator<Entry> iterator() {
- return new Iterator<Entry>() {
- int mIndex = 0;
-
- @Override
- public boolean hasNext() {
- return mIndex < size;
- }
-
- @Override
- public Entry next() {
- return getValues(mIndex++, null);
- }
- };
- }
-
- /**
- * Return specific stats entry.
- * @hide
- */
- @UnsupportedAppUsage
- public Entry getValues(int i, @Nullable Entry recycle) {
- final Entry entry = recycle != null ? recycle : new Entry();
- entry.iface = iface[i];
- entry.uid = uid[i];
- entry.set = set[i];
- entry.tag = tag[i];
- entry.metered = metered[i];
- entry.roaming = roaming[i];
- entry.defaultNetwork = defaultNetwork[i];
- entry.rxBytes = rxBytes[i];
- entry.rxPackets = rxPackets[i];
- entry.txBytes = txBytes[i];
- entry.txPackets = txPackets[i];
- entry.operations = operations[i];
- return entry;
- }
-
- /**
- * If @{code dest} is not equal to @{code src}, copy entry from index @{code src} to index
- * @{code dest}.
- */
- private void maybeCopyEntry(int dest, int src) {
- if (dest == src) return;
- iface[dest] = iface[src];
- uid[dest] = uid[src];
- set[dest] = set[src];
- tag[dest] = tag[src];
- metered[dest] = metered[src];
- roaming[dest] = roaming[src];
- defaultNetwork[dest] = defaultNetwork[src];
- rxBytes[dest] = rxBytes[src];
- rxPackets[dest] = rxPackets[src];
- txBytes[dest] = txBytes[src];
- txPackets[dest] = txPackets[src];
- operations[dest] = operations[src];
- }
-
- /** @hide */
- public long getElapsedRealtime() {
- return elapsedRealtime;
- }
-
- /** @hide */
- public void setElapsedRealtime(long time) {
- elapsedRealtime = time;
- }
-
- /**
- * Return age of this {@link NetworkStats} object with respect to
- * {@link SystemClock#elapsedRealtime()}.
- * @hide
- */
- public long getElapsedRealtimeAge() {
- return SystemClock.elapsedRealtime() - elapsedRealtime;
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public int size() {
- return size;
- }
-
- /** @hide */
- @VisibleForTesting
- public int internalSize() {
- return capacity;
- }
-
- /** @hide */
- @Deprecated
- public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
- long txBytes, long txPackets, long operations) {
- return combineValues(
- iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes,
- txPackets, operations);
- }
-
- /** @hide */
- public NetworkStats combineValues(String iface, int uid, int set, int tag,
- long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
- return combineValues(new Entry(
- iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
- }
-
- /**
- * Combine given values with an existing row, or create a new row if
- * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
- * also be used to subtract values from existing rows. This method mutates the referencing
- * {@link NetworkStats} object.
- *
- * @param entry the {@link Entry} to combine.
- * @return a reference to this mutated {@link NetworkStats} object.
- * @hide
- */
- public @NonNull NetworkStats combineValues(@NonNull Entry entry) {
- final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
- entry.roaming, entry.defaultNetwork);
- if (i == -1) {
- // only create new entry when positive contribution
- insertEntry(entry);
- } else {
- rxBytes[i] += entry.rxBytes;
- rxPackets[i] += entry.rxPackets;
- txBytes[i] += entry.txBytes;
- txPackets[i] += entry.txPackets;
- operations[i] += entry.operations;
- }
- return this;
- }
-
- /**
- * Add given values with an existing row, or create a new row if
- * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
- * also be used to subtract values from existing rows.
- *
- * @param entry the {@link Entry} to add.
- * @return a new constructed {@link NetworkStats} object that contains the result.
- */
- public @NonNull NetworkStats addEntry(@NonNull Entry entry) {
- return this.clone().combineValues(entry);
- }
-
- /**
- * Add the given {@link NetworkStats} objects.
- *
- * @return the sum of two objects.
- */
- public @NonNull NetworkStats add(@NonNull NetworkStats another) {
- final NetworkStats ret = this.clone();
- ret.combineAllValues(another);
- return ret;
- }
-
- /**
- * Combine all values from another {@link NetworkStats} into this object.
- * @hide
- */
- public void combineAllValues(@NonNull NetworkStats another) {
- NetworkStats.Entry entry = null;
- for (int i = 0; i < another.size; i++) {
- entry = another.getValues(i, entry);
- combineValues(entry);
- }
- }
-
- /**
- * Find first stats index that matches the requested parameters.
- * @hide
- */
- public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming,
- int defaultNetwork) {
- for (int i = 0; i < size; i++) {
- if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
- && metered == this.metered[i] && roaming == this.roaming[i]
- && defaultNetwork == this.defaultNetwork[i]
- && Objects.equals(iface, this.iface[i])) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Find first stats index that matches the requested parameters, starting
- * search around the hinted index as an optimization.
- * @hide
- */
- @VisibleForTesting
- public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
- int defaultNetwork, int hintIndex) {
- for (int offset = 0; offset < size; offset++) {
- final int halfOffset = offset / 2;
-
- // search outwards from hint index, alternating forward and backward
- final int i;
- if (offset % 2 == 0) {
- i = (hintIndex + halfOffset) % size;
- } else {
- i = (size + hintIndex - halfOffset - 1) % size;
- }
-
- if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
- && metered == this.metered[i] && roaming == this.roaming[i]
- && defaultNetwork == this.defaultNetwork[i]
- && Objects.equals(iface, this.iface[i])) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Splice in {@link #operations} from the given {@link NetworkStats} based
- * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
- * since operation counts are at data layer.
- * @hide
- */
- public void spliceOperationsFrom(NetworkStats stats) {
- for (int i = 0; i < size; i++) {
- final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i],
- defaultNetwork[i]);
- if (j == -1) {
- operations[i] = 0;
- } else {
- operations[i] = stats.operations[j];
- }
- }
- }
-
- /**
- * Return list of unique interfaces known by this data structure.
- * @hide
- */
- public String[] getUniqueIfaces() {
- final HashSet<String> ifaces = new HashSet<String>();
- for (String iface : this.iface) {
- if (iface != IFACE_ALL) {
- ifaces.add(iface);
- }
- }
- return ifaces.toArray(new String[ifaces.size()]);
- }
-
- /**
- * Return list of unique UIDs known by this data structure.
- * @hide
- */
- @UnsupportedAppUsage
- public int[] getUniqueUids() {
- final SparseBooleanArray uids = new SparseBooleanArray();
- for (int uid : this.uid) {
- uids.put(uid, true);
- }
-
- final int size = uids.size();
- final int[] result = new int[size];
- for (int i = 0; i < size; i++) {
- result[i] = uids.keyAt(i);
- }
- return result;
- }
-
- /**
- * Return total bytes represented by this snapshot object, usually used when
- * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
- * @hide
- */
- @UnsupportedAppUsage
- public long getTotalBytes() {
- final Entry entry = getTotal(null);
- return entry.rxBytes + entry.txBytes;
- }
-
- /**
- * Return total of all fields represented by this snapshot object.
- * @hide
- */
- @UnsupportedAppUsage
- public Entry getTotal(Entry recycle) {
- return getTotal(recycle, null, UID_ALL, false);
- }
-
- /**
- * Return total of all fields represented by this snapshot object matching
- * the requested {@link #uid}.
- * @hide
- */
- @UnsupportedAppUsage
- public Entry getTotal(Entry recycle, int limitUid) {
- return getTotal(recycle, null, limitUid, false);
- }
-
- /**
- * Return total of all fields represented by this snapshot object matching
- * the requested {@link #iface}.
- * @hide
- */
- public Entry getTotal(Entry recycle, HashSet<String> limitIface) {
- return getTotal(recycle, limitIface, UID_ALL, false);
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public Entry getTotalIncludingTags(Entry recycle) {
- return getTotal(recycle, null, UID_ALL, true);
- }
-
- /**
- * Return total of all fields represented by this snapshot object matching
- * the requested {@link #iface} and {@link #uid}.
- *
- * @param limitIface Set of {@link #iface} to include in total; or {@code
- * null} to include all ifaces.
- */
- private Entry getTotal(
- Entry recycle, HashSet<String> limitIface, int limitUid, boolean includeTags) {
- final Entry entry = recycle != null ? recycle : new Entry();
-
- entry.iface = IFACE_ALL;
- entry.uid = limitUid;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.metered = METERED_ALL;
- entry.roaming = ROAMING_ALL;
- entry.defaultNetwork = DEFAULT_NETWORK_ALL;
- entry.rxBytes = 0;
- entry.rxPackets = 0;
- entry.txBytes = 0;
- entry.txPackets = 0;
- entry.operations = 0;
-
- for (int i = 0; i < size; i++) {
- final boolean matchesUid = (limitUid == UID_ALL) || (limitUid == uid[i]);
- final boolean matchesIface = (limitIface == null) || (limitIface.contains(iface[i]));
-
- if (matchesUid && matchesIface) {
- // skip specific tags, since already counted in TAG_NONE
- if (tag[i] != TAG_NONE && !includeTags) continue;
-
- entry.rxBytes += rxBytes[i];
- entry.rxPackets += rxPackets[i];
- entry.txBytes += txBytes[i];
- entry.txPackets += txPackets[i];
- entry.operations += operations[i];
- }
- }
- return entry;
- }
-
- /**
- * Fast path for battery stats.
- * @hide
- */
- public long getTotalPackets() {
- long total = 0;
- for (int i = size-1; i >= 0; i--) {
- total += rxPackets[i] + txPackets[i];
- }
- return total;
- }
-
- /**
- * Subtract the given {@link NetworkStats}, effectively leaving the delta
- * between two snapshots in time. Assumes that statistics rows collect over
- * time, and that none of them have disappeared. This method does not mutate
- * the referencing object.
- *
- * @return the delta between two objects.
- */
- public @NonNull NetworkStats subtract(@NonNull NetworkStats right) {
- return subtract(this, right, null, null);
- }
-
- /**
- * Subtract the two given {@link NetworkStats} objects, returning the delta
- * between two snapshots in time. Assumes that statistics rows collect over
- * time, and that none of them have disappeared.
- * <p>
- * If counters have rolled backwards, they are clamped to {@code 0} and
- * reported to the given {@link NonMonotonicObserver}.
- * @hide
- */
- public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
- NonMonotonicObserver<C> observer, C cookie) {
- return subtract(left, right, observer, cookie, null);
- }
-
- /**
- * Subtract the two given {@link NetworkStats} objects, returning the delta
- * between two snapshots in time. Assumes that statistics rows collect over
- * time, and that none of them have disappeared.
- * <p>
- * If counters have rolled backwards, they are clamped to {@code 0} and
- * reported to the given {@link NonMonotonicObserver}.
- * <p>
- * If <var>recycle</var> is supplied, this NetworkStats object will be
- * reused (and returned) as the result if it is large enough to contain
- * the data.
- * @hide
- */
- public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
- NonMonotonicObserver<C> observer, C cookie, NetworkStats recycle) {
- long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime;
- if (deltaRealtime < 0) {
- if (observer != null) {
- observer.foundNonMonotonic(left, -1, right, -1, cookie);
- }
- deltaRealtime = 0;
- }
-
- // result will have our rows, and elapsed time between snapshots
- final Entry entry = new Entry();
- final NetworkStats result;
- if (recycle != null && recycle.capacity >= left.size) {
- result = recycle;
- result.size = 0;
- result.elapsedRealtime = deltaRealtime;
- } else {
- result = new NetworkStats(deltaRealtime, left.size);
- }
- for (int i = 0; i < left.size; i++) {
- entry.iface = left.iface[i];
- entry.uid = left.uid[i];
- entry.set = left.set[i];
- entry.tag = left.tag[i];
- entry.metered = left.metered[i];
- entry.roaming = left.roaming[i];
- entry.defaultNetwork = left.defaultNetwork[i];
- entry.rxBytes = left.rxBytes[i];
- entry.rxPackets = left.rxPackets[i];
- entry.txBytes = left.txBytes[i];
- entry.txPackets = left.txPackets[i];
- entry.operations = left.operations[i];
-
- // find remote row that matches, and subtract
- final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
- entry.metered, entry.roaming, entry.defaultNetwork, i);
- if (j != -1) {
- // Found matching row, subtract remote value.
- entry.rxBytes -= right.rxBytes[j];
- entry.rxPackets -= right.rxPackets[j];
- entry.txBytes -= right.txBytes[j];
- entry.txPackets -= right.txPackets[j];
- entry.operations -= right.operations[j];
- }
-
- if (entry.isNegative()) {
- if (observer != null) {
- observer.foundNonMonotonic(left, i, right, j, cookie);
- }
- entry.rxBytes = Math.max(entry.rxBytes, 0);
- entry.rxPackets = Math.max(entry.rxPackets, 0);
- entry.txBytes = Math.max(entry.txBytes, 0);
- entry.txPackets = Math.max(entry.txPackets, 0);
- entry.operations = Math.max(entry.operations, 0);
- }
-
- result.insertEntry(entry);
- }
-
- return result;
- }
-
- /**
- * Calculate and apply adjustments to captured statistics for 464xlat traffic.
- *
- * <p>This mutates stacked traffic stats, to account for IPv4/IPv6 header size difference.
- *
- * <p>UID stats, which are only accounted on the stacked interface, need to be increased
- * by 20 bytes/packet to account for translation overhead.
- *
- * <p>The potential additional overhead of 8 bytes/packet for ip fragments is ignored.
- *
- * <p>Interface stats need to sum traffic on both stacked and base interface because:
- * - eBPF offloaded packets appear only on the stacked interface
- * - Non-offloaded ingress packets appear only on the stacked interface
- * (due to iptables raw PREROUTING drop rules)
- * - Non-offloaded egress packets appear only on the stacked interface
- * (due to ignoring traffic from clat daemon by uid match)
- * (and of course the 20 bytes/packet overhead needs to be applied to stacked interface stats)
- *
- * <p>This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only
- * {@code ConcurrentHashMap}
- * @param baseTraffic Traffic on the base interfaces. Will be mutated.
- * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
- * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
- * @hide
- */
- public static void apply464xlatAdjustments(NetworkStats baseTraffic,
- NetworkStats stackedTraffic, Map<String, String> stackedIfaces) {
- // For recycling
- Entry entry = null;
- for (int i = 0; i < stackedTraffic.size; i++) {
- entry = stackedTraffic.getValues(i, entry);
- if (entry == null) continue;
- if (entry.iface == null) continue;
- if (!entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) continue;
-
- // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet
- // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after
- // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes
- // difference for all packets (http://b/12249687, http:/b/33681750).
- //
- // Note: this doesn't account for LRO/GRO/GSO/TSO (ie. >mtu) traffic correctly, nor
- // does it correctly account for the 8 extra bytes in the IPv6 fragmentation header.
- //
- // While the ebpf code path does try to simulate proper post segmentation packet
- // counts, we have nothing of the sort of xt_qtaguid stats.
- entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA;
- entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA;
- stackedTraffic.setValues(i, entry);
- }
- }
-
- /**
- * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice.
- *
- * <p>This mutates the object this method is called on. Equivalent to calling
- * {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as
- * base and stacked traffic.
- * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
- * @hide
- */
- public void apply464xlatAdjustments(Map<String, String> stackedIfaces) {
- apply464xlatAdjustments(this, this, stackedIfaces);
- }
-
- /**
- * Return total statistics grouped by {@link #iface}; doesn't mutate the
- * original structure.
- * @hide
- */
- public NetworkStats groupedByIface() {
- final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
-
- final Entry entry = new Entry();
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.metered = METERED_ALL;
- entry.roaming = ROAMING_ALL;
- entry.defaultNetwork = DEFAULT_NETWORK_ALL;
- entry.operations = 0L;
-
- for (int i = 0; i < size; i++) {
- // skip specific tags, since already counted in TAG_NONE
- if (tag[i] != TAG_NONE) continue;
-
- entry.iface = iface[i];
- entry.rxBytes = rxBytes[i];
- entry.rxPackets = rxPackets[i];
- entry.txBytes = txBytes[i];
- entry.txPackets = txPackets[i];
- stats.combineValues(entry);
- }
-
- return stats;
- }
-
- /**
- * Return total statistics grouped by {@link #uid}; doesn't mutate the
- * original structure.
- * @hide
- */
- public NetworkStats groupedByUid() {
- final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
-
- final Entry entry = new Entry();
- entry.iface = IFACE_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.metered = METERED_ALL;
- entry.roaming = ROAMING_ALL;
- entry.defaultNetwork = DEFAULT_NETWORK_ALL;
-
- for (int i = 0; i < size; i++) {
- // skip specific tags, since already counted in TAG_NONE
- if (tag[i] != TAG_NONE) continue;
-
- entry.uid = uid[i];
- entry.rxBytes = rxBytes[i];
- entry.rxPackets = rxPackets[i];
- entry.txBytes = txBytes[i];
- entry.txPackets = txPackets[i];
- entry.operations = operations[i];
- stats.combineValues(entry);
- }
-
- return stats;
- }
-
- /**
- * Remove all rows that match one of specified UIDs.
- * This mutates the original structure in place.
- * @hide
- */
- public void removeUids(int[] uids) {
- filter(e -> !CollectionUtils.contains(uids, e.uid));
- }
-
- /**
- * Remove all rows that match one of specified UIDs.
- * @return the result object.
- * @hide
- */
- @NonNull
- public NetworkStats removeEmptyEntries() {
- final NetworkStats ret = this.clone();
- ret.filter(e -> e.rxBytes != 0 || e.rxPackets != 0 || e.txBytes != 0 || e.txPackets != 0
- || e.operations != 0);
- return ret;
- }
-
- /**
- * Only keep entries that match all specified filters.
- *
- * <p>This mutates the original structure in place. After this method is called,
- * size is the number of matching entries, and capacity is the previous capacity.
- * @param limitUid UID to filter for, or {@link #UID_ALL}.
- * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}.
- * @param limitTag Tag to filter for, or {@link #TAG_ALL}.
- * @hide
- */
- public void filter(int limitUid, String[] limitIfaces, int limitTag) {
- if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
- return;
- }
- filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
- && (limitTag == TAG_ALL || limitTag == e.tag)
- && (limitIfaces == INTERFACES_ALL
- || CollectionUtils.contains(limitIfaces, e.iface)));
- }
-
- /**
- * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
- *
- * <p>This mutates the original structure in place.
- * @hide
- */
- public void filterDebugEntries() {
- filter(e -> e.set < SET_DEBUG_START);
- }
-
- private void filter(Predicate<Entry> predicate) {
- Entry entry = new Entry();
- int nextOutputEntry = 0;
- for (int i = 0; i < size; i++) {
- entry = getValues(i, entry);
- if (predicate.test(entry)) {
- if (nextOutputEntry != i) {
- setValues(nextOutputEntry, entry);
- }
- nextOutputEntry++;
- }
- }
- size = nextOutputEntry;
- }
-
- /** @hide */
- public void dump(String prefix, PrintWriter pw) {
- pw.print(prefix);
- pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
- for (int i = 0; i < size; i++) {
- pw.print(prefix);
- pw.print(" ["); pw.print(i); pw.print("]");
- pw.print(" iface="); pw.print(iface[i]);
- pw.print(" uid="); pw.print(uid[i]);
- pw.print(" set="); pw.print(setToString(set[i]));
- pw.print(" tag="); pw.print(tagToString(tag[i]));
- pw.print(" metered="); pw.print(meteredToString(metered[i]));
- pw.print(" roaming="); pw.print(roamingToString(roaming[i]));
- pw.print(" defaultNetwork="); pw.print(defaultNetworkToString(defaultNetwork[i]));
- pw.print(" rxBytes="); pw.print(rxBytes[i]);
- pw.print(" rxPackets="); pw.print(rxPackets[i]);
- pw.print(" txBytes="); pw.print(txBytes[i]);
- pw.print(" txPackets="); pw.print(txPackets[i]);
- pw.print(" operations="); pw.println(operations[i]);
- }
- }
-
- /**
- * Return text description of {@link #set} value.
- * @hide
- */
- public static String setToString(int set) {
- switch (set) {
- case SET_ALL:
- return "ALL";
- case SET_DEFAULT:
- return "DEFAULT";
- case SET_FOREGROUND:
- return "FOREGROUND";
- case SET_DBG_VPN_IN:
- return "DBG_VPN_IN";
- case SET_DBG_VPN_OUT:
- return "DBG_VPN_OUT";
- default:
- return "UNKNOWN";
- }
- }
-
- /**
- * Return text description of {@link #set} value.
- * @hide
- */
- public static String setToCheckinString(int set) {
- switch (set) {
- case SET_ALL:
- return "all";
- case SET_DEFAULT:
- return "def";
- case SET_FOREGROUND:
- return "fg";
- case SET_DBG_VPN_IN:
- return "vpnin";
- case SET_DBG_VPN_OUT:
- return "vpnout";
- default:
- return "unk";
- }
- }
-
- /**
- * @return true if the querySet matches the dataSet.
- * @hide
- */
- public static boolean setMatches(int querySet, int dataSet) {
- if (querySet == dataSet) {
- return true;
- }
- // SET_ALL matches all non-debugging sets.
- return querySet == SET_ALL && dataSet < SET_DEBUG_START;
- }
-
- /**
- * Return text description of {@link #tag} value.
- * @hide
- */
- public static String tagToString(int tag) {
- return "0x" + Integer.toHexString(tag);
- }
-
- /**
- * Return text description of {@link #metered} value.
- * @hide
- */
- public static String meteredToString(int metered) {
- switch (metered) {
- case METERED_ALL:
- return "ALL";
- case METERED_NO:
- return "NO";
- case METERED_YES:
- return "YES";
- default:
- return "UNKNOWN";
- }
- }
-
- /**
- * Return text description of {@link #roaming} value.
- * @hide
- */
- public static String roamingToString(int roaming) {
- switch (roaming) {
- case ROAMING_ALL:
- return "ALL";
- case ROAMING_NO:
- return "NO";
- case ROAMING_YES:
- return "YES";
- default:
- return "UNKNOWN";
- }
- }
-
- /**
- * Return text description of {@link #defaultNetwork} value.
- * @hide
- */
- public static String defaultNetworkToString(int defaultNetwork) {
- switch (defaultNetwork) {
- case DEFAULT_NETWORK_ALL:
- return "ALL";
- case DEFAULT_NETWORK_NO:
- return "NO";
- case DEFAULT_NETWORK_YES:
- return "YES";
- default:
- return "UNKNOWN";
- }
- }
-
- /** @hide */
- @Override
- public String toString() {
- final CharArrayWriter writer = new CharArrayWriter();
- dump("", new PrintWriter(writer));
- return writer.toString();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
- @Override
- public NetworkStats createFromParcel(Parcel in) {
- return new NetworkStats(in);
- }
-
- @Override
- public NetworkStats[] newArray(int size) {
- return new NetworkStats[size];
- }
- };
-
- /** @hide */
- public interface NonMonotonicObserver<C> {
- public void foundNonMonotonic(
- NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
- public void foundNonMonotonic(
- NetworkStats stats, int statsIndex, C cookie);
- }
-
- /**
- * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface.
- *
- * <p>This method should only be called on delta NetworkStats. Do not call this method on a
- * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change
- * over time.
- *
- * <p>This method performs adjustments for one active VPN package and one VPN iface at a time.
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @hide
- */
- public void migrateTun(int tunUid, @NonNull String tunIface,
- @NonNull List<String> underlyingIfaces) {
- // Combined usage by all apps using VPN.
- final Entry tunIfaceTotal = new Entry();
- // Usage by VPN, grouped by its {@code underlyingIfaces}.
- final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.size()];
- // Usage by VPN, summed across all its {@code underlyingIfaces}.
- final Entry underlyingIfacesTotal = new Entry();
-
- for (int i = 0; i < perInterfaceTotal.length; i++) {
- perInterfaceTotal[i] = new Entry();
- }
-
- tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal,
- underlyingIfacesTotal);
-
- // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app.
- // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression.
- // Negative stats should be avoided.
- final Entry[] moved =
- addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal,
- perInterfaceTotal, underlyingIfacesTotal);
- deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved);
- }
-
- /**
- * Initializes the data used by the migrateTun() method.
- *
- * <p>This is the first pass iteration which does the following work:
- *
- * <ul>
- * <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and
- * background).
- * <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
- * </ul>
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN
- * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code
- * underlyingIfaces}
- * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its
- * {@code underlyingIfaces}
- */
- private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
- @NonNull List<String> underlyingIfaces, @NonNull Entry tunIfaceTotal,
- @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
- final Entry recycle = new Entry();
- for (int i = 0; i < size; i++) {
- getValues(i, recycle);
- if (recycle.uid == UID_ALL) {
- throw new IllegalStateException(
- "Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
- }
- if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
- throw new IllegalStateException(
- "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
- }
- if (recycle.tag != TAG_NONE) {
- // TODO(b/123666283): Take all tags for tunUid into account.
- continue;
- }
-
- if (tunUid == Process.SYSTEM_UID) {
- // Kernel-based VPN or VCN, traffic sent by apps on the VPN/VCN network
- //
- // Since the data is not UID-accounted on underlying networks, just use VPN/VCN
- // network usage as ground truth. Encrypted traffic on the underlying networks will
- // never be processed here because encrypted traffic on the underlying interfaces
- // is not present in UID stats, and this method is only called on UID stats.
- if (tunIface.equals(recycle.iface)) {
- tunIfaceTotal.add(recycle);
- underlyingIfacesTotal.add(recycle);
-
- // In steady state, there should always be one network, but edge cases may
- // result in the network being null (network lost), and thus no underlying
- // ifaces is possible.
- if (perInterfaceTotal.length > 0) {
- // While platform VPNs and VCNs have exactly one underlying network, that
- // network may have multiple interfaces (eg for 464xlat). This layer does
- // not have the required information to identify which of the interfaces
- // were used. Select "any" of the interfaces. Since overhead is already
- // lost, this number is an approximation anyways.
- perInterfaceTotal[0].add(recycle);
- }
- }
- } else if (recycle.uid == tunUid) {
- // VpnService VPN, traffic sent by the VPN app over underlying networks
- for (int j = 0; j < underlyingIfaces.size(); j++) {
- if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) {
- perInterfaceTotal[j].add(recycle);
- underlyingIfacesTotal.add(recycle);
- break;
- }
- }
- } else if (tunIface.equals(recycle.iface)) {
- // VpnService VPN; traffic sent by apps on the VPN network
- tunIfaceTotal.add(recycle);
- }
- }
- }
-
- /**
- * Distributes traffic across apps that are using given {@code tunIface}, and returns the total
- * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}.
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @param tunIfaceTotal combined data usage across all apps using {@code tunIface}
- * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces}
- * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code
- * underlyingIfaces}
- */
- private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
- @NonNull List<String> underlyingIfaces, @NonNull Entry tunIfaceTotal,
- @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
- // Traffic that should be moved off of each underlying interface for tunUid (see
- // deductTrafficFromVpnApp below).
- final Entry[] moved = new Entry[underlyingIfaces.size()];
- for (int i = 0; i < underlyingIfaces.size(); i++) {
- moved[i] = new Entry();
- }
-
- final Entry tmpEntry = new Entry();
- final int origSize = size;
- for (int i = 0; i < origSize; i++) {
- if (!Objects.equals(iface[i], tunIface)) {
- // Consider only entries that go onto the VPN interface.
- continue;
- }
-
- if (uid[i] == tunUid && tunUid != Process.SYSTEM_UID) {
- // Exclude VPN app from the redistribution, as it can choose to create packet
- // streams by writing to itself.
- //
- // However, for platform VPNs, do not exclude the system's usage of the VPN network,
- // since it is never local-only, and never double counted
- continue;
- }
- tmpEntry.uid = uid[i];
- tmpEntry.tag = tag[i];
- tmpEntry.metered = metered[i];
- tmpEntry.roaming = roaming[i];
- tmpEntry.defaultNetwork = defaultNetwork[i];
-
- // In a first pass, compute this entry's total share of data across all
- // underlyingIfaces. This is computed on the basis of the share of this entry's usage
- // over tunIface.
- // TODO: Consider refactoring first pass into a separate helper method.
- long totalRxBytes = 0;
- if (tunIfaceTotal.rxBytes > 0) {
- // Note - The multiplication below should not overflow since NetworkStatsService
- // processes this every time device has transmitted/received amount equivalent to
- // global threshold alert (~ 2MB) across all interfaces.
- final long rxBytesAcrossUnderlyingIfaces =
- 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 =
- multiplySafeByRational(underlyingIfacesTotal.rxPackets,
- rxPackets[i], tunIfaceTotal.rxPackets);
- totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
- }
- long totalTxBytes = 0;
- if (tunIfaceTotal.txBytes > 0) {
- final long txBytesAcrossUnderlyingIfaces =
- multiplySafeByRational(underlyingIfacesTotal.txBytes,
- txBytes[i], tunIfaceTotal.txBytes);
- totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
- }
- long totalTxPackets = 0;
- if (tunIfaceTotal.txPackets > 0) {
- final long txPacketsAcrossUnderlyingIfaces =
- multiplySafeByRational(underlyingIfacesTotal.txPackets,
- txPackets[i], tunIfaceTotal.txPackets);
- totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
- }
- long totalOperations = 0;
- if (tunIfaceTotal.operations > 0) {
- final long operationsAcrossUnderlyingIfaces =
- 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
- // each interface represents of the total traffic of the underlying interfaces.
- for (int j = 0; j < underlyingIfaces.size(); j++) {
- tmpEntry.iface = underlyingIfaces.get(j);
- tmpEntry.rxBytes = 0;
- // Reset 'set' to correct value since it gets updated when adding debug info below.
- tmpEntry.set = set[i];
- if (underlyingIfacesTotal.rxBytes > 0) {
- tmpEntry.rxBytes =
- multiplySafeByRational(totalRxBytes,
- perInterfaceTotal[j].rxBytes,
- underlyingIfacesTotal.rxBytes);
- }
- tmpEntry.rxPackets = 0;
- if (underlyingIfacesTotal.rxPackets > 0) {
- tmpEntry.rxPackets =
- multiplySafeByRational(totalRxPackets,
- perInterfaceTotal[j].rxPackets,
- underlyingIfacesTotal.rxPackets);
- }
- tmpEntry.txBytes = 0;
- if (underlyingIfacesTotal.txBytes > 0) {
- tmpEntry.txBytes =
- multiplySafeByRational(totalTxBytes,
- perInterfaceTotal[j].txBytes,
- underlyingIfacesTotal.txBytes);
- }
- tmpEntry.txPackets = 0;
- if (underlyingIfacesTotal.txPackets > 0) {
- tmpEntry.txPackets =
- multiplySafeByRational(totalTxPackets,
- perInterfaceTotal[j].txPackets,
- underlyingIfacesTotal.txPackets);
- }
- tmpEntry.operations = 0;
- if (underlyingIfacesTotal.operations > 0) {
- tmpEntry.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.
- combineValues(tmpEntry);
- if (tag[i] == TAG_NONE) {
- // Add the migrated data to moved so it is deducted from the VPN app later.
- moved[j].add(tmpEntry);
- // Add debug info
- tmpEntry.set = SET_DBG_VPN_IN;
- combineValues(tmpEntry);
- }
- }
- }
- return moved;
- }
-
- private void deductTrafficFromVpnApp(
- int tunUid,
- @NonNull List<String> underlyingIfaces,
- @NonNull Entry[] moved) {
- if (tunUid == Process.SYSTEM_UID) {
- // No traffic recorded on a per-UID basis for in-kernel VPN/VCNs over underlying
- // networks; thus no traffic to deduct.
- return;
- }
-
- for (int i = 0; i < underlyingIfaces.size(); i++) {
- moved[i].uid = tunUid;
- // Add debug info
- moved[i].set = SET_DBG_VPN_OUT;
- moved[i].tag = TAG_NONE;
- moved[i].iface = underlyingIfaces.get(i);
- moved[i].metered = METERED_ALL;
- moved[i].roaming = ROAMING_ALL;
- moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
- combineValues(moved[i]);
-
- // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
- // the TAG_NONE traffic.
- //
- // Relies on the fact that the underlying traffic only has state ROAMING_NO and
- // METERED_NO, which should be the case as it comes directly from the /proc file.
- // We only blend in the roaming data after applying these adjustments, by checking the
- // NetworkIdentity of the underlying iface.
- final int idxVpnBackground = findIndex(underlyingIfaces.get(i), tunUid, SET_DEFAULT,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnBackground != -1) {
- // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
- // from foreground usage.
- tunSubtract(idxVpnBackground, this, moved[i]);
- }
-
- final int idxVpnForeground = findIndex(underlyingIfaces.get(i), tunUid, SET_FOREGROUND,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnForeground != -1) {
- tunSubtract(idxVpnForeground, this, moved[i]);
- }
- }
- }
-
- private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) {
- long rxBytes = Math.min(left.rxBytes[i], right.rxBytes);
- left.rxBytes[i] -= rxBytes;
- right.rxBytes -= rxBytes;
-
- long rxPackets = Math.min(left.rxPackets[i], right.rxPackets);
- left.rxPackets[i] -= rxPackets;
- right.rxPackets -= rxPackets;
-
- long txBytes = Math.min(left.txBytes[i], right.txBytes);
- left.txBytes[i] -= txBytes;
- right.txBytes -= txBytes;
-
- long txPackets = Math.min(left.txPackets[i], right.txPackets);
- left.txPackets[i] -= txPackets;
- right.txPackets -= txPackets;
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
deleted file mode 100644
index b64fbdb..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2015 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.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;
-
-import android.Manifest;
-import android.annotation.IntDef;
-import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.Process;
-import android.os.UserHandle;
-import android.telephony.TelephonyManager;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Utility methods for controlling access to network stats APIs.
- *
- * @hide
- */
-public final class NetworkStatsAccess {
- private NetworkStatsAccess() {}
-
- /**
- * Represents an access level for the network usage history and statistics APIs.
- *
- * <p>Access levels are in increasing order; that is, it is reasonable to check access by
- * verifying that the caller's access level is at least the minimum required level.
- */
- @IntDef({
- Level.DEFAULT,
- Level.USER,
- Level.DEVICESUMMARY,
- Level.DEVICE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Level {
- /**
- * Default, unprivileged access level.
- *
- * <p>Can only access usage for one's own UID.
- *
- * <p>Every app will have at least this access level.
- */
- int DEFAULT = 0;
-
- /**
- * Access level for apps which can access usage for any app running in the same user.
- *
- * <p>Granted to:
- * <ul>
- * <li>Profile owners.
- * </ul>
- */
- int USER = 1;
-
- /**
- * Access level for apps which can access usage summary of device. Device summary includes
- * usage by apps running in any profiles/users, however this access level does not
- * allow querying usage of individual apps running in other profiles/users.
- *
- * <p>Granted to:
- * <ul>
- * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
- * so it is not necessarily sufficient to declare this in the manifest.
- * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
- * </ul>
- */
- int DEVICESUMMARY = 2;
-
- /**
- * Access level for apps which can access usage for any app on the device, including apps
- * running on other users/profiles.
- *
- * <p>Granted to:
- * <ul>
- * <li>Device owners.
- * <li>Carrier-privileged applications.
- * <li>The system UID.
- * </ul>
- */
- int DEVICE = 3;
- }
-
- /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
- public static @NetworkStatsAccess.Level int checkAccessLevel(
- 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;
- final long token = Binder.clearCallingIdentity();
- try {
- hasCarrierPrivileges = tm != null
- && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- 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 || 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;
- }
-
- boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
- if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
- READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
- return NetworkStatsAccess.Level.DEVICESUMMARY;
- }
-
- //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
- 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.
- return NetworkStatsAccess.Level.USER;
- }
-
- // Everyone else gets default access (only to their own UID).
- return NetworkStatsAccess.Level.DEFAULT;
- }
-
- /**
- * Returns whether the given caller should be able to access the given UID when the caller has
- * the given {@link NetworkStatsAccess.Level}.
- */
- 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.
- return true;
- case NetworkStatsAccess.Level.DEVICESUMMARY:
- // Can access usage for any app running in the same user, along
- // with some special uids (system, removed, or tethering) and
- // anonymized uids
- return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
- || uid == UID_TETHERING || uid == UID_ALL
- || 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
- || userId == callerUserId;
- case NetworkStatsAccess.Level.DEFAULT:
- default:
- // Default access level - can only access one's own usage.
- return uid == callerUid;
- }
- }
-
- private static boolean hasAppOpsPermission(
- Context context, int callingUid, String callingPackage) {
- if (callingPackage != null) {
- AppOpsManager appOps = (AppOpsManager) context.getSystemService(
- Context.APP_OPS_SERVICE);
-
- 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.
- final int permissionCheck = context.checkCallingPermission(
- Manifest.permission.PACKAGE_USAGE_STATS);
- return permissionCheck == PackageManager.PERMISSION_GRANTED;
- }
- return (mode == AppOpsManager.MODE_ALLOWED);
- }
- return false;
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
deleted file mode 100644
index 1ddc78b..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
+++ /dev/null
@@ -1,956 +0,0 @@
-/*
- * Copyright (C) 2012 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.NetworkStats.DEFAULT_NETWORK_NO;
-import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.ROAMING_YES;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.UID_REMOVED;
-import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-
-import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.net.NetworkStats.State;
-import android.net.NetworkStatsHistory.Entry;
-import android.os.Binder;
-import android.service.NetworkStatsCollectionKeyProto;
-import android.service.NetworkStatsCollectionProto;
-import android.service.NetworkStatsCollectionStatsProto;
-import android.telephony.SubscriptionPlan;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.AtomicFile;
-import android.util.IndentingPrintWriter;
-import android.util.Log;
-import android.util.Range;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FileRotator;
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import libcore.io.IoUtils;
-
-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;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.ProtocolException;
-import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Collection of {@link NetworkStatsHistory}, stored based on combined key of
- * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-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;
-
- private static final int VERSION_NETWORK_INIT = 1;
-
- private static final int VERSION_UID_INIT = 1;
- private static final int VERSION_UID_WITH_IDENT = 2;
- private static final int VERSION_UID_WITH_TAG = 3;
- private static final int VERSION_UID_WITH_SET = 4;
-
- private static final int VERSION_UNIFIED_INIT = 16;
-
- private ArrayMap<Key, NetworkStatsHistory> mStats = new ArrayMap<>();
-
- private final long mBucketDurationMillis;
-
- private long mStartMillis;
- private long mEndMillis;
- private long mTotalBytes;
- private boolean mDirty;
-
- /**
- * Construct a {@link NetworkStatsCollection} object.
- *
- * @param bucketDuration duration of the buckets in this object, in milliseconds.
- * @hide
- */
- public NetworkStatsCollection(long bucketDurationMillis) {
- mBucketDurationMillis = bucketDurationMillis;
- reset();
- }
-
- /** @hide */
- public void clear() {
- reset();
- }
-
- /** @hide */
- public void reset() {
- mStats.clear();
- mStartMillis = Long.MAX_VALUE;
- mEndMillis = Long.MIN_VALUE;
- mTotalBytes = 0;
- mDirty = false;
- }
-
- /** @hide */
- public long getStartMillis() {
- return mStartMillis;
- }
-
- /**
- * Return first atomic bucket in this collection, which is more conservative
- * than {@link #mStartMillis}.
- * @hide
- */
- public long getFirstAtomicBucketMillis() {
- if (mStartMillis == Long.MAX_VALUE) {
- return Long.MAX_VALUE;
- } else {
- return mStartMillis + mBucketDurationMillis;
- }
- }
-
- /** @hide */
- public long getEndMillis() {
- return mEndMillis;
- }
-
- /** @hide */
- public long getTotalBytes() {
- return mTotalBytes;
- }
-
- /** @hide */
- public boolean isDirty() {
- return mDirty;
- }
-
- /** @hide */
- public void clearDirty() {
- mDirty = false;
- }
-
- /** @hide */
- public boolean isEmpty() {
- return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
- }
-
- /** @hide */
- @VisibleForTesting
- public long roundUp(long time) {
- if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
- || time == SubscriptionPlan.TIME_UNKNOWN) {
- return time;
- } else {
- final long mod = time % mBucketDurationMillis;
- if (mod > 0) {
- time -= mod;
- time += mBucketDurationMillis;
- }
- return time;
- }
- }
-
- /** @hide */
- @VisibleForTesting
- public long roundDown(long time) {
- if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
- || time == SubscriptionPlan.TIME_UNKNOWN) {
- return time;
- } else {
- final long mod = time % mBucketDurationMillis;
- if (mod > 0) {
- time -= mod;
- }
- return time;
- }
- }
-
- /** @hide */
- public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
- return getRelevantUids(accessLevel, Binder.getCallingUid());
- }
-
- /** @hide */
- public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
- final int callerUid) {
- 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 = Collections.binarySearch(uids, new Integer(key.uid));
-
- if (j < 0) {
- j = ~j;
- uids.add(j, key.uid);
- }
- }
- }
- return CollectionUtils.toIntArray(uids);
- }
-
- /**
- * Combine all {@link NetworkStatsHistory} in this collection which match
- * the requested parameters.
- * @hide
- */
- public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan,
- int uid, int set, int tag, int fields, long start, long end,
- @NetworkStatsAccess.Level int accessLevel, int callerUid) {
- if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) {
- throw new SecurityException("Network stats history of uid " + uid
- + " is forbidden for caller " + callerUid);
- }
-
- // 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) NetworkStatsUtils.constrain(
- ((end - start) / mBucketDurationMillis), 0,
- (180 * DateUtils.DAY_IN_MILLIS) / mBucketDurationMillis);
- final NetworkStatsHistory combined = new NetworkStatsHistory(
- mBucketDurationMillis, bucketEstimate, fields);
-
- // shortcut when we know stats will be empty
- if (start == end) return combined;
-
- // Figure out the window of time that we should be augmenting (if any)
- long augmentStart = SubscriptionPlan.TIME_UNKNOWN;
- long augmentEnd = (augmentPlan != null) ? augmentPlan.getDataUsageTime()
- : SubscriptionPlan.TIME_UNKNOWN;
- // And if augmenting, we might need to collect more data to adjust with
- long collectStart = start;
- long collectEnd = end;
-
- if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) {
- final Iterator<Range<ZonedDateTime>> it = augmentPlan.cycleIterator();
- while (it.hasNext()) {
- final Range<ZonedDateTime> cycle = it.next();
- final long cycleStart = cycle.getLower().toInstant().toEpochMilli();
- final long cycleEnd = cycle.getUpper().toInstant().toEpochMilli();
- if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) {
- augmentStart = cycleStart;
- collectStart = Long.min(collectStart, augmentStart);
- collectEnd = Long.max(collectEnd, augmentEnd);
- break;
- }
- }
- }
-
- if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) {
- // Shrink augmentation window so we don't risk undercounting.
- augmentStart = roundUp(augmentStart);
- augmentEnd = roundDown(augmentEnd);
- // Grow collection window so we get all the stats needed.
- collectStart = roundDown(collectStart);
- collectEnd = roundUp(collectEnd);
- }
-
- for (int i = 0; i < mStats.size(); i++) {
- final Key key = mStats.keyAt(i);
- if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag
- && templateMatches(template, key.ident)) {
- final NetworkStatsHistory value = mStats.valueAt(i);
- combined.recordHistory(value, collectStart, collectEnd);
- }
- }
-
- if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) {
- final NetworkStatsHistory.Entry entry = combined.getValues(
- augmentStart, augmentEnd, null);
-
- // If we don't have any recorded data for this time period, give
- // ourselves something to scale with.
- if (entry.rxBytes == 0 || entry.txBytes == 0) {
- combined.recordData(augmentStart, augmentEnd,
- new NetworkStats.Entry(1, 0, 1, 0, 0));
- combined.getValues(augmentStart, augmentEnd, entry);
- }
-
- final long rawBytes = (entry.rxBytes + entry.txBytes) == 0 ? 1 :
- (entry.rxBytes + entry.txBytes);
- final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes;
- final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes;
- final long targetBytes = augmentPlan.getDataUsageBytes();
-
- final long targetRxBytes = multiplySafeByRational(targetBytes, rawRxBytes, rawBytes);
- final long targetTxBytes = multiplySafeByRational(targetBytes, rawTxBytes, rawBytes);
-
-
- // Scale all matching buckets to reach anchor target
- final long beforeTotal = combined.getTotalBytes();
- for (int i = 0; i < combined.size(); i++) {
- combined.getValues(i, entry);
- if (entry.bucketStart >= augmentStart
- && entry.bucketStart + entry.bucketDuration <= augmentEnd) {
- entry.rxBytes = multiplySafeByRational(
- targetRxBytes, entry.rxBytes, rawRxBytes);
- entry.txBytes = multiplySafeByRational(
- targetTxBytes, entry.txBytes, rawTxBytes);
- // We purposefully clear out packet counters to indicate
- // that this data has been augmented.
- entry.rxPackets = 0;
- entry.txPackets = 0;
- combined.setValues(i, entry);
- }
- }
-
- final long deltaTotal = combined.getTotalBytes() - beforeTotal;
- if (deltaTotal != 0) {
- Log.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
- }
-
- // Finally we can slice data as originally requested
- final NetworkStatsHistory sliced = new NetworkStatsHistory(
- mBucketDurationMillis, bucketEstimate, fields);
- sliced.recordHistory(combined, start, end);
- return sliced;
- } else {
- return combined;
- }
- }
-
- /**
- * Summarize all {@link NetworkStatsHistory} in this collection which match
- * 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.
- * @hide
- */
- public NetworkStats getSummary(NetworkTemplate template, long start, long end,
- @NetworkStatsAccess.Level int accessLevel, int callerUid) {
- final long now = System.currentTimeMillis();
-
- final NetworkStats stats = new NetworkStats(end - start, 24);
-
- // shortcut when we know stats will be empty
- if (start == end) return stats;
-
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- NetworkStatsHistory.Entry historyEntry = null;
-
- for (int i = 0; i < mStats.size(); i++) {
- final Key key = mStats.keyAt(i);
- if (templateMatches(template, key.ident)
- && NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)
- && key.set < NetworkStats.SET_DEBUG_START) {
- final NetworkStatsHistory value = mStats.valueAt(i);
- historyEntry = value.getValues(start, end, now, historyEntry);
-
- entry.iface = IFACE_ALL;
- entry.uid = key.uid;
- entry.set = key.set;
- entry.tag = key.tag;
- 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;
- entry.rxPackets = historyEntry.rxPackets;
- entry.txBytes = historyEntry.txBytes;
- entry.txPackets = historyEntry.txPackets;
- entry.operations = historyEntry.operations;
-
- if (!entry.isEmpty()) {
- stats.combineValues(entry);
- }
- }
- }
-
- return stats;
- }
-
- /**
- * Record given {@link android.net.NetworkStats.Entry} into this collection.
- * @hide
- */
- public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start,
- long end, NetworkStats.Entry entry) {
- final NetworkStatsHistory history = findOrCreateHistory(ident, uid, set, tag);
- history.recordData(start, end, entry);
- noteRecordedHistory(history.getStart(), history.getEnd(), entry.rxBytes + entry.txBytes);
- }
-
- /**
- * Record given {@link NetworkStatsHistory} into this collection.
- *
- * @hide
- */
- public void recordHistory(@NonNull Key key, @NonNull NetworkStatsHistory history) {
- Objects.requireNonNull(key);
- Objects.requireNonNull(history);
- if (history.size() == 0) return;
- noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes());
-
- NetworkStatsHistory target = mStats.get(key);
- if (target == null) {
- target = new NetworkStatsHistory(history.getBucketDuration());
- mStats.put(key, target);
- }
- target.recordEntireHistory(history);
- }
-
- /**
- * Record all {@link NetworkStatsHistory} contained in the given collection
- * into this collection.
- *
- * @hide
- */
- public void recordCollection(@NonNull NetworkStatsCollection another) {
- Objects.requireNonNull(another);
- for (int i = 0; i < another.mStats.size(); i++) {
- final Key key = another.mStats.keyAt(i);
- final NetworkStatsHistory value = another.mStats.valueAt(i);
- recordHistory(key, value);
- }
- }
-
- private NetworkStatsHistory findOrCreateHistory(
- NetworkIdentitySet ident, int uid, int set, int tag) {
- final Key key = new Key(ident, uid, set, tag);
- final NetworkStatsHistory existing = mStats.get(key);
-
- // update when no existing, or when bucket duration changed
- NetworkStatsHistory updated = null;
- if (existing == null) {
- updated = new NetworkStatsHistory(mBucketDurationMillis, 10);
- } else if (existing.getBucketDuration() != mBucketDurationMillis) {
- updated = new NetworkStatsHistory(existing, mBucketDurationMillis);
- }
-
- if (updated != null) {
- mStats.put(key, updated);
- return updated;
- } else {
- return existing;
- }
- }
-
- /** @hide */
- @Override
- public void read(InputStream in) throws IOException {
- read((DataInput) new DataInputStream(in));
- }
-
- private void read(DataInput in) throws IOException {
- // verify file magic header intact
- final int magic = in.readInt();
- if (magic != FILE_MAGIC) {
- throw new ProtocolException("unexpected magic: " + magic);
- }
-
- final int version = in.readInt();
- switch (version) {
- case VERSION_UNIFIED_INIT: {
- // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
- final int identSize = in.readInt();
- for (int i = 0; i < identSize; i++) {
- final NetworkIdentitySet ident = new NetworkIdentitySet(in);
-
- final int size = in.readInt();
- for (int j = 0; j < size; j++) {
- final int uid = in.readInt();
- final int set = in.readInt();
- final int tag = in.readInt();
-
- final Key key = new Key(ident, uid, set, tag);
- final NetworkStatsHistory history = new NetworkStatsHistory(in);
- recordHistory(key, history);
- }
- }
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
- }
-
- /** @hide */
- @Override
- public void write(OutputStream out) throws IOException {
- write((DataOutput) new DataOutputStream(out));
- out.flush();
- }
-
- private void write(DataOutput out) throws IOException {
- // cluster key lists grouped by ident
- final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = new HashMap<>();
- for (Key key : mStats.keySet()) {
- ArrayList<Key> keys = keysByIdent.get(key.ident);
- if (keys == null) {
- keys = new ArrayList<>();
- keysByIdent.put(key.ident, keys);
- }
- keys.add(key);
- }
-
- out.writeInt(FILE_MAGIC);
- out.writeInt(VERSION_UNIFIED_INIT);
-
- out.writeInt(keysByIdent.size());
- for (NetworkIdentitySet ident : keysByIdent.keySet()) {
- final ArrayList<Key> keys = keysByIdent.get(ident);
- ident.writeToStream(out);
-
- out.writeInt(keys.size());
- for (Key key : keys) {
- final NetworkStatsHistory history = mStats.get(key);
- out.writeInt(key.uid);
- out.writeInt(key.set);
- out.writeInt(key.tag);
- history.writeToStream(out);
- }
- }
- }
-
- /**
- * Read legacy network summary statistics file format into the collection,
- * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public void readLegacyNetwork(File file) throws IOException {
- final AtomicFile inputFile = new AtomicFile(file);
-
- DataInputStream in = null;
- try {
- in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
-
- // verify file magic header intact
- final int magic = in.readInt();
- if (magic != FILE_MAGIC) {
- throw new ProtocolException("unexpected magic: " + magic);
- }
-
- final int version = in.readInt();
- switch (version) {
- case VERSION_NETWORK_INIT: {
- // network := size *(NetworkIdentitySet NetworkStatsHistory)
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- final NetworkIdentitySet ident = new NetworkIdentitySet(in);
- final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
- final Key key = new Key(ident, UID_ALL, SET_ALL, TAG_NONE);
- recordHistory(key, history);
- }
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
- } catch (FileNotFoundException e) {
- // missing stats is okay, probably first boot
- } finally {
- IoUtils.closeQuietly(in);
- }
- }
-
- /**
- * Read legacy Uid statistics file format into the collection,
- * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public void readLegacyUid(File file, boolean onlyTags) throws IOException {
- final AtomicFile inputFile = new AtomicFile(file);
-
- DataInputStream in = null;
- try {
- in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
-
- // verify file magic header intact
- final int magic = in.readInt();
- if (magic != FILE_MAGIC) {
- throw new ProtocolException("unexpected magic: " + magic);
- }
-
- final int version = in.readInt();
- switch (version) {
- case VERSION_UID_INIT: {
- // uid := size *(UID NetworkStatsHistory)
-
- // drop this data version, since we don't have a good
- // mapping into NetworkIdentitySet.
- break;
- }
- case VERSION_UID_WITH_IDENT: {
- // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
-
- // drop this data version, since this version only existed
- // for a short time.
- break;
- }
- case VERSION_UID_WITH_TAG:
- case VERSION_UID_WITH_SET: {
- // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
- final int identSize = in.readInt();
- for (int i = 0; i < identSize; i++) {
- final NetworkIdentitySet ident = new NetworkIdentitySet(in);
-
- final int size = in.readInt();
- for (int j = 0; j < size; j++) {
- final int uid = in.readInt();
- final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt()
- : SET_DEFAULT;
- final int tag = in.readInt();
-
- final Key key = new Key(ident, uid, set, tag);
- final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
- if ((tag == TAG_NONE) != onlyTags) {
- recordHistory(key, history);
- }
- }
- }
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
- } catch (FileNotFoundException e) {
- // missing stats is okay, probably first boot
- } finally {
- IoUtils.closeQuietly(in);
- }
- }
-
- /**
- * Remove any {@link NetworkStatsHistory} attributed to the requested UID,
- * moving any {@link NetworkStats#TAG_NONE} series to
- * {@link TrafficStats#UID_REMOVED}.
- * @hide
- */
- public void removeUids(int[] uids) {
- final ArrayList<Key> knownKeys = new ArrayList<>();
- knownKeys.addAll(mStats.keySet());
-
- // migrate all UID stats into special "removed" bucket
- for (Key key : knownKeys) {
- if (CollectionUtils.contains(uids, key.uid)) {
- // only migrate combined TAG_NONE history
- if (key.tag == TAG_NONE) {
- final NetworkStatsHistory uidHistory = mStats.get(key);
- final NetworkStatsHistory removedHistory = findOrCreateHistory(
- key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE);
- removedHistory.recordEntireHistory(uidHistory);
- }
- mStats.remove(key);
- mDirty = true;
- }
- }
- }
-
- private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) {
- if (startMillis < mStartMillis) mStartMillis = startMillis;
- if (endMillis > mEndMillis) mEndMillis = endMillis;
- mTotalBytes += totalBytes;
- mDirty = true;
- }
-
- private int estimateBuckets() {
- return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5)
- / mBucketDurationMillis);
- }
-
- private ArrayList<Key> getSortedKeys() {
- final ArrayList<Key> keys = new ArrayList<>();
- keys.addAll(mStats.keySet());
- Collections.sort(keys, (left, right) -> Key.compare(left, right));
- return keys;
- }
-
- /** @hide */
- public void dump(IndentingPrintWriter pw) {
- for (Key key : getSortedKeys()) {
- pw.print("ident="); pw.print(key.ident.toString());
- pw.print(" uid="); pw.print(key.uid);
- pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
- pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
-
- final NetworkStatsHistory history = mStats.get(key);
- pw.increaseIndent();
- history.dump(pw, true);
- pw.decreaseIndent();
- }
- }
-
- /** @hide */
- public void dumpDebug(ProtoOutputStream proto, long tag) {
- final long start = proto.start(tag);
-
- for (Key key : getSortedKeys()) {
- final long startStats = proto.start(NetworkStatsCollectionProto.STATS_FIELD_NUMBER);
-
- // Key
- final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY_FIELD_NUMBER);
- key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY_FIELD_NUMBER);
- proto.write(NetworkStatsCollectionKeyProto.UID_FIELD_NUMBER, key.uid);
- proto.write(NetworkStatsCollectionKeyProto.SET_FIELD_NUMBER, key.set);
- proto.write(NetworkStatsCollectionKeyProto.TAG_FIELD_NUMBER, key.tag);
- proto.end(startKey);
-
- // Value
- final NetworkStatsHistory history = mStats.get(key);
- history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY_FIELD_NUMBER);
- proto.end(startStats);
- }
-
- proto.end(start);
- }
-
- /** @hide */
- public void dumpCheckin(PrintWriter pw, long start, long end) {
- dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
- dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
- dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateEthernet(), "eth");
- dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateBluetooth(), "bt");
- }
-
- /**
- * Dump all contained stats that match requested parameters, but group
- * together all matching {@link NetworkTemplate} under a single prefix.
- */
- private void dumpCheckin(PrintWriter pw, long start, long end, NetworkTemplate groupTemplate,
- String groupPrefix) {
- final ArrayMap<Key, NetworkStatsHistory> grouped = new ArrayMap<>();
-
- // Walk through all history, grouping by matching network templates
- for (int i = 0; i < mStats.size(); i++) {
- final Key key = mStats.keyAt(i);
- final NetworkStatsHistory value = mStats.valueAt(i);
-
- if (!templateMatches(groupTemplate, key.ident)) continue;
- if (key.set >= NetworkStats.SET_DEBUG_START) continue;
-
- final Key groupKey = new Key(null, key.uid, key.set, key.tag);
- NetworkStatsHistory groupHistory = grouped.get(groupKey);
- if (groupHistory == null) {
- groupHistory = new NetworkStatsHistory(value.getBucketDuration());
- grouped.put(groupKey, groupHistory);
- }
- groupHistory.recordHistory(value, start, end);
- }
-
- for (int i = 0; i < grouped.size(); i++) {
- final Key key = grouped.keyAt(i);
- final NetworkStatsHistory value = grouped.valueAt(i);
-
- if (value.size() == 0) continue;
-
- pw.print("c,");
- pw.print(groupPrefix); pw.print(',');
- pw.print(key.uid); pw.print(',');
- pw.print(NetworkStats.setToCheckinString(key.set)); pw.print(',');
- pw.print(key.tag);
- pw.println();
-
- value.dumpCheckin(pw);
- }
- }
-
- /**
- * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
- * in the given {@link NetworkIdentitySet}.
- */
- private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
- for (NetworkIdentity ident : identSet) {
- if (template.matches(ident)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get the all historical stats of the collection {@link NetworkStatsCollection}.
- *
- * @return All {@link NetworkStatsHistory} in this collection.
- */
- @NonNull
- public Map<Key, NetworkStatsHistory> getEntries() {
- return new ArrayMap(mStats);
- }
-
- /**
- * Builder class for {@link NetworkStatsCollection}.
- */
- public static final class Builder {
- private final long mBucketDurationMillis;
- private final ArrayMap<Key, NetworkStatsHistory> mEntries = new ArrayMap<>();
-
- /**
- * Creates a new Builder with given bucket duration.
- *
- * @param bucketDuration Duration of the buckets of the object, in milliseconds.
- */
- public Builder(long bucketDurationMillis) {
- mBucketDurationMillis = bucketDurationMillis;
- }
-
- /**
- * Add association of the history with the specified key in this map.
- *
- * @param key The object used to identify a network, see {@link Key}.
- * @param history {@link NetworkStatsHistory} instance associated to the given {@link Key}.
- * @return The builder object.
- */
- @NonNull
- public NetworkStatsCollection.Builder addEntry(@NonNull Key key,
- @NonNull NetworkStatsHistory history) {
- Objects.requireNonNull(key);
- Objects.requireNonNull(history);
- final List<Entry> historyEntries = history.getEntries();
-
- final NetworkStatsHistory.Builder historyBuilder =
- new NetworkStatsHistory.Builder(mBucketDurationMillis, historyEntries.size());
- for (Entry entry : historyEntries) {
- historyBuilder.addEntry(entry);
- }
-
- mEntries.put(key, historyBuilder.build());
- return this;
- }
-
- /**
- * Builds the instance of the {@link NetworkStatsCollection}.
- *
- * @return the built instance of {@link NetworkStatsCollection}.
- */
- @NonNull
- public NetworkStatsCollection build() {
- final NetworkStatsCollection collection =
- new NetworkStatsCollection(mBucketDurationMillis);
- for (int i = 0; i < mEntries.size(); i++) {
- collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i));
- }
- return collection;
- }
- }
-
- /**
- * the identifier that associate with the {@link NetworkStatsHistory} object to identify
- * a certain record in the {@link NetworkStatsCollection} object.
- */
- public static final class Key {
- /** @hide */
- public final NetworkIdentitySet ident;
- /** @hide */
- public final int uid;
- /** @hide */
- public final int set;
- /** @hide */
- public final int tag;
-
- private final int mHashCode;
-
- /**
- * Construct a {@link Key} object.
- *
- * @param ident a Set of {@link NetworkIdentity} that associated with the record.
- * @param uid Uid of the record.
- * @param set Set of the record, see {@code NetworkStats#SET_*}.
- * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}.
- */
- public Key(@NonNull Set<NetworkIdentity> ident, int uid, @State int set, int tag) {
- this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag);
- }
-
- /** @hide */
- public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) {
- this.ident = Objects.requireNonNull(ident);
- this.uid = uid;
- this.set = set;
- this.tag = tag;
- mHashCode = Objects.hash(ident, uid, set, tag);
- }
-
- @Override
- public int hashCode() {
- return mHashCode;
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (obj instanceof Key) {
- final Key key = (Key) obj;
- return uid == key.uid && set == key.set && tag == key.tag
- && Objects.equals(ident, key.ident);
- }
- return false;
- }
-
- /** @hide */
- public static int compare(@NonNull Key left, @NonNull Key right) {
- Objects.requireNonNull(left);
- Objects.requireNonNull(right);
- int res = 0;
- if (left.ident != null && right.ident != null) {
- res = NetworkIdentitySet.compare(left.ident, right.ident);
- }
- if (res == 0) {
- res = Integer.compare(left.uid, right.uid);
- }
- if (res == 0) {
- res = Integer.compare(left.set, right.set);
- }
- if (res == 0) {
- res = Integer.compare(left.tag, right.tag);
- }
- return res;
- }
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl
deleted file mode 100644
index 8b9069f..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl
+++ /dev/null
@@ -1,19 +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;
-
-parcelable NetworkStatsHistory;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
deleted file mode 100644
index 822a16e..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
+++ /dev/null
@@ -1,1162 +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.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStatsHistory.DataStreamUtils.readFullLongArray;
-import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLongArray;
-import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray;
-import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
-import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
-import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-
-import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.NetworkStatsHistoryBucketProto;
-import android.service.NetworkStatsHistoryProto;
-import android.util.IndentingPrintWriter;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import libcore.util.EmptyArray;
-
-import java.io.CharArrayWriter;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.ProtocolException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-
-/**
- * Collection of historical network statistics, recorded into equally-sized
- * "buckets" in time. Internally it stores data in {@code long} series for more
- * efficient persistence.
- * <p>
- * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for
- * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is
- * sorted at all times.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class NetworkStatsHistory implements Parcelable {
- private static final int VERSION_INIT = 1;
- private static final int VERSION_ADD_PACKETS = 2;
- private static final int VERSION_ADD_ACTIVE = 3;
-
- /** @hide */
- public static final int FIELD_ACTIVE_TIME = 0x01;
- /** @hide */
- public static final int FIELD_RX_BYTES = 0x02;
- /** @hide */
- public static final int FIELD_RX_PACKETS = 0x04;
- /** @hide */
- public static final int FIELD_TX_BYTES = 0x08;
- /** @hide */
- public static final int FIELD_TX_PACKETS = 0x10;
- /** @hide */
- public static final int FIELD_OPERATIONS = 0x20;
- /** @hide */
- public static final int FIELD_ALL = 0xFFFFFFFF;
-
- private long bucketDuration;
- private int bucketCount;
- private long[] bucketStart;
- private long[] activeTime;
- private long[] rxBytes;
- private long[] rxPackets;
- private long[] txBytes;
- private long[] txPackets;
- private long[] operations;
- private long totalBytes;
-
- /** @hide */
- public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime,
- long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets,
- long[] operations, int bucketCount, long totalBytes) {
- this.bucketDuration = bucketDuration;
- this.bucketStart = bucketStart;
- this.activeTime = activeTime;
- this.rxBytes = rxBytes;
- this.rxPackets = rxPackets;
- this.txBytes = txBytes;
- this.txPackets = txPackets;
- this.operations = operations;
- this.bucketCount = bucketCount;
- this.totalBytes = totalBytes;
- }
-
- /**
- * An instance to represent a single record in a {@link NetworkStatsHistory} object.
- */
- public static final class Entry {
- /** @hide */
- public static final long UNKNOWN = -1;
-
- /** @hide */
- // TODO: Migrate all callers to get duration from the history object and remove this field.
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long bucketDuration;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long bucketStart;
- /** @hide */
- public long activeTime;
- /** @hide */
- @UnsupportedAppUsage
- public long rxBytes;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long rxPackets;
- /** @hide */
- @UnsupportedAppUsage
- public long txBytes;
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long txPackets;
- /** @hide */
- public long operations;
- /** @hide */
- Entry() {}
-
- /**
- * Construct a {@link Entry} instance to represent a single record in a
- * {@link NetworkStatsHistory} object.
- *
- * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the
- * Unix epoch, see {@link java.lang.System#currentTimeMillis}.
- * @param activeTime Active time for this {@link Entry}, in milliseconds.
- * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
- * represent the contents of IP packets, including IP headers.
- * @param operations count of network operations performed for this {@link Entry}. This can
- * be used to derive bytes-per-operation.
- */
- public Entry(long bucketStart, long activeTime, long rxBytes,
- long rxPackets, long txBytes, long txPackets, long operations) {
- this.bucketStart = bucketStart;
- this.activeTime = activeTime;
- this.rxBytes = rxBytes;
- this.rxPackets = rxPackets;
- this.txBytes = txBytes;
- this.txPackets = txPackets;
- this.operations = operations;
- }
-
- /**
- * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch.
- */
- public long getBucketStart() {
- return bucketStart;
- }
-
- /**
- * Get active time of the bucket's time interval, in milliseconds.
- */
- public long getActiveTime() {
- return activeTime;
- }
-
- /** Get number of bytes received for this {@link Entry}. */
- public long getRxBytes() {
- return rxBytes;
- }
-
- /** Get number of packets received for this {@link Entry}. */
- public long getRxPackets() {
- return rxPackets;
- }
-
- /** Get number of bytes transmitted for this {@link Entry}. */
- public long getTxBytes() {
- return txBytes;
- }
-
- /** Get number of packets transmitted for this {@link Entry}. */
- public long getTxPackets() {
- return txPackets;
- }
-
- /** Get count of network operations performed for this {@link Entry}. */
- public long getOperations() {
- return operations;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o.getClass() != getClass()) return false;
- Entry entry = (Entry) o;
- return bucketStart == entry.bucketStart
- && activeTime == entry.activeTime && rxBytes == entry.rxBytes
- && rxPackets == entry.rxPackets && txBytes == entry.txBytes
- && txPackets == entry.txPackets && operations == entry.operations;
- }
-
- @Override
- public int hashCode() {
- return (int) (bucketStart * 2
- + activeTime * 3
- + rxBytes * 5
- + rxPackets * 7
- + txBytes * 11
- + txPackets * 13
- + operations * 17);
- }
-
- @Override
- public String toString() {
- return "Entry{"
- + "bucketStart=" + bucketStart
- + ", activeTime=" + activeTime
- + ", rxBytes=" + rxBytes
- + ", rxPackets=" + rxPackets
- + ", txBytes=" + txBytes
- + ", txPackets=" + txPackets
- + ", operations=" + operations
- + "}";
- }
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public NetworkStatsHistory(long bucketDuration) {
- this(bucketDuration, 10, FIELD_ALL);
- }
-
- /** @hide */
- public NetworkStatsHistory(long bucketDuration, int initialSize) {
- this(bucketDuration, initialSize, FIELD_ALL);
- }
-
- /** @hide */
- public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
- this.bucketDuration = bucketDuration;
- bucketStart = new long[initialSize];
- if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize];
- if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
- if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
- if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
- if ((fields & FIELD_TX_PACKETS) != 0) txPackets = new long[initialSize];
- if ((fields & FIELD_OPERATIONS) != 0) operations = new long[initialSize];
- bucketCount = 0;
- totalBytes = 0;
- }
-
- /** @hide */
- public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) {
- this(bucketDuration, existing.estimateResizeBuckets(bucketDuration));
- recordEntireHistory(existing);
- }
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public NetworkStatsHistory(Parcel in) {
- bucketDuration = in.readLong();
- bucketStart = readLongArray(in);
- activeTime = readLongArray(in);
- rxBytes = readLongArray(in);
- rxPackets = readLongArray(in);
- txBytes = readLongArray(in);
- txPackets = readLongArray(in);
- operations = readLongArray(in);
- bucketCount = bucketStart.length;
- totalBytes = in.readLong();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeLong(bucketDuration);
- writeLongArray(out, bucketStart, bucketCount);
- writeLongArray(out, activeTime, bucketCount);
- writeLongArray(out, rxBytes, bucketCount);
- writeLongArray(out, rxPackets, bucketCount);
- writeLongArray(out, txBytes, bucketCount);
- writeLongArray(out, txPackets, bucketCount);
- writeLongArray(out, operations, bucketCount);
- out.writeLong(totalBytes);
- }
-
- /** @hide */
- public NetworkStatsHistory(DataInput in) throws IOException {
- final int version = in.readInt();
- switch (version) {
- case VERSION_INIT: {
- bucketDuration = in.readLong();
- bucketStart = readFullLongArray(in);
- rxBytes = readFullLongArray(in);
- rxPackets = new long[bucketStart.length];
- txBytes = readFullLongArray(in);
- txPackets = new long[bucketStart.length];
- operations = new long[bucketStart.length];
- bucketCount = bucketStart.length;
- totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
- break;
- }
- case VERSION_ADD_PACKETS:
- case VERSION_ADD_ACTIVE: {
- bucketDuration = in.readLong();
- bucketStart = readVarLongArray(in);
- activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in)
- : new long[bucketStart.length];
- rxBytes = readVarLongArray(in);
- rxPackets = readVarLongArray(in);
- txBytes = readVarLongArray(in);
- txPackets = readVarLongArray(in);
- operations = readVarLongArray(in);
- bucketCount = bucketStart.length;
- totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
-
- if (bucketStart.length != bucketCount || rxBytes.length != bucketCount
- || rxPackets.length != bucketCount || txBytes.length != bucketCount
- || txPackets.length != bucketCount || operations.length != bucketCount) {
- throw new ProtocolException("Mismatched history lengths");
- }
- }
-
- /** @hide */
- public void writeToStream(DataOutput out) throws IOException {
- out.writeInt(VERSION_ADD_ACTIVE);
- out.writeLong(bucketDuration);
- writeVarLongArray(out, bucketStart, bucketCount);
- writeVarLongArray(out, activeTime, bucketCount);
- writeVarLongArray(out, rxBytes, bucketCount);
- writeVarLongArray(out, rxPackets, bucketCount);
- writeVarLongArray(out, txBytes, bucketCount);
- writeVarLongArray(out, txPackets, bucketCount);
- writeVarLongArray(out, operations, bucketCount);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int size() {
- return bucketCount;
- }
-
- /** @hide */
- public long getBucketDuration() {
- return bucketDuration;
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public long getStart() {
- if (bucketCount > 0) {
- return bucketStart[0];
- } else {
- return Long.MAX_VALUE;
- }
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public long getEnd() {
- if (bucketCount > 0) {
- return bucketStart[bucketCount - 1] + bucketDuration;
- } else {
- return Long.MIN_VALUE;
- }
- }
-
- /**
- * Return total bytes represented by this history.
- * @hide
- */
- public long getTotalBytes() {
- return totalBytes;
- }
-
- /**
- * Return index of bucket that contains or is immediately before the
- * requested time.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int getIndexBefore(long time) {
- int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
- if (index < 0) {
- index = (~index) - 1;
- } else {
- index -= 1;
- }
- return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
- }
-
- /**
- * Return index of bucket that contains or is immediately after the
- * requested time.
- * @hide
- */
- public int getIndexAfter(long time) {
- int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
- if (index < 0) {
- index = ~index;
- } else {
- index += 1;
- }
- return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
- }
-
- /**
- * Return specific stats entry.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public Entry getValues(int i, Entry recycle) {
- final Entry entry = recycle != null ? recycle : new Entry();
- entry.bucketStart = bucketStart[i];
- entry.bucketDuration = bucketDuration;
- entry.activeTime = getLong(activeTime, i, UNKNOWN);
- entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
- entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
- entry.txBytes = getLong(txBytes, i, UNKNOWN);
- entry.txPackets = getLong(txPackets, i, UNKNOWN);
- entry.operations = getLong(operations, i, UNKNOWN);
- return entry;
- }
-
- /**
- * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance.
- *
- * @return
- */
- @NonNull
- public List<Entry> getEntries() {
- // TODO: Return a wrapper that uses this list instead, to prevent the returned result
- // from being changed.
- final ArrayList<Entry> ret = new ArrayList<>(size());
- for (int i = 0; i < size(); i++) {
- ret.add(getValues(i, null /* recycle */));
- }
- return ret;
- }
-
- /** @hide */
- public void setValues(int i, Entry entry) {
- // Unwind old values
- if (rxBytes != null) totalBytes -= rxBytes[i];
- if (txBytes != null) totalBytes -= txBytes[i];
-
- bucketStart[i] = entry.bucketStart;
- setLong(activeTime, i, entry.activeTime);
- setLong(rxBytes, i, entry.rxBytes);
- setLong(rxPackets, i, entry.rxPackets);
- setLong(txBytes, i, entry.txBytes);
- setLong(txPackets, i, entry.txPackets);
- setLong(operations, i, entry.operations);
-
- // Apply new values
- if (rxBytes != null) totalBytes += rxBytes[i];
- if (txBytes != null) totalBytes += txBytes[i];
- }
-
- /**
- * Record that data traffic occurred in the given time range. Will
- * distribute across internal buckets, creating new buckets as needed.
- * @hide
- */
- @Deprecated
- public void recordData(long start, long end, long rxBytes, long txBytes) {
- recordData(start, end, new NetworkStats.Entry(
- IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L));
- }
-
- /**
- * Record that data traffic occurred in the given time range. Will
- * distribute across internal buckets, creating new buckets as needed.
- * @hide
- */
- public void recordData(long start, long end, NetworkStats.Entry entry) {
- long rxBytes = entry.rxBytes;
- long rxPackets = entry.rxPackets;
- long txBytes = entry.txBytes;
- long txPackets = entry.txPackets;
- long operations = entry.operations;
-
- if (entry.isNegative()) {
- throw new IllegalArgumentException("tried recording negative data");
- }
- if (entry.isEmpty()) {
- return;
- }
-
- // 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;
- final int startIndex = getIndexAfter(end);
- for (int i = startIndex; i >= 0; i--) {
- final long curStart = bucketStart[i];
- final long curEnd = curStart + bucketDuration;
-
- // bucket is older than record; we're finished
- if (curEnd < start) break;
- // bucket is newer than record; keep looking
- if (curStart > end) continue;
-
- final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
- if (overlap <= 0) continue;
-
- // integer math each time is faster than floating point
- final long fracRxBytes = multiplySafeByRational(rxBytes, overlap, duration);
- final long fracRxPackets = multiplySafeByRational(rxPackets, overlap, duration);
- final long fracTxBytes = multiplySafeByRational(txBytes, overlap, duration);
- final long fracTxPackets = multiplySafeByRational(txPackets, overlap, duration);
- final long fracOperations = multiplySafeByRational(operations, overlap, duration);
-
-
- addLong(activeTime, i, overlap);
- addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes;
- addLong(this.rxPackets, i, fracRxPackets); rxPackets -= fracRxPackets;
- addLong(this.txBytes, i, fracTxBytes); txBytes -= fracTxBytes;
- addLong(this.txPackets, i, fracTxPackets); txPackets -= fracTxPackets;
- addLong(this.operations, i, fracOperations); operations -= fracOperations;
-
- duration -= overlap;
- }
-
- totalBytes += entry.rxBytes + entry.txBytes;
- }
-
- /**
- * Record an entire {@link NetworkStatsHistory} into this history. Usually
- * for combining together stats for external reporting.
- * @hide
- */
- @UnsupportedAppUsage
- public void recordEntireHistory(NetworkStatsHistory input) {
- recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE);
- }
-
- /**
- * Record given {@link NetworkStatsHistory} into this history, copying only
- * buckets that atomically occur in the inclusive time range. Doesn't
- * interpolate across partial buckets.
- * @hide
- */
- public void recordHistory(NetworkStatsHistory input, long start, long end) {
- final NetworkStats.Entry entry = new NetworkStats.Entry(
- IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
- for (int i = 0; i < input.bucketCount; i++) {
- final long bucketStart = input.bucketStart[i];
- final long bucketEnd = bucketStart + input.bucketDuration;
-
- // skip when bucket is outside requested range
- if (bucketStart < start || bucketEnd > end) continue;
-
- entry.rxBytes = getLong(input.rxBytes, i, 0L);
- entry.rxPackets = getLong(input.rxPackets, i, 0L);
- entry.txBytes = getLong(input.txBytes, i, 0L);
- entry.txPackets = getLong(input.txPackets, i, 0L);
- entry.operations = getLong(input.operations, i, 0L);
-
- recordData(bucketStart, bucketEnd, entry);
- }
- }
-
- /**
- * Ensure that buckets exist for given time range, creating as needed.
- */
- private void ensureBuckets(long start, long end) {
- // normalize incoming range to bucket boundaries
- start -= start % bucketDuration;
- end += (bucketDuration - (end % bucketDuration)) % bucketDuration;
-
- for (long now = start; now < end; now += bucketDuration) {
- // try finding existing bucket
- final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now);
- if (index < 0) {
- // bucket missing, create and insert
- insertBucket(~index, now);
- }
- }
- }
-
- /**
- * Insert new bucket at requested index and starting time.
- */
- private void insertBucket(int index, long start) {
- // create more buckets when needed
- if (bucketCount >= bucketStart.length) {
- final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
- bucketStart = Arrays.copyOf(bucketStart, newLength);
- if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength);
- if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
- if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
- if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
- if (txPackets != null) txPackets = Arrays.copyOf(txPackets, newLength);
- if (operations != null) operations = Arrays.copyOf(operations, newLength);
- }
-
- // create gap when inserting bucket in middle
- if (index < bucketCount) {
- final int dstPos = index + 1;
- final int length = bucketCount - index;
-
- System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
- if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length);
- if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
- if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
- if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
- if (txPackets != null) System.arraycopy(txPackets, index, txPackets, dstPos, length);
- if (operations != null) System.arraycopy(operations, index, operations, dstPos, length);
- }
-
- bucketStart[index] = start;
- setLong(activeTime, index, 0L);
- setLong(rxBytes, index, 0L);
- setLong(rxPackets, index, 0L);
- setLong(txBytes, index, 0L);
- setLong(txPackets, index, 0L);
- setLong(operations, index, 0L);
- bucketCount++;
- }
-
- /**
- * Clear all data stored in this object.
- * @hide
- */
- public void clear() {
- bucketStart = EmptyArray.LONG;
- if (activeTime != null) activeTime = EmptyArray.LONG;
- if (rxBytes != null) rxBytes = EmptyArray.LONG;
- if (rxPackets != null) rxPackets = EmptyArray.LONG;
- if (txBytes != null) txBytes = EmptyArray.LONG;
- if (txPackets != null) txPackets = EmptyArray.LONG;
- if (operations != null) operations = EmptyArray.LONG;
- bucketCount = 0;
- totalBytes = 0;
- }
-
- /**
- * Remove buckets older than requested cutoff.
- * @hide
- */
- public void removeBucketsBefore(long cutoff) {
- // TODO: Consider use getIndexBefore.
- int i;
- for (i = 0; i < bucketCount; i++) {
- final long curStart = bucketStart[i];
- final long curEnd = curStart + bucketDuration;
-
- // cutoff happens before or during this bucket; everything before
- // this bucket should be removed.
- if (curEnd > cutoff) break;
- }
-
- if (i > 0) {
- final int length = bucketStart.length;
- bucketStart = Arrays.copyOfRange(bucketStart, i, length);
- if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length);
- if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
- if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
- if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
- if (txPackets != null) txPackets = Arrays.copyOfRange(txPackets, i, length);
- if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
- bucketCount -= i;
-
- totalBytes = 0;
- if (rxBytes != null) totalBytes += CollectionUtils.total(rxBytes);
- if (txBytes != null) totalBytes += CollectionUtils.total(txBytes);
- }
- }
-
- /**
- * 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.
- * @hide
- */
- @UnsupportedAppUsage
- public Entry getValues(long start, long end, Entry recycle) {
- return getValues(start, end, Long.MAX_VALUE, recycle);
- }
-
- /**
- * 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.
- * @hide
- */
- @UnsupportedAppUsage
- public Entry getValues(long start, long end, long now, Entry recycle) {
- final Entry entry = recycle != null ? recycle : new Entry();
- entry.bucketDuration = end - start;
- entry.bucketStart = start;
- entry.activeTime = activeTime != null ? 0 : UNKNOWN;
- entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
- entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
- entry.txBytes = txBytes != null ? 0 : UNKNOWN;
- 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];
- long curEnd = curStart + bucketDuration;
-
- // bucket is older than request; we're finished
- if (curEnd <= start) break;
- // bucket is newer than request; keep looking
- if (curStart >= end) continue;
-
- // the active bucket is shorter then a normal completed bucket
- if (curEnd > now) curEnd = now;
- // usually this is simply bucketDuration
- final long bucketSpan = curEnd - curStart;
- // prevent division by zero
- if (bucketSpan <= 0) continue;
-
- final long overlapEnd = curEnd < end ? curEnd : end;
- final long overlapStart = curStart > start ? curStart : start;
- final long overlap = overlapEnd - overlapStart;
- if (overlap <= 0) continue;
-
- // integer math each time is faster than floating point
- if (activeTime != null) {
- entry.activeTime += multiplySafeByRational(activeTime[i], overlap, bucketSpan);
- }
- if (rxBytes != null) {
- entry.rxBytes += multiplySafeByRational(rxBytes[i], overlap, bucketSpan);
- }
- if (rxPackets != null) {
- entry.rxPackets += multiplySafeByRational(rxPackets[i], overlap, bucketSpan);
- }
- if (txBytes != null) {
- entry.txBytes += multiplySafeByRational(txBytes[i], overlap, bucketSpan);
- }
- if (txPackets != null) {
- entry.txPackets += multiplySafeByRational(txPackets[i], overlap, bucketSpan);
- }
- if (operations != null) {
- entry.operations += multiplySafeByRational(operations[i], overlap, bucketSpan);
- }
- }
- return entry;
- }
-
- /**
- * @deprecated only for temporary testing
- * @hide
- */
- @Deprecated
- public void generateRandom(long start, long end, long bytes) {
- final Random r = new Random();
-
- final float fractionRx = r.nextFloat();
- final long rxBytes = (long) (bytes * fractionRx);
- final long txBytes = (long) (bytes * (1 - fractionRx));
-
- final long rxPackets = rxBytes / 1024;
- final long txPackets = txBytes / 1024;
- final long operations = rxBytes / 2048;
-
- generateRandom(start, end, rxBytes, rxPackets, txBytes, txPackets, operations, r);
- }
-
- /**
- * @deprecated only for temporary testing
- * @hide
- */
- @Deprecated
- public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
- long txPackets, long operations, Random r) {
- ensureBuckets(start, end);
-
- final NetworkStats.Entry entry = new NetworkStats.Entry(
- IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
- while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128
- || operations > 32) {
- final long curStart = randomLong(r, start, end);
- final long curEnd = curStart + randomLong(r, 0, (end - curStart) / 2);
-
- entry.rxBytes = randomLong(r, 0, rxBytes);
- entry.rxPackets = randomLong(r, 0, rxPackets);
- entry.txBytes = randomLong(r, 0, txBytes);
- entry.txPackets = randomLong(r, 0, txPackets);
- entry.operations = randomLong(r, 0, operations);
-
- rxBytes -= entry.rxBytes;
- rxPackets -= entry.rxPackets;
- txBytes -= entry.txBytes;
- txPackets -= entry.txPackets;
- operations -= entry.operations;
-
- recordData(curStart, curEnd, entry);
- }
- }
-
- /** @hide */
- public static long randomLong(Random r, long start, long end) {
- return (long) (start + (r.nextFloat() * (end - start)));
- }
-
- /**
- * Quickly determine if this history intersects with given window.
- * @hide
- */
- public boolean intersects(long start, long end) {
- final long dataStart = getStart();
- final long dataEnd = getEnd();
- if (start >= dataStart && start <= dataEnd) return true;
- if (end >= dataStart && end <= dataEnd) return true;
- if (dataStart >= start && dataStart <= end) return true;
- if (dataEnd >= start && dataEnd <= end) return true;
- return false;
- }
-
- /** @hide */
- public void dump(IndentingPrintWriter pw, boolean fullHistory) {
- pw.print("NetworkStatsHistory: bucketDuration=");
- pw.println(bucketDuration / SECOND_IN_MILLIS);
- pw.increaseIndent();
-
- final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32);
- if (start > 0) {
- pw.print("(omitting "); pw.print(start); pw.println(" buckets)");
- }
-
- for (int i = start; i < bucketCount; i++) {
- pw.print("st="); pw.print(bucketStart[i] / SECOND_IN_MILLIS);
- if (rxBytes != null) { pw.print(" rb="); pw.print(rxBytes[i]); }
- if (rxPackets != null) { pw.print(" rp="); pw.print(rxPackets[i]); }
- if (txBytes != null) { pw.print(" tb="); pw.print(txBytes[i]); }
- if (txPackets != null) { pw.print(" tp="); pw.print(txPackets[i]); }
- if (operations != null) { pw.print(" op="); pw.print(operations[i]); }
- pw.println();
- }
-
- pw.decreaseIndent();
- }
-
- /** @hide */
- public void dumpCheckin(PrintWriter pw) {
- pw.print("d,");
- pw.print(bucketDuration / SECOND_IN_MILLIS);
- pw.println();
-
- for (int i = 0; i < bucketCount; i++) {
- pw.print("b,");
- pw.print(bucketStart[i] / SECOND_IN_MILLIS); pw.print(',');
- if (rxBytes != null) { pw.print(rxBytes[i]); } else { pw.print("*"); } pw.print(',');
- if (rxPackets != null) { pw.print(rxPackets[i]); } else { pw.print("*"); } pw.print(',');
- if (txBytes != null) { pw.print(txBytes[i]); } else { pw.print("*"); } pw.print(',');
- if (txPackets != null) { pw.print(txPackets[i]); } else { pw.print("*"); } pw.print(',');
- if (operations != null) { pw.print(operations[i]); } else { pw.print("*"); }
- pw.println();
- }
- }
-
- /** @hide */
- public void dumpDebug(ProtoOutputStream proto, long tag) {
- final long start = proto.start(tag);
-
- proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS_FIELD_NUMBER, bucketDuration);
-
- for (int i = 0; i < bucketCount; i++) {
- final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS_FIELD_NUMBER);
-
- proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS_FIELD_NUMBER,
- bucketStart[i]);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES_FIELD_NUMBER, rxBytes, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS_FIELD_NUMBER, rxPackets, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES_FIELD_NUMBER, txBytes, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS_FIELD_NUMBER, txPackets, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS_FIELD_NUMBER, operations, i);
-
- proto.end(startBucket);
- }
-
- proto.end(start);
- }
-
- private static void dumpDebug(ProtoOutputStream proto, long tag, long[] array, int index) {
- if (array != null) {
- proto.write(tag, array[index]);
- }
- }
-
- @Override
- public String toString() {
- final CharArrayWriter writer = new CharArrayWriter();
- dump(new IndentingPrintWriter(writer, " "), false);
- return writer.toString();
- }
-
- @UnsupportedAppUsage
- public static final @android.annotation.NonNull Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
- @Override
- public NetworkStatsHistory createFromParcel(Parcel in) {
- return new NetworkStatsHistory(in);
- }
-
- @Override
- public NetworkStatsHistory[] newArray(int size) {
- return new NetworkStatsHistory[size];
- }
- };
-
- private static long getLong(long[] array, int i, long value) {
- return array != null ? array[i] : value;
- }
-
- private static void setLong(long[] array, int i, long value) {
- if (array != null) array[i] = value;
- }
-
- private static void addLong(long[] array, int i, long value) {
- if (array != null) array[i] += value;
- }
-
- /** @hide */
- public int estimateResizeBuckets(long newBucketDuration) {
- return (int) (size() * getBucketDuration() / newBucketDuration);
- }
-
- /**
- * Utility methods for interacting with {@link DataInputStream} and
- * {@link DataOutputStream}, mostly dealing with writing partial arrays.
- * @hide
- */
- public static class DataStreamUtils {
- @Deprecated
- public static long[] readFullLongArray(DataInput in) throws IOException {
- final int size = in.readInt();
- if (size < 0) throw new ProtocolException("negative array size");
- final long[] values = new long[size];
- for (int i = 0; i < values.length; i++) {
- values[i] = in.readLong();
- }
- return values;
- }
-
- /**
- * Read variable-length {@link Long} using protobuf-style approach.
- */
- public static long readVarLong(DataInput in) throws IOException {
- int shift = 0;
- long result = 0;
- while (shift < 64) {
- byte b = in.readByte();
- result |= (long) (b & 0x7F) << shift;
- if ((b & 0x80) == 0)
- return result;
- shift += 7;
- }
- throw new ProtocolException("malformed long");
- }
-
- /**
- * Write variable-length {@link Long} using protobuf-style approach.
- */
- public static void writeVarLong(DataOutput out, long value) throws IOException {
- while (true) {
- if ((value & ~0x7FL) == 0) {
- out.writeByte((int) value);
- return;
- } else {
- out.writeByte(((int) value & 0x7F) | 0x80);
- value >>>= 7;
- }
- }
- }
-
- public static long[] readVarLongArray(DataInput in) throws IOException {
- final int size = in.readInt();
- if (size == -1) return null;
- if (size < 0) throw new ProtocolException("negative array size");
- final long[] values = new long[size];
- for (int i = 0; i < values.length; i++) {
- values[i] = readVarLong(in);
- }
- return values;
- }
-
- public static void writeVarLongArray(DataOutput out, long[] values, int size)
- throws IOException {
- if (values == null) {
- out.writeInt(-1);
- return;
- }
- if (size > values.length) {
- throw new IllegalArgumentException("size larger than length");
- }
- out.writeInt(size);
- for (int i = 0; i < size; i++) {
- writeVarLong(out, values[i]);
- }
- }
- }
-
- /**
- * Utility methods for interacting with {@link Parcel} structures, mostly
- * dealing with writing partial arrays.
- * @hide
- */
- public static class ParcelUtils {
- public static long[] readLongArray(Parcel in) {
- final int size = in.readInt();
- if (size == -1) return null;
- final long[] values = new long[size];
- for (int i = 0; i < values.length; i++) {
- values[i] = in.readLong();
- }
- return values;
- }
-
- public static void writeLongArray(Parcel out, long[] values, int size) {
- if (values == null) {
- out.writeInt(-1);
- return;
- }
- if (size > values.length) {
- throw new IllegalArgumentException("size larger than length");
- }
- out.writeInt(size);
- for (int i = 0; i < size; i++) {
- out.writeLong(values[i]);
- }
- }
- }
-
- /**
- * Builder class for {@link NetworkStatsHistory}.
- */
- public static final class Builder {
- private final long mBucketDuration;
- private final List<Long> mBucketStart;
- private final List<Long> mActiveTime;
- private final List<Long> mRxBytes;
- private final List<Long> mRxPackets;
- private final List<Long> mTxBytes;
- private final List<Long> mTxPackets;
- private final List<Long> mOperations;
-
- /**
- * Creates a new Builder with given bucket duration and initial capacity to construct
- * {@link NetworkStatsHistory} objects.
- *
- * @param bucketDuration Duration of the buckets of the object, in milliseconds.
- * @param initialCapacity Estimated number of records.
- */
- public Builder(long bucketDuration, int initialCapacity) {
- mBucketDuration = bucketDuration;
- mBucketStart = new ArrayList<>(initialCapacity);
- mActiveTime = new ArrayList<>(initialCapacity);
- mRxBytes = new ArrayList<>(initialCapacity);
- mRxPackets = new ArrayList<>(initialCapacity);
- mTxBytes = new ArrayList<>(initialCapacity);
- mTxPackets = new ArrayList<>(initialCapacity);
- mOperations = new ArrayList<>(initialCapacity);
- }
-
- /**
- * Add an {@link Entry} into the {@link NetworkStatsHistory} instance.
- *
- * @param entry The target {@link Entry} object.
- * @return The builder object.
- */
- @NonNull
- public Builder addEntry(@NonNull Entry entry) {
- mBucketStart.add(entry.bucketStart);
- mActiveTime.add(entry.activeTime);
- mRxBytes.add(entry.rxBytes);
- mRxPackets.add(entry.rxPackets);
- mTxBytes.add(entry.txBytes);
- mTxPackets.add(entry.txPackets);
- mOperations.add(entry.operations);
- return this;
- }
-
- private static long sum(@NonNull List<Long> list) {
- long sum = 0;
- for (long entry : list) {
- sum += entry;
- }
- return sum;
- }
-
- /**
- * Builds the instance of the {@link NetworkStatsHistory}.
- *
- * @return the built instance of {@link NetworkStatsHistory}.
- */
- @NonNull
- public NetworkStatsHistory build() {
- return new NetworkStatsHistory(mBucketDuration,
- CollectionUtils.toLongArray(mBucketStart),
- CollectionUtils.toLongArray(mActiveTime),
- CollectionUtils.toLongArray(mRxBytes),
- CollectionUtils.toLongArray(mRxPackets),
- CollectionUtils.toLongArray(mTxBytes),
- CollectionUtils.toLongArray(mTxPackets),
- CollectionUtils.toLongArray(mOperations),
- mBucketStart.size(),
- sum(mRxBytes) + sum(mTxBytes));
- }
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
deleted file mode 100644
index 7b5afd7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ /dev/null
@@ -1,1119 +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.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.app.usage.NetworkStatsManager;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.net.wifi.WifiInfo;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-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.Comparator;
-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_PROXY,
- 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 ConnectivityManager#TYPE_PROXY} as the legacy
- * network type.
- */
- 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;
-
- /** @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,
- 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#getNetworkKey()}
- * 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#getNetworkKey()}
- * 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 mRatType;
- /**
- * 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 ratType,
- int oemManaged) {
- this(matchRule, subscriberId, matchSubscriberIds,
- wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
- metered, roaming, defaultNetwork, ratType, 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 ratType, 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;
- mRatType = ratType;
- 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();
- mRatType = 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(mRatType);
- 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 (mRatType != NETWORK_TYPE_ALL) {
- builder.append(", ratType=").append(mRatType);
- }
- 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, mRatType, 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
- && mRatType == other.mRatType
- && 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#getNetworkKey()}.
- */
- @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 mRatType;
- }
-
- /**
- * 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
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public boolean matches(@NonNull NetworkIdentity ident) {
- Objects.requireNonNull(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 mRatType == NETWORK_TYPE_ALL
- || NetworkStatsManager.getCollapsedRatType(mRatType)
- == NetworkStatsManager.getCollapsedRatType(ident.mRatType);
- }
-
- /**
- * 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#getNetworkKey()}
- * 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);
- }
- }
-
- /**
- * Check if matches Wi-Fi network template.
- */
- private boolean matchesWifi(NetworkIdentity ident) {
- switch (ident.mType) {
- case TYPE_WIFI:
- return matchesSubscriberId(ident.mSubscriberId)
- && matchesWifiNetworkKey(ident.mWifiNetworkKey);
- 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#getNetworkKey()}.
- * Or an empty list to match all networks.
- * Note that {@code getNetworkKey()} 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(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/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
deleted file mode 100644
index bc836d8..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ /dev/null
@@ -1,1148 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.annotation.NonNull;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.app.DownloadManager;
-import android.app.backup.BackupManager;
-import android.app.usage.NetworkStatsManager;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.media.MediaPlayer;
-import android.os.Binder;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.StrictMode;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * Class that provides network traffic statistics. These statistics include
- * bytes transmitted and received and network packets transmitted and received,
- * over all interfaces, over the mobile interface, and on a per-UID basis.
- * <p>
- * These statistics may not be available on all platforms. If the statistics are
- * not supported by this device, {@link #UNSUPPORTED} will be returned.
- * <p>
- * Note that the statistics returned by this class reset and start from zero
- * after every reboot. To access more robust historical network statistics data,
- * use {@link NetworkStatsManager} instead.
- */
-public class TrafficStats {
- static {
- System.loadLibrary("framework-connectivity-tiramisu-jni");
- }
-
- private static final String TAG = TrafficStats.class.getSimpleName();
- /**
- * The return value to indicate that the device does not support the statistic.
- */
- public final static int UNSUPPORTED = -1;
-
- /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
- @Deprecated
- public static final long KB_IN_BYTES = 1024;
- /** @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 {@code DataUnit} instead to clarify SI-vs-IEC */
- @Deprecated
- public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
- /** @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 {@code DataUnit} instead to clarify SI-vs-IEC */
- @Deprecated
- public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
-
- /**
- * Special UID value used when collecting {@link NetworkStatsHistory} for
- * removed applications.
- *
- * @hide
- */
- public static final int UID_REMOVED = -4;
-
- /**
- * Special UID value used when collecting {@link NetworkStatsHistory} for
- * tethering traffic.
- *
- * @hide
- */
- public static final int UID_TETHERING = NetworkStats.UID_TETHERING;
-
- /**
- * Tag values in this range are reserved for the network stack. The network stack is
- * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline
- * module separate process, and as the system UID otherwise.
- */
- /** @hide */
- @SystemApi
- public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00;
- /** @hide */
- @SystemApi
- public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF;
-
- /**
- * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services
- * like DownloadManager when performing traffic on behalf of an application.
- */
- // Please note there is no enforcement of these constants, so do not rely on them to
- // determine that the caller is a system caller.
- /** @hide */
- @SystemApi
- public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00;
- /** @hide */
- @SystemApi
- public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F;
-
- /**
- * Tag values between these ranges are reserved for the network stack to do traffic
- * on behalf of applications. It is a subrange of the range above.
- */
- /** @hide */
- @SystemApi
- public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80;
- /** @hide */
- @SystemApi
- public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F;
-
- /**
- * Default tag value for {@link DownloadManager} traffic.
- *
- * @hide
- */
- public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
-
- /**
- * Default tag value for {@link MediaPlayer} traffic.
- *
- * @hide
- */
- public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
-
- /**
- * Default tag value for {@link BackupManager} backup traffic; that is,
- * traffic from the device to the storage backend.
- *
- * @hide
- */
- public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
-
- /**
- * Default tag value for {@link BackupManager} restore traffic; that is,
- * app data retrieved from the storage backend at install time.
- *
- * @hide
- */
- public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04;
-
- /**
- * Default tag value for code (typically APKs) downloaded by an app store on
- * behalf of the app, such as updates.
- *
- * @hide
- */
- public static final int TAG_SYSTEM_APP = 0xFFFFFF05;
-
- // TODO : remove this constant when Wifi code is updated
- /** @hide */
- public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42;
-
- private static INetworkStatsService sStatsService;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
- private synchronized static INetworkStatsService getStatsService() {
- if (sStatsService == null) {
- throw new IllegalStateException("TrafficStats not initialized, uid="
- + Binder.getCallingUid());
- }
- return sStatsService;
- }
-
- /**
- * Snapshot of {@link NetworkStats} when the currently active profiling
- * session started, or {@code null} if no session active.
- *
- * @see #startDataProfiling(Context)
- * @see #stopDataProfiling(Context)
- */
- private static NetworkStats sActiveProfilingStart;
-
- private static Object sProfilingLock = new Object();
-
- private static final String LOOPBACK_IFACE = "lo";
-
- /**
- * Initialization {@link TrafficStats} with the context, to
- * allow {@link TrafficStats} to fetch the needed binder.
- *
- * @param context a long-lived context, such as the application context or system
- * server context.
- * @hide
- */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- @SuppressLint("VisiblySynchronized")
- public static synchronized void init(@NonNull final Context context) {
- if (sStatsService != null) {
- throw new IllegalStateException("TrafficStats is already initialized, uid="
- + Binder.getCallingUid());
- }
- final NetworkStatsManager statsManager =
- context.getSystemService(NetworkStatsManager.class);
- if (statsManager == null) {
- // TODO: Currently Process.isSupplemental is not working yet, because it depends on
- // process to run in a certain UID range, which is not true for now. Change this
- // to Log.wtf once Process.isSupplemental is ready.
- Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid());
- return;
- }
- sStatsService = statsManager.getBinder();
- }
-
- /**
- * Attach the socket tagger implementation to the current process, to
- * get notified when a socket's {@link FileDescriptor} is assigned to
- * a thread. See {@link SocketTagger#set(SocketTagger)}.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static void attachSocketTagger() {
- dalvik.system.SocketTagger.set(new SocketTagger());
- }
-
- private static class SocketTagger extends dalvik.system.SocketTagger {
-
- // TODO: set to false
- private static final boolean LOGD = true;
-
- SocketTagger() {
- }
-
- @Override
- public void tag(FileDescriptor fd) throws SocketException {
- final UidTag tagInfo = sThreadUidTag.get();
- if (LOGD) {
- Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
- + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid);
- }
- if (tagInfo.tag == -1) {
- StrictMode.noteUntaggedSocket();
- }
-
- if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
- final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid);
- if (errno < 0) {
- Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
- + tagInfo.tag + ", "
- + tagInfo.uid + ") failed with errno" + errno);
- }
- }
-
- @Override
- public void untag(FileDescriptor fd) throws SocketException {
- if (LOGD) {
- Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
- }
-
- final UidTag tagInfo = sThreadUidTag.get();
- if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
-
- final int errno = native_untagSocketFd(fd);
- if (errno < 0) {
- Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
- }
- }
- }
-
- private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
- private static native int native_untagSocketFd(FileDescriptor fd);
-
- private static class UidTag {
- public int tag = -1;
- public int uid = -1;
- }
-
- private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() {
- @Override
- protected UidTag initialValue() {
- return new UidTag();
- }
- };
-
- /**
- * Set active tag to use when accounting {@link Socket} traffic originating
- * from the current thread. Only one active tag per thread is supported.
- * <p>
- * Changes only take effect during subsequent calls to
- * {@link #tagSocket(Socket)}.
- * <p>
- * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
- * used internally by system services like {@link DownloadManager} when
- * performing traffic on behalf of an application.
- *
- * @see #clearThreadStatsTag()
- */
- public static void setThreadStatsTag(int tag) {
- getAndSetThreadStatsTag(tag);
- }
-
- /**
- * Set active tag to use when accounting {@link Socket} traffic originating
- * from the current thread. Only one active tag per thread is supported.
- * <p>
- * Changes only take effect during subsequent calls to
- * {@link #tagSocket(Socket)}.
- * <p>
- * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
- * used internally by system services like {@link DownloadManager} when
- * performing traffic on behalf of an application.
- *
- * @return the current tag for the calling thread, which can be used to
- * restore any existing values after a nested operation is finished
- */
- public static int getAndSetThreadStatsTag(int tag) {
- final int old = sThreadUidTag.get().tag;
- sThreadUidTag.get().tag = tag;
- return old;
- }
-
- /**
- * Set active tag to use when accounting {@link Socket} traffic originating
- * from the current thread. The tag used internally is well-defined to
- * distinguish all backup-related traffic.
- *
- * @hide
- */
- @SystemApi
- public static void setThreadStatsTagBackup() {
- setThreadStatsTag(TAG_SYSTEM_BACKUP);
- }
-
- /**
- * Set active tag to use when accounting {@link Socket} traffic originating
- * from the current thread. The tag used internally is well-defined to
- * distinguish all restore-related traffic.
- *
- * @hide
- */
- @SystemApi
- public static void setThreadStatsTagRestore() {
- setThreadStatsTag(TAG_SYSTEM_RESTORE);
- }
-
- /**
- * Set active tag to use when accounting {@link Socket} traffic originating
- * from the current thread. The tag used internally is well-defined to
- * distinguish all code (typically APKs) downloaded by an app store on
- * behalf of the app, such as updates.
- *
- * @hide
- */
- @SystemApi
- public static void setThreadStatsTagApp() {
- setThreadStatsTag(TAG_SYSTEM_APP);
- }
-
- /**
- * Set active tag to use when accounting {@link Socket} traffic originating
- * from the current thread. The tag used internally is well-defined to
- * distinguish all download provider traffic.
- *
- * @hide
- */
- @SystemApi
- public static void setThreadStatsTagDownload() {
- setThreadStatsTag(TAG_SYSTEM_DOWNLOAD);
- }
-
- /**
- * Get the active tag used when accounting {@link Socket} traffic originating
- * from the current thread. Only one active tag per thread is supported.
- * {@link #tagSocket(Socket)}.
- *
- * @see #setThreadStatsTag(int)
- */
- public static int getThreadStatsTag() {
- return sThreadUidTag.get().tag;
- }
-
- /**
- * Clear any active tag set to account {@link Socket} traffic originating
- * from the current thread.
- *
- * @see #setThreadStatsTag(int)
- */
- public static void clearThreadStatsTag() {
- sThreadUidTag.get().tag = -1;
- }
-
- /**
- * Set specific UID to use when accounting {@link Socket} traffic
- * originating from the current thread. Designed for use when performing an
- * operation on behalf of another application, or when another application
- * is performing operations on your behalf.
- * <p>
- * Any app can <em>accept</em> blame for traffic performed on a socket
- * originally created by another app by calling this method with the
- * {@link android.system.Os#getuid()} value. However, only apps holding the
- * {@code android.Manifest.permission#UPDATE_DEVICE_STATS} permission may
- * <em>assign</em> blame to another UIDs.
- * <p>
- * Changes only take effect during subsequent calls to
- * {@link #tagSocket(Socket)}.
- */
- @SuppressLint("RequiresPermission")
- public static void setThreadStatsUid(int uid) {
- sThreadUidTag.get().uid = uid;
- }
-
- /**
- * Get the active UID used when accounting {@link Socket} traffic originating
- * from the current thread. Only one active tag per thread is supported.
- * {@link #tagSocket(Socket)}.
- *
- * @see #setThreadStatsUid(int)
- */
- public static int getThreadStatsUid() {
- return sThreadUidTag.get().uid;
- }
-
- /**
- * Set specific UID to use when accounting {@link Socket} traffic
- * originating from the current thread as the calling UID. Designed for use
- * when another application is performing operations on your behalf.
- * <p>
- * Changes only take effect during subsequent calls to
- * {@link #tagSocket(Socket)}.
- *
- * @removed
- * @deprecated use {@link #setThreadStatsUid(int)} instead.
- */
- @Deprecated
- public static void setThreadStatsUidSelf() {
- setThreadStatsUid(android.os.Process.myUid());
- }
-
- /**
- * Clear any active UID set to account {@link Socket} traffic originating
- * from the current thread.
- *
- * @see #setThreadStatsUid(int)
- */
- @SuppressLint("RequiresPermission")
- public static void clearThreadStatsUid() {
- setThreadStatsUid(-1);
- }
-
- /**
- * Tag the given {@link Socket} with any statistics parameters active for
- * the current thread. Subsequent calls always replace any existing
- * parameters. When finished, call {@link #untagSocket(Socket)} to remove
- * statistics parameters.
- *
- * @see #setThreadStatsTag(int)
- */
- public static void tagSocket(Socket socket) throws SocketException {
- SocketTagger.get().tag(socket);
- }
-
- /**
- * Remove any statistics parameters from the given {@link Socket}.
- * <p>
- * In Android 8.1 (API level 27) and lower, a socket is automatically
- * untagged when it's sent to another process using binder IPC with a
- * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28)
- * and higher, the socket tag is kept when the socket is sent to another
- * process using binder IPC. You can mimic the previous behavior by
- * calling {@code untagSocket()} before sending the socket to another
- * process.
- */
- public static void untagSocket(Socket socket) throws SocketException {
- SocketTagger.get().untag(socket);
- }
-
- /**
- * Tag the given {@link DatagramSocket} with any statistics parameters
- * active for the current thread. Subsequent calls always replace any
- * existing parameters. When finished, call
- * {@link #untagDatagramSocket(DatagramSocket)} to remove statistics
- * parameters.
- *
- * @see #setThreadStatsTag(int)
- */
- public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
- SocketTagger.get().tag(socket);
- }
-
- /**
- * Remove any statistics parameters from the given {@link DatagramSocket}.
- */
- public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
- SocketTagger.get().untag(socket);
- }
-
- /**
- * Tag the given {@link FileDescriptor} socket with any statistics
- * parameters active for the current thread. Subsequent calls always replace
- * any existing parameters. When finished, call
- * {@link #untagFileDescriptor(FileDescriptor)} to remove statistics
- * parameters.
- *
- * @see #setThreadStatsTag(int)
- */
- public static void tagFileDescriptor(FileDescriptor fd) throws IOException {
- SocketTagger.get().tag(fd);
- }
-
- /**
- * Remove any statistics parameters from the given {@link FileDescriptor}
- * socket.
- */
- public static void untagFileDescriptor(FileDescriptor fd) throws IOException {
- SocketTagger.get().untag(fd);
- }
-
- /**
- * Start profiling data usage for current UID. Only one profiling session
- * can be active at a time.
- *
- * @hide
- */
- public static void startDataProfiling(Context context) {
- synchronized (sProfilingLock) {
- if (sActiveProfilingStart != null) {
- throw new IllegalStateException("already profiling data");
- }
-
- // take snapshot in time; we calculate delta later
- sActiveProfilingStart = getDataLayerSnapshotForUid(context);
- }
- }
-
- /**
- * Stop profiling data usage for current UID.
- *
- * @return Detailed {@link NetworkStats} of data that occurred since last
- * {@link #startDataProfiling(Context)} call.
- * @hide
- */
- public static NetworkStats stopDataProfiling(Context context) {
- synchronized (sProfilingLock) {
- if (sActiveProfilingStart == null) {
- throw new IllegalStateException("not profiling data");
- }
-
- // subtract starting values and return delta
- final NetworkStats profilingStop = getDataLayerSnapshotForUid(context);
- final NetworkStats profilingDelta = NetworkStats.subtract(
- profilingStop, sActiveProfilingStart, null, null);
- sActiveProfilingStart = null;
- return profilingDelta;
- }
- }
-
- /**
- * Increment count of network operations performed under the accounting tag
- * currently active on the calling thread. This can be used to derive
- * bytes-per-operation.
- *
- * @param operationCount Number of operations to increment count by.
- */
- public static void incrementOperationCount(int operationCount) {
- final int tag = getThreadStatsTag();
- incrementOperationCount(tag, operationCount);
- }
-
- /**
- * Increment count of network operations performed under the given
- * accounting tag. This can be used to derive bytes-per-operation.
- *
- * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
- * @param operationCount Number of operations to increment count by.
- */
- public static void incrementOperationCount(int tag, int operationCount) {
- final int uid = android.os.Process.myUid();
- try {
- getStatsService().incrementOperationCount(uid, tag, operationCount);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** {@hide} */
- public static void closeQuietly(INetworkStatsSession session) {
- // TODO: move to NetworkStatsService once it exists
- if (session != null) {
- try {
- session.close();
- } catch (RuntimeException rethrown) {
- throw rethrown;
- } catch (Exception ignored) {
- }
- }
- }
-
- private static long addIfSupported(long stat) {
- return (stat == UNSUPPORTED) ? 0 : stat;
- }
-
- /**
- * Return number of packets transmitted across mobile networks since device
- * boot. Counts packets across all mobile network interfaces, and always
- * increases monotonically since device boot. Statistics are measured at the
- * network layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getMobileTxPackets() {
- long total = 0;
- for (String iface : getMobileIfaces()) {
- total += addIfSupported(getTxPackets(iface));
- }
- return total;
- }
-
- /**
- * Return number of packets received across mobile networks since device
- * boot. Counts packets across all mobile network interfaces, and always
- * increases monotonically since device boot. Statistics are measured at the
- * network layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getMobileRxPackets() {
- long total = 0;
- for (String iface : getMobileIfaces()) {
- total += addIfSupported(getRxPackets(iface));
- }
- return total;
- }
-
- /**
- * Return number of bytes transmitted across mobile networks since device
- * boot. Counts packets across all mobile network interfaces, and always
- * increases monotonically since device boot. Statistics are measured at the
- * network layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getMobileTxBytes() {
- long total = 0;
- for (String iface : getMobileIfaces()) {
- total += addIfSupported(getTxBytes(iface));
- }
- return total;
- }
-
- /**
- * Return number of bytes received across mobile networks since device boot.
- * Counts packets across all mobile network interfaces, and always increases
- * monotonically since device boot. Statistics are measured at the network
- * layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getMobileRxBytes() {
- long total = 0;
- for (String iface : getMobileIfaces()) {
- total += addIfSupported(getRxBytes(iface));
- }
- return total;
- }
-
- /** {@hide} */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static long getMobileTcpRxPackets() {
- long total = 0;
- for (String iface : getMobileIfaces()) {
- long stat = UNSUPPORTED;
- try {
- stat = getStatsService().getIfaceStats(iface, TYPE_TCP_RX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- total += addIfSupported(stat);
- }
- return total;
- }
-
- /** {@hide} */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static long getMobileTcpTxPackets() {
- long total = 0;
- for (String iface : getMobileIfaces()) {
- long stat = UNSUPPORTED;
- try {
- stat = getStatsService().getIfaceStats(iface, TYPE_TCP_TX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- total += addIfSupported(stat);
- }
- return total;
- }
-
- /**
- * Return the number of packets transmitted on the specified interface since the interface
- * was created. Statistics are measured at the network layer, so both TCP and
- * UDP usage are included.
- *
- * Note that the returned values are partial statistics that do not count data from several
- * sources and do not apply several adjustments that are necessary for correctness, such
- * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
- * determine whether traffic is being transferred on the specific interface but are not a
- * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
- * APIs.
- *
- * @param iface The name of the interface.
- * @return The number of transmitted packets.
- */
- public static long getTxPackets(@NonNull String iface) {
- try {
- return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return the number of packets received on the specified interface since the interface was
- * created. Statistics are measured at the network layer, so both TCP
- * and UDP usage are included.
- *
- * Note that the returned values are partial statistics that do not count data from several
- * sources and do not apply several adjustments that are necessary for correctness, such
- * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
- * determine whether traffic is being transferred on the specific interface but are not a
- * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
- * APIs.
- *
- * @param iface The name of the interface.
- * @return The number of received packets.
- */
- public static long getRxPackets(@NonNull String iface) {
- try {
- return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return the number of bytes transmitted on the specified interface since the interface
- * was created. Statistics are measured at the network layer, so both TCP and
- * UDP usage are included.
- *
- * Note that the returned values are partial statistics that do not count data from several
- * sources and do not apply several adjustments that are necessary for correctness, such
- * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
- * determine whether traffic is being transferred on the specific interface but are not a
- * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
- * APIs.
- *
- * @param iface The name of the interface.
- * @return The number of transmitted bytes.
- */
- public static long getTxBytes(@NonNull String iface) {
- try {
- return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return the number of bytes received on the specified interface since the interface
- * was created. Statistics are measured at the network layer, so both TCP
- * and UDP usage are included.
- *
- * Note that the returned values are partial statistics that do not count data from several
- * sources and do not apply several adjustments that are necessary for correctness, such
- * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
- * determine whether traffic is being transferred on the specific interface but are not a
- * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
- * APIs.
- *
- * @param iface The name of the interface.
- * @return The number of received bytes.
- */
- public static long getRxBytes(@NonNull String iface) {
- try {
- return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** {@hide} */
- @TestApi
- public static long getLoopbackTxPackets() {
- try {
- return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** {@hide} */
- @TestApi
- public static long getLoopbackRxPackets() {
- try {
- return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** {@hide} */
- @TestApi
- public static long getLoopbackTxBytes() {
- try {
- return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** {@hide} */
- @TestApi
- public static long getLoopbackRxBytes() {
- try {
- return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of packets transmitted since device boot. Counts packets
- * across all network interfaces, and always increases monotonically since
- * device boot. Statistics are measured at the network layer, so they
- * include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getTotalTxPackets() {
- try {
- return getStatsService().getTotalStats(TYPE_TX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of packets received since device boot. Counts packets
- * across all network interfaces, and always increases monotonically since
- * device boot. Statistics are measured at the network layer, so they
- * include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getTotalRxPackets() {
- try {
- return getStatsService().getTotalStats(TYPE_RX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of bytes transmitted since device boot. Counts packets
- * across all network interfaces, and always increases monotonically since
- * device boot. Statistics are measured at the network layer, so they
- * include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getTotalTxBytes() {
- try {
- return getStatsService().getTotalStats(TYPE_TX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of bytes received since device boot. Counts packets across
- * all network interfaces, and always increases monotonically since device
- * boot. Statistics are measured at the network layer, so they include both
- * TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- */
- public static long getTotalRxBytes() {
- try {
- return getStatsService().getTotalStats(TYPE_RX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of bytes transmitted by the given UID since device boot.
- * Counts packets across all network interfaces, and always increases
- * monotonically since device boot. Statistics are measured at the network
- * layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
- * return {@link #UNSUPPORTED} on devices where statistics aren't available.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
- * report traffic statistics for the calling UID. It will return
- * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
- * historical network statistics belonging to other UIDs, use
- * {@link NetworkStatsManager}.
- *
- * @see android.os.Process#myUid()
- * @see android.content.pm.ApplicationInfo#uid
- */
- public static long getUidTxBytes(int uid) {
- try {
- return getStatsService().getUidStats(uid, TYPE_TX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of bytes received by the given UID since device boot.
- * Counts packets across all network interfaces, and always increases
- * monotonically since device boot. Statistics are measured at the network
- * layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
- * {@link #UNSUPPORTED} on devices where statistics aren't available.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
- * report traffic statistics for the calling UID. It will return
- * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
- * historical network statistics belonging to other UIDs, use
- * {@link NetworkStatsManager}.
- *
- * @see android.os.Process#myUid()
- * @see android.content.pm.ApplicationInfo#uid
- */
- public static long getUidRxBytes(int uid) {
- try {
- return getStatsService().getUidStats(uid, TYPE_RX_BYTES);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of packets transmitted by the given UID since device boot.
- * Counts packets across all network interfaces, and always increases
- * monotonically since device boot. Statistics are measured at the network
- * layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
- * {@link #UNSUPPORTED} on devices where statistics aren't available.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
- * report traffic statistics for the calling UID. It will return
- * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
- * historical network statistics belonging to other UIDs, use
- * {@link NetworkStatsManager}.
- *
- * @see android.os.Process#myUid()
- * @see android.content.pm.ApplicationInfo#uid
- */
- public static long getUidTxPackets(int uid) {
- try {
- return getStatsService().getUidStats(uid, TYPE_TX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return number of packets received by the given UID since device boot.
- * Counts packets across all network interfaces, and always increases
- * monotonically since device boot. Statistics are measured at the network
- * layer, so they include both TCP and UDP usage.
- * <p>
- * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
- * {@link #UNSUPPORTED} on devices where statistics aren't available.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
- * report traffic statistics for the calling UID. It will return
- * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
- * historical network statistics belonging to other UIDs, use
- * {@link NetworkStatsManager}.
- *
- * @see android.os.Process#myUid()
- * @see android.content.pm.ApplicationInfo#uid
- */
- public static long getUidRxPackets(int uid) {
- try {
- return getStatsService().getUidStats(uid, TYPE_RX_PACKETS);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidTxBytes(int)
- */
- @Deprecated
- public static long getUidTcpTxBytes(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidRxBytes(int)
- */
- @Deprecated
- public static long getUidTcpRxBytes(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidTxBytes(int)
- */
- @Deprecated
- public static long getUidUdpTxBytes(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidRxBytes(int)
- */
- @Deprecated
- public static long getUidUdpRxBytes(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidTxPackets(int)
- */
- @Deprecated
- public static long getUidTcpTxSegments(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidRxPackets(int)
- */
- @Deprecated
- public static long getUidTcpRxSegments(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidTxPackets(int)
- */
- @Deprecated
- public static long getUidUdpTxPackets(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * transport layer statistics are no longer available, and will
- * always return {@link #UNSUPPORTED}.
- * @see #getUidRxPackets(int)
- */
- @Deprecated
- public static long getUidUdpRxPackets(int uid) {
- return UNSUPPORTED;
- }
-
- /**
- * Return detailed {@link NetworkStats} for the current UID. Requires no
- * special permission.
- */
- private static NetworkStats getDataLayerSnapshotForUid(Context context) {
- // TODO: take snapshot locally, since proc file is now visible
- final int uid = android.os.Process.myUid();
- try {
- return getStatsService().getDataLayerSnapshotForUid(uid);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return set of any ifaces associated with mobile networks since boot.
- * Interfaces are never removed from this list, so counters should always be
- * monotonic.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
- private static String[] getMobileIfaces() {
- try {
- return getStatsService().getMobileIfaces();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- // NOTE: keep these in sync with {@code com_android_server_net_NetworkStatsService.cpp}.
- /** {@hide} */
- public static final int TYPE_RX_BYTES = 0;
- /** {@hide} */
- public static final int TYPE_RX_PACKETS = 1;
- /** {@hide} */
- public static final int TYPE_TX_BYTES = 2;
- /** {@hide} */
- public static final int TYPE_TX_PACKETS = 3;
- /** {@hide} */
- public static final int TYPE_TCP_RX_PACKETS = 4;
- /** {@hide} */
- public static final int TYPE_TCP_TX_PACKETS = 5;
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl
deleted file mode 100644
index a56f2f4..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2015 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 UnderlyingNetworkInfo;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
deleted file mode 100644
index 33f9375..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2015 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 android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A lightweight container used to carry information on the networks that underly a given
- * virtual network.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class UnderlyingNetworkInfo implements Parcelable {
- /** The owner of this network. */
- private final int mOwnerUid;
-
- /** The interface name of this network. */
- @NonNull
- private final String mIface;
-
- /** The names of the interfaces underlying this network. */
- @NonNull
- private final List<String> mUnderlyingIfaces;
-
- public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface,
- @NonNull List<String> underlyingIfaces) {
- Objects.requireNonNull(iface);
- Objects.requireNonNull(underlyingIfaces);
- mOwnerUid = ownerUid;
- mIface = iface;
- mUnderlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces));
- }
-
- private UnderlyingNetworkInfo(@NonNull Parcel in) {
- mOwnerUid = in.readInt();
- mIface = in.readString();
- List<String> underlyingIfaces = new ArrayList<>();
- in.readList(underlyingIfaces, null /*classLoader*/);
- mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces);
- }
-
- /** Get the owner of this network. */
- public int getOwnerUid() {
- return mOwnerUid;
- }
-
- /** Get the interface name of this network. */
- @NonNull
- public String getInterface() {
- return mIface;
- }
-
- /** Get the names of the interfaces underlying this network. */
- @NonNull
- public List<String> getUnderlyingInterfaces() {
- return mUnderlyingIfaces;
- }
-
- @Override
- public String toString() {
- return "UnderlyingNetworkInfo{"
- + "ownerUid=" + mOwnerUid
- + ", iface='" + mIface + '\''
- + ", underlyingIfaces='" + mUnderlyingIfaces.toString() + '\''
- + '}';
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mOwnerUid);
- dest.writeString(mIface);
- dest.writeList(mUnderlyingIfaces);
- }
-
- @NonNull
- public static final Parcelable.Creator<UnderlyingNetworkInfo> CREATOR =
- new Parcelable.Creator<UnderlyingNetworkInfo>() {
- @NonNull
- @Override
- public UnderlyingNetworkInfo createFromParcel(@NonNull Parcel in) {
- return new UnderlyingNetworkInfo(in);
- }
-
- @NonNull
- @Override
- public UnderlyingNetworkInfo[] newArray(int size) {
- return new UnderlyingNetworkInfo[size];
- }
- };
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof UnderlyingNetworkInfo)) return false;
- final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o;
- return mOwnerUid == that.getOwnerUid()
- && Objects.equals(mIface, that.getInterface())
- && Objects.equals(mUnderlyingIfaces, that.getUnderlyingInterfaces());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mOwnerUid, mIface, mUnderlyingIfaces);
- }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
deleted file mode 100644
index 4e8a5b2..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2022 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.netstats;
-
-import android.net.DataUsageRequest;
-
-/**
- * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback.
- *
- * @hide
- */
-oneway interface IUsageCallback {
- void onThresholdReached(in DataUsageRequest request);
- void onCallbackReleased(in DataUsageRequest request);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl
deleted file mode 100644
index 74c3ba4..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.netstats.provider;
-
-/**
- * Interface for NetworkStatsService to query network statistics and set data limits.
- *
- * @hide
- */
-oneway interface INetworkStatsProvider {
- void onRequestStatsUpdate(int token);
- void onSetAlert(long quotaBytes);
- void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
deleted file mode 100644
index 01ff02d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.netstats.provider;
-
-import android.net.NetworkStats;
-
-/**
- * Interface for implementor of {@link INetworkStatsProviderCallback} to push events
- * such as network statistics update or notify limit reached.
- * @hide
- */
-oneway interface INetworkStatsProviderCallback {
- void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
- void notifyAlertReached();
- void notifyWarningReached();
- void notifyLimitReached();
- void unregister();
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
deleted file mode 100644
index d37a53d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2020 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.netstats.provider;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.net.NetworkStats;
-import android.os.RemoteException;
-
-/**
- * A base class that allows external modules to implement a custom network statistics provider.
- * @hide
- */
-@SystemApi
-public abstract class NetworkStatsProvider {
- /**
- * A value used by {@link #onSetLimit}, {@link #onSetAlert} and {@link #onSetWarningAndLimit}
- * indicates there is no limit.
- */
- public static final int QUOTA_UNLIMITED = -1;
-
- @NonNull private final INetworkStatsProvider mProviderBinder =
- new INetworkStatsProvider.Stub() {
-
- @Override
- public void onRequestStatsUpdate(int token) {
- NetworkStatsProvider.this.onRequestStatsUpdate(token);
- }
-
- @Override
- public void onSetAlert(long quotaBytes) {
- NetworkStatsProvider.this.onSetAlert(quotaBytes);
- }
-
- @Override
- public void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes) {
- NetworkStatsProvider.this.onSetWarningAndLimit(iface, warningBytes, limitBytes);
- }
- };
-
- // The binder given by the service when successfully registering. Only null before registering,
- // never null once non-null.
- @Nullable
- private INetworkStatsProviderCallback mProviderCbBinder;
-
- /**
- * Return the binder invoked by the service and redirect function calls to the overridden
- * methods.
- * @hide
- */
- @NonNull
- public INetworkStatsProvider getProviderBinder() {
- return mProviderBinder;
- }
-
- /**
- * Store the binder that was returned by the service when successfully registering. Note that
- * the provider cannot be re-registered. Hence this method can only be called once per provider.
- *
- * @hide
- */
- public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) {
- if (mProviderCbBinder != null) {
- throw new IllegalArgumentException("provider is already registered");
- }
- mProviderCbBinder = binder;
- }
-
- /**
- * Get the binder that was returned by the service when successfully registering. Or null if the
- * provider was never registered.
- *
- * @hide
- */
- @Nullable
- public INetworkStatsProviderCallback getProviderCallbackBinder() {
- return mProviderCbBinder;
- }
-
- /**
- * Get the binder that was returned by the service when successfully registering. Throw an
- * {@link IllegalStateException} if the provider is not registered.
- *
- * @hide
- */
- @NonNull
- public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() {
- if (mProviderCbBinder == null) {
- throw new IllegalStateException("the provider is not registered");
- }
- return mProviderCbBinder;
- }
-
- /**
- * Notify the system of new network statistics.
- *
- * Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must
- * be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)}
- * being called. Responding later increases the probability stats will be dropped. The
- * provider can also call this whenever it wants to reports new stats for any reason.
- * Note that the system will not necessarily immediately propagate the statistics to
- * reflect the update.
- *
- * @param token the token under which these stats were gathered. Providers can call this method
- * with the current token as often as they want, until the token changes.
- * {@see NetworkStatsProvider#onRequestStatsUpdate()}
- * @param ifaceStats the {@link NetworkStats} per interface to be reported.
- * The provider should not include any traffic that is already counted by
- * kernel interface counters.
- * @param uidStats the same stats as above, but counts {@link NetworkStats}
- * per uid.
- */
- public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
- @NonNull NetworkStats uidStats) {
- try {
- getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Notify system that the quota set by {@code onSetAlert} has been reached.
- */
- public void notifyAlertReached() {
- try {
- getProviderCallbackBinderOrThrow().notifyAlertReached();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached.
- */
- public void notifyWarningReached() {
- try {
- // Reuse the code path to notify warning reached with limit reached
- // since framework handles them in the same way.
- getProviderCallbackBinderOrThrow().notifyWarningReached();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Notify system that the limit set by {@link #onSetLimit} or limit set by
- * {@link #onSetWarningAndLimit} has been reached.
- */
- public void notifyLimitReached() {
- try {
- getProviderCallbackBinderOrThrow().notifyLimitReached();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Called by {@code NetworkStatsService} when it requires to know updated stats.
- * The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible.
- * Responding later increases the probability stats will be dropped. Memory allowing, the
- * system will try to take stats into account up to one minute after calling
- * {@link #onRequestStatsUpdate}.
- *
- * @param token a positive number identifying the new state of the system under which
- * {@link NetworkStats} have to be gathered from now on. When this is called,
- * custom implementations of providers MUST tally and report the latest stats with
- * the previous token, under which stats were being gathered so far.
- */
- public abstract void onRequestStatsUpdate(int token);
-
- /**
- * Called by {@code NetworkStatsService} when setting the interface quota for the specified
- * upstream interface. When this is called, the custom implementation should block all egress
- * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
- * been reached, and MUST respond to it by calling
- * {@link NetworkStatsProvider#notifyLimitReached()}.
- *
- * @param iface the interface requiring the operation.
- * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
- * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
- */
- public abstract void onSetLimit(@NonNull String iface, long quotaBytes);
-
- /**
- * Called by {@code NetworkStatsService} when setting the interface quotas for the specified
- * upstream interface. If a provider implements {@link #onSetWarningAndLimit}, the system
- * will not call {@link #onSetLimit}. When this method is called, the implementation
- * should behave as follows:
- * 1. If {@code warningBytes} is reached on {@code iface}, block all further traffic on
- * {@code iface} and call {@link NetworkStatsProvider@notifyWarningReached()}.
- * 2. If {@code limitBytes} is reached on {@code iface}, block all further traffic on
- * {@code iface} and call {@link NetworkStatsProvider#notifyLimitReached()}.
- *
- * @param iface the interface requiring the operation.
- * @param warningBytes the warning defined as the number of bytes, starting from zero and
- * counting from now. A value of {@link #QUOTA_UNLIMITED} indicates
- * there is no warning.
- * @param limitBytes the limit defined as the number of bytes, starting from zero and counting
- * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
- */
- public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) {
- // Backward compatibility for those who didn't override this function.
- onSetLimit(iface, limitBytes);
- }
-
- /**
- * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
- * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes
- * have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should
- * not block all egress packets.
- *
- * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
- * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
- */
- public abstract void onSetAlert(long quotaBytes);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl
deleted file mode 100644
index 89e9cdb..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.INsdServiceConnector;
-import android.os.Messenger;
-
-/**
- * Interface that NsdService implements to connect NsdManager clients.
- *
- * {@hide}
- */
-interface INsdManager {
- INsdServiceConnector connect(INsdManagerCallback cb);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
deleted file mode 100644
index 1a262ec..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
deleted file mode 100644
index b06ae55..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
deleted file mode 100644
index 512fbce..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
+++ /dev/null
@@ -1,1005 +0,0 @@
-/*
- * 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.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemService;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.Network;
-import android.net.NetworkRequest;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Objects;
-
-/**
- * The Network Service Discovery Manager class provides the API to discover services
- * on a network. As an example, if device A and device B are connected over a Wi-Fi
- * network, a game registered on device A can be discovered by a game on device
- * B. Another example use case is an application discovering printers on the network.
- *
- * <p> The API currently supports DNS based service discovery and discovery is currently
- * limited to a local network over Multicast DNS. DNS service discovery is described at
- * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
- *
- * <p> The API is asynchronous, and responses to requests from an application are on listener
- * callbacks on a separate internal thread.
- *
- * <p> There are three main operations the API supports - registration, discovery and resolution.
- * <pre>
- * Application start
- * |
- * |
- * | onServiceRegistered()
- * Register any local services /
- * to be advertised with \
- * registerService() onRegistrationFailed()
- * |
- * |
- * discoverServices()
- * |
- * Maintain a list to track
- * discovered services
- * |
- * |--------->
- * | |
- * | onServiceFound()
- * | |
- * | add service to list
- * | |
- * |<----------
- * |
- * |--------->
- * | |
- * | onServiceLost()
- * | |
- * | remove service from list
- * | |
- * |<----------
- * |
- * |
- * | Connect to a service
- * | from list ?
- * |
- * resolveService()
- * |
- * onServiceResolved()
- * |
- * Establish connection to service
- * with the host and port information
- *
- * </pre>
- * An application that needs to advertise itself over a network for other applications to
- * discover it can do so with a call to {@link #registerService}. If Example is a http based
- * application that can provide HTML data to peer services, it can register a name "Example"
- * with service type "_http._tcp". A successful registration is notified with a callback to
- * {@link RegistrationListener#onServiceRegistered} and a failure to register is notified
- * over {@link RegistrationListener#onRegistrationFailed}
- *
- * <p> A peer application looking for http services can initiate a discovery for "_http._tcp"
- * with a call to {@link #discoverServices}. A service found is notified with a callback
- * to {@link DiscoveryListener#onServiceFound} and a service lost is notified on
- * {@link DiscoveryListener#onServiceLost}.
- *
- * <p> Once the peer application discovers the "Example" http service, and either needs to read the
- * attributes of the service or wants to receive data from the "Example" application, it can
- * initiate a resolve with {@link #resolveService} to resolve the attributes, host, and port
- * details. A successful resolve is notified on {@link ResolveListener#onServiceResolved} and a
- * failure is notified on {@link ResolveListener#onResolveFailed}.
- *
- * Applications can reserve for a service type at
- * http://www.iana.org/form/ports-service. Existing services can be found at
- * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
- *
- * {@see NsdServiceInfo}
- */
-@SystemService(Context.NSD_SERVICE)
-public final class NsdManager {
- private static final String TAG = NsdManager.class.getSimpleName();
- private static final boolean DBG = false;
-
- /**
- * When enabled, apps targeting < Android 12 are considered legacy for
- * the NSD native daemon.
- * The platform will only keep the daemon running as long as there are
- * any legacy apps connected.
- *
- * After Android 12, directly communicate with native daemon might not
- * work since the native damon won't always stay alive.
- * Use the NSD APIs from NsdManager as the replacement is recommended.
- * An another alternative could be bundling your own mdns solutions instead of
- * depending on the system mdns native daemon.
- *
- * @hide
- */
- @ChangeId
- @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
- public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS = 191844585L;
-
- /**
- * Broadcast intent action to indicate whether network service discovery is
- * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
- * information as int.
- *
- * @see #EXTRA_NSD_STATE
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
-
- /**
- * The lookup key for an int that indicates whether network service discovery is enabled
- * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
- *
- * @see #NSD_STATE_DISABLED
- * @see #NSD_STATE_ENABLED
- */
- public static final String EXTRA_NSD_STATE = "nsd_state";
-
- /**
- * Network service discovery is disabled
- *
- * @see #ACTION_NSD_STATE_CHANGED
- */
- public static final int NSD_STATE_DISABLED = 1;
-
- /**
- * Network service discovery is enabled
- *
- * @see #ACTION_NSD_STATE_CHANGED
- */
- public static final int NSD_STATE_ENABLED = 2;
-
- /** @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 STOP_DISCOVERY = 6;
- /** @hide */
- public static final int STOP_DISCOVERY_FAILED = 7;
- /** @hide */
- public static final int STOP_DISCOVERY_SUCCEEDED = 8;
-
- /** @hide */
- public static final int REGISTER_SERVICE = 9;
- /** @hide */
- public static final int REGISTER_SERVICE_FAILED = 10;
- /** @hide */
- public static final int REGISTER_SERVICE_SUCCEEDED = 11;
-
- /** @hide */
- public static final int UNREGISTER_SERVICE = 12;
- /** @hide */
- public static final int UNREGISTER_SERVICE_FAILED = 13;
- /** @hide */
- public static final int UNREGISTER_SERVICE_SUCCEEDED = 14;
-
- /** @hide */
- public static final int RESOLVE_SERVICE = 15;
- /** @hide */
- public static final int RESOLVE_SERVICE_FAILED = 16;
- /** @hide */
- public static final int RESOLVE_SERVICE_SUCCEEDED = 17;
-
- /** @hide */
- public static final int DAEMON_CLEANUP = 18;
-
- /** @hide */
- public static final int DAEMON_STARTUP = 19;
-
- /** @hide */
- public static final int ENABLE = 20;
- /** @hide */
- public static final int DISABLE = 21;
-
- /** @hide */
- public static final int NATIVE_DAEMON_EVENT = 22;
-
- /** @hide */
- 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;
-
- private static final SparseArray<String> EVENT_NAMES = new SparseArray<>();
- static {
- EVENT_NAMES.put(DISCOVER_SERVICES, "DISCOVER_SERVICES");
- EVENT_NAMES.put(DISCOVER_SERVICES_STARTED, "DISCOVER_SERVICES_STARTED");
- EVENT_NAMES.put(DISCOVER_SERVICES_FAILED, "DISCOVER_SERVICES_FAILED");
- EVENT_NAMES.put(SERVICE_FOUND, "SERVICE_FOUND");
- EVENT_NAMES.put(SERVICE_LOST, "SERVICE_LOST");
- EVENT_NAMES.put(STOP_DISCOVERY, "STOP_DISCOVERY");
- EVENT_NAMES.put(STOP_DISCOVERY_FAILED, "STOP_DISCOVERY_FAILED");
- EVENT_NAMES.put(STOP_DISCOVERY_SUCCEEDED, "STOP_DISCOVERY_SUCCEEDED");
- EVENT_NAMES.put(REGISTER_SERVICE, "REGISTER_SERVICE");
- EVENT_NAMES.put(REGISTER_SERVICE_FAILED, "REGISTER_SERVICE_FAILED");
- EVENT_NAMES.put(REGISTER_SERVICE_SUCCEEDED, "REGISTER_SERVICE_SUCCEEDED");
- EVENT_NAMES.put(UNREGISTER_SERVICE, "UNREGISTER_SERVICE");
- EVENT_NAMES.put(UNREGISTER_SERVICE_FAILED, "UNREGISTER_SERVICE_FAILED");
- EVENT_NAMES.put(UNREGISTER_SERVICE_SUCCEEDED, "UNREGISTER_SERVICE_SUCCEEDED");
- EVENT_NAMES.put(RESOLVE_SERVICE, "RESOLVE_SERVICE");
- EVENT_NAMES.put(RESOLVE_SERVICE_FAILED, "RESOLVE_SERVICE_FAILED");
- EVENT_NAMES.put(RESOLVE_SERVICE_SUCCEEDED, "RESOLVE_SERVICE_SUCCEEDED");
- EVENT_NAMES.put(DAEMON_CLEANUP, "DAEMON_CLEANUP");
- EVENT_NAMES.put(DAEMON_STARTUP, "DAEMON_STARTUP");
- EVENT_NAMES.put(ENABLE, "ENABLE");
- EVENT_NAMES.put(DISABLE, "DISABLE");
- EVENT_NAMES.put(NATIVE_DAEMON_EVENT, "NATIVE_DAEMON_EVENT");
- }
-
- /** @hide */
- public static String nameOf(int event) {
- String name = EVENT_NAMES.get(event);
- if (name == null) {
- return Integer.toString(event);
- }
- return name;
- }
-
- private static final int FIRST_LISTENER_KEY = 1;
-
- private final INsdServiceConnector mService;
- private final Context mContext;
-
- private int mListenerKey = FIRST_LISTENER_KEY;
- private final SparseArray mListenerMap = new SparseArray();
- private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
- private final Object mMapLock = new Object();
- // Map of listener key sent by client -> per-network discovery tracker
- @GuardedBy("mPerNetworkDiscoveryMap")
- private final ArrayMap<Integer, PerNetworkDiscoveryTracker>
- mPerNetworkDiscoveryMap = new ArrayMap<>();
-
- private final ServiceHandler mHandler;
-
- private class PerNetworkDiscoveryTracker {
- final String mServiceType;
- final int mProtocolType;
- final DiscoveryListener mBaseListener;
- final ArrayMap<Network, DelegatingDiscoveryListener> mPerNetworkListeners =
- new ArrayMap<>();
-
- final NetworkCallback mNetworkCb = new NetworkCallback() {
- @Override
- public void onAvailable(@NonNull Network network) {
- final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener(
- network, mBaseListener);
- mPerNetworkListeners.put(network, wrappedListener);
- discoverServices(mServiceType, mProtocolType, network, wrappedListener);
- }
-
- @Override
- public void onLost(@NonNull Network network) {
- final DelegatingDiscoveryListener listener = mPerNetworkListeners.get(network);
- if (listener == null) return;
- listener.notifyAllServicesLost();
- // Listener will be removed from map in discovery stopped callback
- stopServiceDiscovery(listener);
- }
- };
-
- // Accessed from mHandler
- private boolean mStopRequested;
-
- public void start(@NonNull NetworkRequest request) {
- final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
- cm.registerNetworkCallback(request, mNetworkCb, mHandler);
- mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType));
- }
-
- /**
- * Stop discovery on all networks tracked by this class.
- *
- * This will request all underlying listeners to stop, and the last one to stop will call
- * onDiscoveryStopped or onStopDiscoveryFailed.
- *
- * Must be called on the handler thread.
- */
- public void requestStop() {
- mHandler.post(() -> {
- mStopRequested = true;
- final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
- cm.unregisterNetworkCallback(mNetworkCb);
- if (mPerNetworkListeners.size() == 0) {
- mBaseListener.onDiscoveryStopped(mServiceType);
- return;
- }
- for (int i = 0; i < mPerNetworkListeners.size(); i++) {
- final DelegatingDiscoveryListener listener = mPerNetworkListeners.valueAt(i);
- stopServiceDiscovery(listener);
- }
- });
- }
-
- private PerNetworkDiscoveryTracker(String serviceType, int protocolType,
- DiscoveryListener baseListener) {
- mServiceType = serviceType;
- mProtocolType = protocolType;
- mBaseListener = baseListener;
- }
-
- /**
- * Subset of NsdServiceInfo that is tracked to generate service lost notifications when a
- * network is lost.
- *
- * Service lost notifications only contain service name, type and network, so only track
- * that information (Network is known from the listener). This also implements
- * equals/hashCode for usage in maps.
- */
- private class TrackedNsdInfo {
- private final String mServiceName;
- private final String mServiceType;
- TrackedNsdInfo(NsdServiceInfo info) {
- mServiceName = info.getServiceName();
- mServiceType = info.getServiceType();
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mServiceName, mServiceType);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof TrackedNsdInfo)) return false;
- final TrackedNsdInfo other = (TrackedNsdInfo) obj;
- return Objects.equals(mServiceName, other.mServiceName)
- && Objects.equals(mServiceType, other.mServiceType);
- }
- }
-
- private class DelegatingDiscoveryListener implements DiscoveryListener {
- private final Network mNetwork;
- private final DiscoveryListener mWrapped;
- private final ArraySet<TrackedNsdInfo> mFoundInfo = new ArraySet<>();
-
- private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) {
- mNetwork = network;
- mWrapped = listener;
- }
-
- void notifyAllServicesLost() {
- for (int i = 0; i < mFoundInfo.size(); i++) {
- final TrackedNsdInfo trackedInfo = mFoundInfo.valueAt(i);
- final NsdServiceInfo serviceInfo = new NsdServiceInfo(
- trackedInfo.mServiceName, trackedInfo.mServiceType);
- serviceInfo.setNetwork(mNetwork);
- mWrapped.onServiceLost(serviceInfo);
- }
- }
-
- @Override
- public void onStartDiscoveryFailed(String serviceType, int errorCode) {
- // The delegated listener is used when NsdManager takes care of starting/stopping
- // discovery on multiple networks. Failure to start on one network is not a global
- // failure to be reported up, as other networks may succeed: just log.
- Log.e(TAG, "Failed to start discovery for " + serviceType + " on " + mNetwork
- + " with code " + errorCode);
- mPerNetworkListeners.remove(mNetwork);
- }
-
- @Override
- public void onDiscoveryStarted(String serviceType) {
- // Wrapped listener was called upon registration, it is not called for discovery
- // on each network
- }
-
- @Override
- public void onStopDiscoveryFailed(String serviceType, int errorCode) {
- Log.e(TAG, "Failed to stop discovery for " + serviceType + " on " + mNetwork
- + " with code " + errorCode);
- mPerNetworkListeners.remove(mNetwork);
- if (mStopRequested && mPerNetworkListeners.size() == 0) {
- // Do not report onStopDiscoveryFailed when some underlying listeners failed:
- // this does not mean that all listeners did, and onStopDiscoveryFailed is not
- // actionable anyway. Just report that discovery stopped.
- mWrapped.onDiscoveryStopped(serviceType);
- }
- }
-
- @Override
- public void onDiscoveryStopped(String serviceType) {
- mPerNetworkListeners.remove(mNetwork);
- if (mStopRequested && mPerNetworkListeners.size() == 0) {
- mWrapped.onDiscoveryStopped(serviceType);
- }
- }
-
- @Override
- public void onServiceFound(NsdServiceInfo serviceInfo) {
- mFoundInfo.add(new TrackedNsdInfo(serviceInfo));
- mWrapped.onServiceFound(serviceInfo);
- }
-
- @Override
- public void onServiceLost(NsdServiceInfo serviceInfo) {
- mFoundInfo.remove(new TrackedNsdInfo(serviceInfo));
- mWrapped.onServiceLost(serviceInfo);
- }
- }
- }
-
- /**
- * Create a new Nsd instance. Applications use
- * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
- * {@link android.content.Context#NSD_SERVICE Context.NSD_SERVICE}.
- * @param service the Binder interface
- * @hide - hide this because it takes in a parameter of type INsdManager, which
- * is a system private class.
- */
- public NsdManager(Context context, INsdManager service) {
- mContext = context;
-
- 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
- }
- }
- }
-
- 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);
- }
- }
-
- /**
- * Failures are passed with {@link RegistrationListener#onRegistrationFailed},
- * {@link RegistrationListener#onUnregistrationFailed},
- * {@link DiscoveryListener#onStartDiscoveryFailed},
- * {@link DiscoveryListener#onStopDiscoveryFailed} or {@link ResolveListener#onResolveFailed}.
- *
- * Indicates that the operation failed due to an internal error.
- */
- public static final int FAILURE_INTERNAL_ERROR = 0;
-
- /**
- * Indicates that the operation failed because it is already active.
- */
- public static final int FAILURE_ALREADY_ACTIVE = 3;
-
- /**
- * Indicates that the operation failed because the maximum outstanding
- * requests from the applications have reached.
- */
- public static final int FAILURE_MAX_LIMIT = 4;
-
- /** Interface for callback invocation for service discovery */
- public interface DiscoveryListener {
-
- public void onStartDiscoveryFailed(String serviceType, int errorCode);
-
- public void onStopDiscoveryFailed(String serviceType, int errorCode);
-
- public void onDiscoveryStarted(String serviceType);
-
- public void onDiscoveryStopped(String serviceType);
-
- public void onServiceFound(NsdServiceInfo serviceInfo);
-
- public void onServiceLost(NsdServiceInfo serviceInfo);
- }
-
- /** Interface for callback invocation for service registration */
- public interface RegistrationListener {
-
- public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode);
-
- public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode);
-
- public void onServiceRegistered(NsdServiceInfo serviceInfo);
-
- public void onServiceUnregistered(NsdServiceInfo serviceInfo);
- }
-
- /** Interface for callback invocation for service resolution */
- public interface ResolveListener {
-
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode);
-
- public void onServiceResolved(NsdServiceInfo serviceInfo);
- }
-
- @VisibleForTesting
- class ServiceHandler extends Handler {
- ServiceHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message message) {
- final int what = message.what;
- final int key = message.arg2;
- final Object listener;
- final NsdServiceInfo ns;
- synchronized (mMapLock) {
- listener = mListenerMap.get(key);
- ns = mServiceMap.get(key);
- }
- if (listener == null) {
- Log.d(TAG, "Stale key " + message.arg2);
- return;
- }
- if (DBG) {
- Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns);
- }
- switch (what) {
- case DISCOVER_SERVICES_STARTED:
- String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
- ((DiscoveryListener) listener).onDiscoveryStarted(s);
- break;
- case DISCOVER_SERVICES_FAILED:
- removeListener(key);
- ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns),
- message.arg1);
- break;
- case SERVICE_FOUND:
- ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj);
- break;
- case SERVICE_LOST:
- ((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj);
- break;
- case STOP_DISCOVERY_FAILED:
- // TODO: failure to stop discovery should be internal and retried internally, as
- // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED
- removeListener(key);
- ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
- message.arg1);
- break;
- case STOP_DISCOVERY_SUCCEEDED:
- removeListener(key);
- ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns));
- break;
- case REGISTER_SERVICE_FAILED:
- removeListener(key);
- ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1);
- break;
- case REGISTER_SERVICE_SUCCEEDED:
- ((RegistrationListener) listener).onServiceRegistered(
- (NsdServiceInfo) message.obj);
- break;
- case UNREGISTER_SERVICE_FAILED:
- removeListener(key);
- ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
- break;
- case UNREGISTER_SERVICE_SUCCEEDED:
- // TODO: do not unregister listener until service is unregistered, or provide
- // alternative way for unregistering ?
- removeListener(message.arg2);
- ((RegistrationListener) listener).onServiceUnregistered(ns);
- break;
- case RESOLVE_SERVICE_FAILED:
- removeListener(key);
- ((ResolveListener) listener).onResolveFailed(ns, message.arg1);
- break;
- case RESOLVE_SERVICE_SUCCEEDED:
- removeListener(key);
- ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj);
- break;
- default:
- Log.d(TAG, "Ignored " + message);
- break;
- }
- }
- }
-
- private int nextListenerKey() {
- // Ensure mListenerKey >= FIRST_LISTENER_KEY;
- mListenerKey = Math.max(FIRST_LISTENER_KEY, mListenerKey + 1);
- return mListenerKey;
- }
-
- // Assert that the listener is not in the map, then add it and returns its key
- private int putListener(Object listener, NsdServiceInfo s) {
- checkListener(listener);
- final int key;
- synchronized (mMapLock) {
- int valueIndex = mListenerMap.indexOfValue(listener);
- if (valueIndex != -1) {
- throw new IllegalArgumentException("listener already in use");
- }
- key = nextListenerKey();
- mListenerMap.put(key, listener);
- mServiceMap.put(key, s);
- }
- return key;
- }
-
- private void removeListener(int key) {
- synchronized (mMapLock) {
- mListenerMap.remove(key);
- mServiceMap.remove(key);
- }
- }
-
- private int getListenerKey(Object listener) {
- checkListener(listener);
- synchronized (mMapLock) {
- int valueIndex = mListenerMap.indexOfValue(listener);
- if (valueIndex == -1) {
- throw new IllegalArgumentException("listener not registered");
- }
- return mListenerMap.keyAt(valueIndex);
- }
- }
-
- private static String getNsdServiceInfoType(NsdServiceInfo s) {
- if (s == null) return "?";
- return s.getServiceType();
- }
-
- /**
- * Register a service to be discovered by other services.
- *
- * <p> The function call immediately returns after sending a request to register service
- * to the framework. The application is notified of a successful registration
- * through the callback {@link RegistrationListener#onServiceRegistered} or a failure
- * through {@link RegistrationListener#onRegistrationFailed}.
- *
- * <p> The application should call {@link #unregisterService} when the service
- * registration is no longer required, and/or whenever the application is stopped.
- *
- * @param serviceInfo The service being registered
- * @param protocolType The service discovery protocol
- * @param listener The listener notifies of a successful registration and is used to
- * unregister this service through a call on {@link #unregisterService}. Cannot be null.
- * Cannot be in use for an active service registration.
- */
- public void registerService(NsdServiceInfo serviceInfo, int protocolType,
- RegistrationListener listener) {
- if (serviceInfo.getPort() <= 0) {
- throw new IllegalArgumentException("Invalid port number");
- }
- checkServiceInfo(serviceInfo);
- checkProtocol(protocolType);
- int key = putListener(listener, serviceInfo);
- try {
- mService.registerService(key, serviceInfo);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Unregister a service registered through {@link #registerService}. A successful
- * unregister is notified to the application with a call to
- * {@link RegistrationListener#onServiceUnregistered}.
- *
- * @param listener This should be the listener object that was passed to
- * {@link #registerService}. It identifies the service that should be unregistered
- * and notifies of a successful or unsuccessful unregistration via the listener
- * callbacks. In API versions 20 and above, the listener object may be used for
- * another service registration once the callback has been called. In API versions <= 19,
- * there is no entirely reliable way to know when a listener may be re-used, and a new
- * listener should be created for each service registration request.
- */
- public void unregisterService(RegistrationListener listener) {
- int id = getListenerKey(listener);
- try {
- mService.unregisterService(id);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Same as {@link #discoverServices(String, int, Network, DiscoveryListener)} with a null
- * {@link Network}.
- */
- public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
- discoverServices(serviceType, protocolType, (Network) null, listener);
- }
-
- /**
- * Initiate service discovery to browse for instances of a service type. Service discovery
- * consumes network bandwidth and will continue until the application calls
- * {@link #stopServiceDiscovery}.
- *
- * <p> The function call immediately returns after sending a request to start service
- * discovery to the framework. The application is notified of a success to initiate
- * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
- * through {@link DiscoveryListener#onStartDiscoveryFailed}.
- *
- * <p> Upon successful start, application is notified when a service is found with
- * {@link DiscoveryListener#onServiceFound} or when a service is lost with
- * {@link DiscoveryListener#onServiceLost}.
- *
- * <p> Upon failure to start, service discovery is not active and application does
- * not need to invoke {@link #stopServiceDiscovery}
- *
- * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
- * service type is no longer required, and/or whenever the application is paused or
- * stopped.
- *
- * @param serviceType The service type being discovered. Examples include "_http._tcp" for
- * http services or "_ipp._tcp" for printers
- * @param protocolType The service discovery protocol
- * @param network Network to discover services on, or null to discover on all available networks
- * @param listener The listener notifies of a successful discovery and is used
- * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
- * Cannot be null. Cannot be in use for an active service discovery.
- */
- public void discoverServices(@NonNull String serviceType, int protocolType,
- @Nullable Network network, @NonNull DiscoveryListener listener) {
- if (TextUtils.isEmpty(serviceType)) {
- throw new IllegalArgumentException("Service type cannot be empty");
- }
- checkProtocol(protocolType);
-
- NsdServiceInfo s = new NsdServiceInfo();
- s.setServiceType(serviceType);
- s.setNetwork(network);
-
- int key = putListener(listener, s);
- try {
- mService.discoverServices(key, s);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Initiate service discovery to browse for instances of a service type. Service discovery
- * consumes network bandwidth and will continue until the application calls
- * {@link #stopServiceDiscovery}.
- *
- * <p> The function call immediately returns after sending a request to start service
- * discovery to the framework. The application is notified of a success to initiate
- * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
- * through {@link DiscoveryListener#onStartDiscoveryFailed}.
- *
- * <p> Upon successful start, application is notified when a service is found with
- * {@link DiscoveryListener#onServiceFound} or when a service is lost with
- * {@link DiscoveryListener#onServiceLost}.
- *
- * <p> Upon failure to start, service discovery is not active and application does
- * not need to invoke {@link #stopServiceDiscovery}
- *
- * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
- * service type is no longer required, and/or whenever the application is paused or
- * stopped.
- *
- * <p> During discovery, new networks may connect or existing networks may disconnect - for
- * example if wifi is reconnected. When a service was found on a network that disconnects,
- * {@link DiscoveryListener#onServiceLost} will be called. If a new network connects that
- * matches the {@link NetworkRequest}, {@link DiscoveryListener#onServiceFound} will be called
- * for services found on that network. Applications that do not want to track networks
- * themselves are encouraged to use this method instead of other overloads of
- * {@code discoverServices}, as they will receive proper notifications when a service becomes
- * available or unavailable due to network changes.
- *
- * @param serviceType The service type being discovered. Examples include "_http._tcp" for
- * http services or "_ipp._tcp" for printers
- * @param protocolType The service discovery protocol
- * @param networkRequest Request specifying networks that should be considered when discovering
- * @param listener The listener notifies of a successful discovery and is used
- * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
- * Cannot be null. Cannot be in use for an active service discovery.
- */
- @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
- public void discoverServices(@NonNull String serviceType, int protocolType,
- @NonNull NetworkRequest networkRequest, @NonNull DiscoveryListener listener) {
- if (TextUtils.isEmpty(serviceType)) {
- throw new IllegalArgumentException("Service type cannot be empty");
- }
- Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null");
- checkProtocol(protocolType);
-
- NsdServiceInfo s = new NsdServiceInfo();
- s.setServiceType(serviceType);
-
- final int baseListenerKey = putListener(listener, s);
-
- final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker(
- serviceType, protocolType, listener);
-
- synchronized (mPerNetworkDiscoveryMap) {
- mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo);
- discoveryInfo.start(networkRequest);
- }
- }
-
- /**
- * Stop service discovery initiated with {@link #discoverServices}. An active service
- * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted}
- * and it stays active until the application invokes a stop service discovery. A successful
- * stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}.
- *
- * <p> Upon failure to stop service discovery, application is notified through
- * {@link DiscoveryListener#onStopDiscoveryFailed}.
- *
- * @param listener This should be the listener object that was passed to {@link #discoverServices}.
- * It identifies the discovery that should be stopped and notifies of a successful or
- * unsuccessful stop. In API versions 20 and above, the listener object may be used for
- * another service discovery once the callback has been called. In API versions <= 19,
- * there is no entirely reliable way to know when a listener may be re-used, and a new
- * listener should be created for each service discovery request.
- */
- public void stopServiceDiscovery(DiscoveryListener listener) {
- int id = getListenerKey(listener);
- // If this is a PerNetworkDiscovery request, handle it as such
- synchronized (mPerNetworkDiscoveryMap) {
- final PerNetworkDiscoveryTracker info = mPerNetworkDiscoveryMap.get(id);
- if (info != null) {
- info.requestStop();
- return;
- }
- }
- try {
- mService.stopDiscovery(id);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Resolve a discovered service. An application can resolve a service right before
- * establishing a connection to fetch the IP and port details on which to setup
- * the connection.
- *
- * @param serviceInfo service to be resolved
- * @param listener to receive callback upon success or failure. Cannot be null.
- * Cannot be in use for an active service resolution.
- */
- public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
- checkServiceInfo(serviceInfo);
- int key = putListener(listener, serviceInfo);
- try {
- mService.resolveService(key, serviceInfo);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- private static void checkListener(Object listener) {
- Objects.requireNonNull(listener, "listener cannot be null");
- }
-
- private static void checkProtocol(int protocolType) {
- if (protocolType != PROTOCOL_DNS_SD) {
- throw new IllegalArgumentException("Unsupported protocol");
- }
- }
-
- private static void checkServiceInfo(NsdServiceInfo serviceInfo) {
- 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/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
deleted file mode 100644
index 8506db1..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2012 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.annotation.NonNull;
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.net.Network;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Base64;
-import android.util.Log;
-
-import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * A class representing service information for network service discovery
- * {@see NsdManager}
- */
-public final class NsdServiceInfo implements Parcelable {
-
- private static final String TAG = "NsdServiceInfo";
-
- private String mServiceName;
-
- private String mServiceType;
-
- private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<>();
-
- private InetAddress mHost;
-
- private int mPort;
-
- @Nullable
- private Network mNetwork;
-
- public NsdServiceInfo() {
- }
-
- /** @hide */
- public NsdServiceInfo(String sn, String rt) {
- mServiceName = sn;
- mServiceType = rt;
- }
-
- /** Get the service name */
- public String getServiceName() {
- return mServiceName;
- }
-
- /** Set the service name */
- public void setServiceName(String s) {
- mServiceName = s;
- }
-
- /** Get the service type */
- public String getServiceType() {
- return mServiceType;
- }
-
- /** Set the service type */
- public void setServiceType(String s) {
- mServiceType = s;
- }
-
- /** Get the host address. The host address is valid for a resolved service. */
- public InetAddress getHost() {
- return mHost;
- }
-
- /** Set the host address */
- public void setHost(InetAddress s) {
- mHost = s;
- }
-
- /** Get port number. The port number is valid for a resolved service. */
- public int getPort() {
- return mPort;
- }
-
- /** Set port number */
- public void setPort(int p) {
- mPort = p;
- }
-
- /**
- * Unpack txt information from a base-64 encoded byte array.
- *
- * @param rawRecords The raw base64 encoded records string read from netd.
- *
- * @hide
- */
- public void setTxtRecords(@NonNull String rawRecords) {
- byte[] txtRecordsRawBytes = Base64.decode(rawRecords, Base64.DEFAULT);
-
- // There can be multiple TXT records after each other. Each record has to following format:
- //
- // byte type required meaning
- // ------------------- ------------------- -------- ----------------------------------
- // 0 unsigned 8 bit yes size of record excluding this byte
- // 1 - n ASCII but not '=' yes key
- // n + 1 '=' optional separator of key and value
- // n + 2 - record size uninterpreted bytes optional value
- //
- // Example legal records:
- // [11, 'm', 'y', 'k', 'e', 'y', '=', 0x0, 0x4, 0x65, 0x7, 0xff]
- // [17, 'm', 'y', 'K', 'e', 'y', 'W', 'i', 't', 'h', 'N', 'o', 'V', 'a', 'l', 'u', 'e', '=']
- // [12, 'm', 'y', 'B', 'o', 'o', 'l', 'e', 'a', 'n', 'K', 'e', 'y']
- //
- // Example corrupted records
- // [3, =, 1, 2] <- key is empty
- // [3, 0, =, 2] <- key contains non-ASCII character. We handle this by replacing the
- // invalid characters instead of skipping the record.
- // [30, 'a', =, 2] <- length exceeds total left over bytes in the TXT records array, we
- // handle this by reducing the length of the record as needed.
- int pos = 0;
- while (pos < txtRecordsRawBytes.length) {
- // recordLen is an unsigned 8 bit value
- int recordLen = txtRecordsRawBytes[pos] & 0xff;
- pos += 1;
-
- try {
- if (recordLen == 0) {
- throw new IllegalArgumentException("Zero sized txt record");
- } else if (pos + recordLen > txtRecordsRawBytes.length) {
- Log.w(TAG, "Corrupt record length (pos = " + pos + "): " + recordLen);
- recordLen = txtRecordsRawBytes.length - pos;
- }
-
- // Decode key-value records
- String key = null;
- byte[] value = null;
- int valueLen = 0;
- for (int i = pos; i < pos + recordLen; i++) {
- if (key == null) {
- if (txtRecordsRawBytes[i] == '=') {
- key = new String(txtRecordsRawBytes, pos, i - pos,
- StandardCharsets.US_ASCII);
- }
- } else {
- if (value == null) {
- value = new byte[recordLen - key.length() - 1];
- }
- value[valueLen] = txtRecordsRawBytes[i];
- valueLen++;
- }
- }
-
- // If '=' was not found we have a boolean record
- if (key == null) {
- key = new String(txtRecordsRawBytes, pos, recordLen, StandardCharsets.US_ASCII);
- }
-
- if (TextUtils.isEmpty(key)) {
- // Empty keys are not allowed (RFC6763 6.4)
- throw new IllegalArgumentException("Invalid txt record (key is empty)");
- }
-
- if (getAttributes().containsKey(key)) {
- // When we have a duplicate record, the later ones are ignored (RFC6763 6.4)
- throw new IllegalArgumentException("Invalid txt record (duplicate key \"" + key + "\")");
- }
-
- setAttribute(key, value);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "While parsing txt records (pos = " + pos + "): " + e.getMessage());
- }
-
- pos += recordLen;
- }
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public void setAttribute(String key, byte[] value) {
- if (TextUtils.isEmpty(key)) {
- throw new IllegalArgumentException("Key cannot be empty");
- }
-
- // Key must be printable US-ASCII, excluding =.
- for (int i = 0; i < key.length(); ++i) {
- char character = key.charAt(i);
- if (character < 0x20 || character > 0x7E) {
- throw new IllegalArgumentException("Key strings must be printable US-ASCII");
- } else if (character == 0x3D) {
- throw new IllegalArgumentException("Key strings must not include '='");
- }
- }
-
- // Key length + value length must be < 255.
- if (key.length() + (value == null ? 0 : value.length) >= 255) {
- throw new IllegalArgumentException("Key length + value length must be < 255 bytes");
- }
-
- // Warn if key is > 9 characters, as recommended by RFC 6763 section 6.4.
- if (key.length() > 9) {
- Log.w(TAG, "Key lengths > 9 are discouraged: " + key);
- }
-
- // Check against total TXT record size limits.
- // Arbitrary 400 / 1300 byte limits taken from RFC 6763 section 6.2.
- int txtRecordSize = getTxtRecordSize();
- int futureSize = txtRecordSize + key.length() + (value == null ? 0 : value.length) + 2;
- if (futureSize > 1300) {
- throw new IllegalArgumentException("Total length of attributes must be < 1300 bytes");
- } else if (futureSize > 400) {
- Log.w(TAG, "Total length of all attributes exceeds 400 bytes; truncation may occur");
- }
-
- mTxtRecord.put(key, value);
- }
-
- /**
- * Add a service attribute as a key/value pair.
- *
- * <p> Service attributes are included as DNS-SD TXT record pairs.
- *
- * <p> The key must be US-ASCII printable characters, excluding the '=' character. Values may
- * be UTF-8 strings or null. The total length of key + value must be less than 255 bytes.
- *
- * <p> Keys should be short, ideally no more than 9 characters, and unique per instance of
- * {@link NsdServiceInfo}. Calling {@link #setAttribute} twice with the same key will overwrite
- * first value.
- */
- public void setAttribute(String key, String value) {
- try {
- setAttribute(key, value == null ? (byte []) null : value.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException("Value must be UTF-8");
- }
- }
-
- /** Remove an attribute by key */
- public void removeAttribute(String key) {
- mTxtRecord.remove(key);
- }
-
- /**
- * Retrieve attributes as a map of String keys to byte[] values. The attributes map is only
- * valid for a resolved service.
- *
- * <p> The returned map is unmodifiable; changes must be made through {@link #setAttribute} and
- * {@link #removeAttribute}.
- */
- public Map<String, byte[]> getAttributes() {
- return Collections.unmodifiableMap(mTxtRecord);
- }
-
- private int getTxtRecordSize() {
- int txtRecordSize = 0;
- for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
- txtRecordSize += 2; // One for the length byte, one for the = between key and value.
- txtRecordSize += entry.getKey().length();
- byte[] value = entry.getValue();
- txtRecordSize += value == null ? 0 : value.length;
- }
- return txtRecordSize;
- }
-
- /** @hide */
- public @NonNull byte[] getTxtRecord() {
- int txtRecordSize = getTxtRecordSize();
- if (txtRecordSize == 0) {
- return new byte[]{};
- }
-
- byte[] txtRecord = new byte[txtRecordSize];
- int ptr = 0;
- for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
- String key = entry.getKey();
- byte[] value = entry.getValue();
-
- // One byte to record the length of this key/value pair.
- txtRecord[ptr++] = (byte) (key.length() + (value == null ? 0 : value.length) + 1);
-
- // The key, in US-ASCII.
- // Note: use the StandardCharsets const here because it doesn't raise exceptions and we
- // already know the key is ASCII at this point.
- System.arraycopy(key.getBytes(StandardCharsets.US_ASCII), 0, txtRecord, ptr,
- key.length());
- ptr += key.length();
-
- // US-ASCII '=' character.
- txtRecord[ptr++] = (byte)'=';
-
- // The value, as any raw bytes.
- if (value != null) {
- System.arraycopy(value, 0, txtRecord, ptr, value.length);
- ptr += value.length;
- }
- }
- return txtRecord;
- }
-
- /**
- * Get the network where the service can be found.
- *
- * This is never null if this {@link NsdServiceInfo} was obtained from
- * {@link NsdManager#discoverServices} or {@link NsdManager#resolveService}.
- */
- @Nullable
- public Network getNetwork() {
- return mNetwork;
- }
-
- /**
- * Set the network where the service can be found.
- * @param network The network, or null to search for, or to announce, the service on all
- * connected networks.
- */
- public void setNetwork(@Nullable Network network) {
- mNetwork = network;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("name: ").append(mServiceName)
- .append(", type: ").append(mServiceType)
- .append(", host: ").append(mHost)
- .append(", port: ").append(mPort)
- .append(", network: ").append(mNetwork);
-
- byte[] txtRecord = getTxtRecord();
- sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mServiceName);
- dest.writeString(mServiceType);
- if (mHost != null) {
- dest.writeInt(1);
- dest.writeByteArray(mHost.getAddress());
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mPort);
-
- // TXT record key/value pairs.
- dest.writeInt(mTxtRecord.size());
- for (String key : mTxtRecord.keySet()) {
- byte[] value = mTxtRecord.get(key);
- if (value != null) {
- dest.writeInt(1);
- dest.writeInt(value.length);
- dest.writeByteArray(value);
- } else {
- dest.writeInt(0);
- }
- dest.writeString(key);
- }
-
- dest.writeParcelable(mNetwork, 0);
- }
-
- /** Implement the Parcelable interface */
- public static final @android.annotation.NonNull Creator<NsdServiceInfo> CREATOR =
- new Creator<NsdServiceInfo>() {
- public NsdServiceInfo createFromParcel(Parcel in) {
- NsdServiceInfo info = new NsdServiceInfo();
- info.mServiceName = in.readString();
- info.mServiceType = in.readString();
-
- if (in.readInt() == 1) {
- try {
- info.mHost = InetAddress.getByAddress(in.createByteArray());
- } catch (java.net.UnknownHostException e) {}
- }
-
- info.mPort = in.readInt();
-
- // TXT record key/value pairs.
- int recordCount = in.readInt();
- for (int i = 0; i < recordCount; ++i) {
- byte[] valueArray = null;
- if (in.readInt() == 1) {
- int valueLength = in.readInt();
- valueArray = new byte[valueLength];
- in.readByteArray(valueArray);
- }
- info.mTxtRecord.put(in.readString(), valueArray);
- }
- info.mNetwork = in.readParcelable(null, Network.class);
- return info;
- }
-
- public NsdServiceInfo[] newArray(int size) {
- return new NsdServiceInfo[size];
- }
- };
-}
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
deleted file mode 100644
index 4b799c5..0000000
--- a/packages/ConnectivityT/service/Android.bp
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// 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",
- "src/com/android/server/net/BpfInterfaceMapUpdater.java",
- "src/com/android/server/net/InterfaceMapValue.java",
- "src/com/android/server/net/CookieTagMapKey.java",
- "src/com/android/server/net/CookieTagMapValue.java",
- "src/com/android/server/net/StatsMapKey.java",
- "src/com/android/server/net/StatsMapValue.java",
- "src/com/android/server/net/UidStatsMapKey.java",
- ],
- path: "src",
- visibility: [
- "//visibility:private",
- ],
-}
-
-// For test code only.
-filegroup {
- name: "lib_networkStatsFactory_native",
- srcs: [
- "jni/com_android_server_net_NetworkStatsFactory.cpp",
- ],
- path: "jni",
- visibility: [
- "//packages/modules/Connectivity:__subpackages__",
- ],
-}
-
-filegroup {
- name: "services.connectivity-netstats-jni-sources",
- srcs: [
- "jni/com_android_server_net_NetworkStatsFactory.cpp",
- "jni/com_android_server_net_NetworkStatsService.cpp",
- ],
- path: "jni",
- visibility: [
- "//packages/modules/Connectivity:__subpackages__",
- ],
-}
-
-// 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/DelayedDiskWrite.java",
- "src/com/android/server/net/IpConfigStore.java",
- ],
- path: "src",
- visibility: [
- "//frameworks/opt/net/ethernet/tests",
- ],
-}
-
-// Connectivity-T common libraries.
-
-// TODO: remove this empty filegroup.
-filegroup {
- name: "services.connectivity-tiramisu-sources",
- srcs: [],
- path: "src",
- visibility: ["//frameworks/base/services/core"],
-}
-
-filegroup {
- name: "services.connectivity-tiramisu-updatable-sources",
- srcs: [
- ":services.connectivity-ethernet-sources",
- ":services.connectivity-ipsec-sources",
- ":services.connectivity-netstats-sources",
- ":services.connectivity-nsd-sources",
- ],
- path: "src",
- visibility: [
- "//packages/modules/Connectivity:__subpackages__",
- ],
-}
-
-cc_library_shared {
- name: "libcom_android_net_module_util_jni",
- min_sdk_version: "30",
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- "-Wthread-safety",
- ],
- srcs: [
- "jni/onload.cpp",
- ],
- stl: "libc++_static",
- static_libs: [
- "libnet_utils_device_common_bpfjni",
- ],
- shared_libs: [
- "liblog",
- "libnativehelper",
- ],
- apex_available: [
- "//apex_available:platform",
- ],
-}
diff --git a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp
deleted file mode 100644
index 8b6526ff..0000000
--- a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "NetworkStats"
-
-#include <errno.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <vector>
-
-#include <jni.h>
-
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <nativehelper/ScopedLocalRef.h>
-#include <nativehelper/ScopedPrimitiveArray.h>
-
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include "android-base/unique_fd.h"
-#include "bpf/BpfUtils.h"
-#include "netdbpf/BpfNetworkStats.h"
-
-using android::bpf::parseBpfNetworkStatsDetail;
-using android::bpf::stats_line;
-
-namespace android {
-
-static jclass gStringClass;
-
-static struct {
- jfieldID size;
- jfieldID capacity;
- jfieldID iface;
- jfieldID uid;
- jfieldID set;
- jfieldID tag;
- jfieldID metered;
- jfieldID roaming;
- jfieldID defaultNetwork;
- jfieldID rxBytes;
- jfieldID rxPackets;
- jfieldID txBytes;
- jfieldID txPackets;
- jfieldID operations;
-} gNetworkStatsClassInfo;
-
-static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
-{
- if (!grow) {
- jobjectArray array = (jobjectArray)env->GetObjectField(obj, field);
- if (array != NULL) {
- return array;
- }
- }
- return env->NewObjectArray(size, gStringClass, NULL);
-}
-
-static jintArray get_int_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
-{
- if (!grow) {
- jintArray array = (jintArray)env->GetObjectField(obj, field);
- if (array != NULL) {
- return array;
- }
- }
- return env->NewIntArray(size);
-}
-
-static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
-{
- if (!grow) {
- jlongArray array = (jlongArray)env->GetObjectField(obj, field);
- if (array != NULL) {
- return array;
- }
- }
- return env->NewLongArray(size);
-}
-
-static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
- const std::vector<std::string>& limitIfaces,
- int limitTag, int limitUid, const char* path) {
- FILE* fp = fopen(path, "re");
- if (fp == NULL) {
- return -1;
- }
-
- int lastIdx = 1;
- int idx;
- char buffer[384];
- while (fgets(buffer, sizeof(buffer), fp) != NULL) {
- stats_line s;
- int64_t rawTag;
- char* pos = buffer;
- char* endPos;
- // First field is the index.
- idx = (int)strtol(pos, &endPos, 10);
- //ALOGI("Index #%d: %s", idx, buffer);
- if (pos == endPos) {
- // Skip lines that don't start with in index. In particular,
- // this will skip the initial header line.
- continue;
- }
- if (idx != lastIdx + 1) {
- ALOGE("inconsistent idx=%d after lastIdx=%d: %s", idx, lastIdx, buffer);
- fclose(fp);
- return -1;
- }
- lastIdx = idx;
- pos = endPos;
- // Skip whitespace.
- while (*pos == ' ') {
- pos++;
- }
- // Next field is iface.
- int ifaceIdx = 0;
- while (*pos != ' ' && *pos != 0 && ifaceIdx < (int)(sizeof(s.iface)-1)) {
- s.iface[ifaceIdx] = *pos;
- ifaceIdx++;
- pos++;
- }
- if (*pos != ' ') {
- ALOGE("bad iface: %s", buffer);
- fclose(fp);
- return -1;
- }
- s.iface[ifaceIdx] = 0;
- if (limitIfaces.size() > 0) {
- // Is this an iface the caller is interested in?
- int i = 0;
- while (i < (int)limitIfaces.size()) {
- if (limitIfaces[i] == s.iface) {
- break;
- }
- i++;
- }
- if (i >= (int)limitIfaces.size()) {
- // Nothing matched; skip this line.
- //ALOGI("skipping due to iface: %s", buffer);
- continue;
- }
- }
-
- // Ignore whitespace
- while (*pos == ' ') pos++;
-
- // Find end of tag field
- endPos = pos;
- while (*endPos != ' ') endPos++;
-
- // Three digit field is always 0x0, otherwise parse
- if (endPos - pos == 3) {
- rawTag = 0;
- } else {
- if (sscanf(pos, "%" PRIx64, &rawTag) != 1) {
- ALOGE("bad tag: %s", pos);
- fclose(fp);
- return -1;
- }
- }
- s.tag = rawTag >> 32;
- if (limitTag != -1 && s.tag != static_cast<uint32_t>(limitTag)) {
- //ALOGI("skipping due to tag: %s", buffer);
- continue;
- }
- pos = endPos;
-
- // Ignore whitespace
- while (*pos == ' ') pos++;
-
- // Parse remaining fields.
- if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64,
- &s.uid, &s.set, &s.rxBytes, &s.rxPackets,
- &s.txBytes, &s.txPackets) == 6) {
- if (limitUid != -1 && static_cast<uint32_t>(limitUid) != s.uid) {
- //ALOGI("skipping due to uid: %s", buffer);
- continue;
- }
- lines->push_back(s);
- } else {
- //ALOGI("skipping due to bad remaining fields: %s", pos);
- }
- }
-
- if (fclose(fp) != 0) {
- ALOGE("Failed to close netstats file");
- return -1;
- }
- return 0;
-}
-
-static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats,
- std::vector<stats_line>& lines) {
- int size = lines.size();
-
- bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
-
- ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
- gNetworkStatsClassInfo.iface, size, grow));
- if (iface.get() == NULL) return -1;
- ScopedIntArrayRW uid(env, get_int_array(env, stats,
- gNetworkStatsClassInfo.uid, size, grow));
- if (uid.get() == NULL) return -1;
- ScopedIntArrayRW set(env, get_int_array(env, stats,
- gNetworkStatsClassInfo.set, size, grow));
- if (set.get() == NULL) return -1;
- ScopedIntArrayRW tag(env, get_int_array(env, stats,
- gNetworkStatsClassInfo.tag, size, grow));
- if (tag.get() == NULL) return -1;
- ScopedIntArrayRW metered(env, get_int_array(env, stats,
- gNetworkStatsClassInfo.metered, size, grow));
- if (metered.get() == NULL) return -1;
- ScopedIntArrayRW roaming(env, get_int_array(env, stats,
- gNetworkStatsClassInfo.roaming, size, grow));
- if (roaming.get() == NULL) return -1;
- ScopedIntArrayRW defaultNetwork(env, get_int_array(env, stats,
- gNetworkStatsClassInfo.defaultNetwork, size, grow));
- if (defaultNetwork.get() == NULL) return -1;
- ScopedLongArrayRW rxBytes(env, get_long_array(env, stats,
- gNetworkStatsClassInfo.rxBytes, size, grow));
- if (rxBytes.get() == NULL) return -1;
- ScopedLongArrayRW rxPackets(env, get_long_array(env, stats,
- gNetworkStatsClassInfo.rxPackets, size, grow));
- if (rxPackets.get() == NULL) return -1;
- ScopedLongArrayRW txBytes(env, get_long_array(env, stats,
- gNetworkStatsClassInfo.txBytes, size, grow));
- if (txBytes.get() == NULL) return -1;
- ScopedLongArrayRW txPackets(env, get_long_array(env, stats,
- gNetworkStatsClassInfo.txPackets, size, grow));
- if (txPackets.get() == NULL) return -1;
- ScopedLongArrayRW operations(env, get_long_array(env, stats,
- gNetworkStatsClassInfo.operations, size, grow));
- if (operations.get() == NULL) return -1;
-
- for (int i = 0; i < size; i++) {
- ScopedLocalRef<jstring> ifaceString(env, env->NewStringUTF(lines[i].iface));
- env->SetObjectArrayElement(iface.get(), i, ifaceString.get());
-
- uid[i] = lines[i].uid;
- set[i] = lines[i].set;
- tag[i] = lines[i].tag;
- // Metered, roaming and defaultNetwork are populated in Java-land.
- rxBytes[i] = lines[i].rxBytes;
- rxPackets[i] = lines[i].rxPackets;
- txBytes[i] = lines[i].txBytes;
- txPackets[i] = lines[i].txPackets;
- }
-
- env->SetIntField(stats, gNetworkStatsClassInfo.size, size);
- if (grow) {
- env->SetIntField(stats, gNetworkStatsClassInfo.capacity, size);
- env->SetObjectField(stats, gNetworkStatsClassInfo.iface, iface.get());
- env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.defaultNetwork,
- defaultNetwork.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
- env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
- }
- return 0;
-}
-
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
- jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
- jboolean useBpfStats) {
-
- std::vector<std::string> limitIfaces;
- if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
- int num = env->GetArrayLength(limitIfacesObj);
- for (int i = 0; i < num; i++) {
- jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
- ScopedUtfChars string8(env, string);
- if (string8.c_str() != NULL) {
- limitIfaces.push_back(std::string(string8.c_str()));
- }
- }
- }
- std::vector<stats_line> lines;
-
-
- if (useBpfStats) {
- if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
- return -1;
- } else {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str());
- return -1;
- }
- if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
- limitUid, path8.c_str()) < 0)
- return -1;
- }
-
- return statsLinesToNetworkStats(env, clazz, stats, lines);
-}
-
-static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) {
- std::vector<stats_line> lines;
-
- if (parseBpfNetworkStatsDev(&lines) < 0)
- return -1;
-
- return statsLinesToNetworkStats(env, clazz, stats, lines);
-}
-
-static const JNINativeMethod gMethods[] = {
- { "nativeReadNetworkStatsDetail",
- "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
- (void*) readNetworkStatsDetail },
- { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
- (void*) readNetworkStatsDev },
-};
-
-int register_android_server_net_NetworkStatsFactory(JNIEnv* env) {
- int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods,
- NELEM(gMethods));
- gStringClass = env->FindClass("java/lang/String");
- gStringClass = static_cast<jclass>(env->NewGlobalRef(gStringClass));
-
- jclass clazz = env->FindClass("android/net/NetworkStats");
- gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I");
- gNetworkStatsClassInfo.capacity = env->GetFieldID(clazz, "capacity", "I");
- gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;");
- gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I");
- gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I");
- gNetworkStatsClassInfo.tag = env->GetFieldID(clazz, "tag", "[I");
- gNetworkStatsClassInfo.metered = env->GetFieldID(clazz, "metered", "[I");
- gNetworkStatsClassInfo.roaming = env->GetFieldID(clazz, "roaming", "[I");
- gNetworkStatsClassInfo.defaultNetwork = env->GetFieldID(clazz, "defaultNetwork", "[I");
- gNetworkStatsClassInfo.rxBytes = env->GetFieldID(clazz, "rxBytes", "[J");
- gNetworkStatsClassInfo.rxPackets = env->GetFieldID(clazz, "rxPackets", "[J");
- gNetworkStatsClassInfo.txBytes = env->GetFieldID(clazz, "txBytes", "[J");
- gNetworkStatsClassInfo.txPackets = env->GetFieldID(clazz, "txPackets", "[J");
- gNetworkStatsClassInfo.operations = env->GetFieldID(clazz, "operations", "[J");
-
- return err;
-}
-
-}
diff --git a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
deleted file mode 100644
index 39cbaf7..0000000
--- a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#define LOG_TAG "NetworkStatsNative"
-
-#include <cutils/qtaguid.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <jni.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include "bpf/BpfUtils.h"
-#include "netdbpf/BpfNetworkStats.h"
-
-using android::bpf::bpfGetUidStats;
-using android::bpf::bpfGetIfaceStats;
-
-namespace android {
-
-// NOTE: keep these in sync with TrafficStats.java
-static const uint64_t UNKNOWN = -1;
-
-enum StatsType {
- RX_BYTES = 0,
- RX_PACKETS = 1,
- TX_BYTES = 2,
- TX_PACKETS = 3,
- TCP_RX_PACKETS = 4,
- TCP_TX_PACKETS = 5
-};
-
-static uint64_t getStatsType(Stats* stats, StatsType type) {
- switch (type) {
- case RX_BYTES:
- return stats->rxBytes;
- case RX_PACKETS:
- return stats->rxPackets;
- case TX_BYTES:
- return stats->txBytes;
- case TX_PACKETS:
- return stats->txPackets;
- case TCP_RX_PACKETS:
- return stats->tcpRxPackets;
- case TCP_TX_PACKETS:
- return stats->tcpTxPackets;
- default:
- return UNKNOWN;
- }
-}
-
-static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
- Stats stats = {};
-
- if (bpfGetIfaceStats(NULL, &stats) == 0) {
- return getStatsType(&stats, (StatsType) type);
- } else {
- return UNKNOWN;
- }
-}
-
-static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
- ScopedUtfChars iface8(env, iface);
- if (iface8.c_str() == NULL) {
- return UNKNOWN;
- }
-
- Stats stats = {};
-
- 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) {
- Stats stats = {};
-
- if (bpfGetUidStats(uid, &stats) == 0) {
- return getStatsType(&stats, (StatsType) type);
- } else {
- return UNKNOWN;
- }
-}
-
-static const JNINativeMethod gMethods[] = {
- {"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) {
- return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
- NELEM(gMethods));
-}
-
-}
diff --git a/packages/ConnectivityT/service/jni/onload.cpp b/packages/ConnectivityT/service/jni/onload.cpp
deleted file mode 100644
index bca4697..0000000
--- a/packages/ConnectivityT/service/jni/onload.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-#include <nativehelper/JNIHelp.h>
-#include <log/log.h>
-
-namespace android {
-
-int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- ALOGE("GetEnv failed");
- return JNI_ERR;
- }
-
- if (register_com_android_net_module_util_BpfMap(env,
- "com/android/net/module/util/BpfMap") < 0) return JNI_ERR;
-
- return JNI_VERSION_1_6;
-}
-
-};
-
diff --git a/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java b/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
deleted file mode 100644
index 0cf9dcd..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
+++ /dev/null
@@ -1,25 +0,0 @@
-
-/*
- * Copyright (C) 2007 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 com.android.server;
-
-interface INativeDaemonConnectorCallbacks {
-
- void onDaemonConnected();
- boolean onCheckHoldWakeLock(int code);
- boolean onEvent(int code, String raw, String[] cooked);
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
deleted file mode 100644
index 4bc40ea..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
+++ /dev/null
@@ -1,1878 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server;
-
-import static android.Manifest.permission.DUMP;
-import static android.net.IpSecManager.INVALID_RESOURCE_ID;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.AF_UNSPEC;
-import static android.system.OsConstants.EINVAL;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.SOCK_DGRAM;
-
-import android.annotation.NonNull;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.IIpSecService;
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecConfig;
-import android.net.IpSecManager;
-import android.net.IpSecSpiResponse;
-import android.net.IpSecTransform;
-import android.net.IpSecTransformResponse;
-import android.net.IpSecTunnelInterfaceResponse;
-import android.net.IpSecUdpEncapResponse;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.TrafficStats;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Range;
-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;
-
-import libcore.io.IoUtils;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A service to manage multiple clients that want to access the IpSec API. The service is
- * responsible for maintaining a list of clients and managing the resources (and related quotas)
- * that each of them own.
- *
- * <p>Synchronization in IpSecService is done on all entrypoints due to potential race conditions at
- * the kernel/xfrm level. Further, this allows the simplifying assumption to be made that only one
- * thread is ever running at a time.
- *
- * @hide
- */
-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 int[] ADDRESS_FAMILIES =
- new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
-
- private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
- private static final InetAddress INADDR_ANY;
-
- @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});
- } catch (UnknownHostException e) {
- throw new RuntimeException(e);
- }
- }
-
- static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved
- static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer
-
- /* 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
- * kernel data structures. Accessing this variable is not thread safe, so it is only read or
- * modified within blocks synchronized on IpSecService.this. We want to avoid -1
- * (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it).
- */
- @GuardedBy("IpSecService.this")
- private int mNextResourceId = 1;
-
- /**
- * 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;
- }
- }
-
- final UidFdTagger mUidFdTagger;
-
- /**
- * Interface for user-reference and kernel-resource cleanup.
- *
- * <p>This interface must be implemented for a resource to be reference counted.
- */
- @VisibleForTesting
- public interface IResource {
- /**
- * Invalidates a IResource object, ensuring it is invalid for the purposes of allocating new
- * objects dependent on it.
- *
- * <p>Implementations of this method are expected to remove references to the IResource
- * object from the IpSecService's tracking arrays. The removal from the arrays ensures that
- * the resource is considered invalid for user access or allocation or use in other
- * resources.
- *
- * <p>References to the IResource object may be held by other RefcountedResource objects,
- * and as such, the underlying resources and quota may not be cleaned up.
- */
- void invalidate() throws RemoteException;
-
- /**
- * Releases underlying resources and related quotas.
- *
- * <p>Implementations of this method are expected to remove all system resources that are
- * tracked by the IResource object. Due to other RefcountedResource objects potentially
- * having references to the IResource object, freeUnderlyingResources may not always be
- * called from releaseIfUnreferencedRecursively().
- */
- void freeUnderlyingResources() throws RemoteException;
- }
-
- /**
- * RefcountedResource manages references and dependencies in an exclusively acyclic graph.
- *
- * <p>RefcountedResource implements both explicit and implicit resource management. Creating a
- * RefcountedResource object creates an explicit reference that must be freed by calling
- * userRelease(). Additionally, adding this object as a child of another RefcountedResource
- * object will add an implicit reference.
- *
- * <p>Resources are cleaned up when all references, both implicit and explicit, are released
- * (ie, when userRelease() is called and when all parents have called releaseReference() on this
- * object.)
- */
- @VisibleForTesting
- public class RefcountedResource<T extends IResource> implements IBinder.DeathRecipient {
- private final T mResource;
- private final List<RefcountedResource> mChildren;
- int mRefCount = 1; // starts at 1 for user's reference.
- IBinder mBinder;
-
- RefcountedResource(T resource, IBinder binder, RefcountedResource... children) {
- synchronized (IpSecService.this) {
- this.mResource = resource;
- this.mChildren = new ArrayList<>(children.length);
- this.mBinder = binder;
-
- for (RefcountedResource child : children) {
- mChildren.add(child);
- child.mRefCount++;
- }
-
- try {
- mBinder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * If the Binder object dies, this function is called to free the system resources that are
- * being tracked by this record and to subsequently release this record for garbage
- * collection
- */
- @Override
- public void binderDied() {
- synchronized (IpSecService.this) {
- try {
- userRelease();
- } catch (Exception e) {
- Log.e(TAG, "Failed to release resource: " + e);
- }
- }
- }
-
- public T getResource() {
- return mResource;
- }
-
- /**
- * Unlinks from binder and performs IpSecService resource cleanup (removes from resource
- * arrays)
- *
- * <p>If this method has been previously called, the RefcountedResource's binder field will
- * be null, and the method will return without performing the cleanup a second time.
- *
- * <p>Note that calling this function does not imply that kernel resources will be freed at
- * this time, or that the related quota will be returned. Such actions will only be
- * performed upon the reference count reaching zero.
- */
- @GuardedBy("IpSecService.this")
- public void userRelease() throws RemoteException {
- // Prevent users from putting reference counts into a bad state by calling
- // userRelease() multiple times.
- if (mBinder == null) {
- return;
- }
-
- mBinder.unlinkToDeath(this, 0);
- mBinder = null;
-
- mResource.invalidate();
-
- releaseReference();
- }
-
- /**
- * Removes a reference to this resource. If the resultant reference count is zero, the
- * underlying resources are freed, and references to all child resources are also dropped
- * recursively (resulting in them freeing their resources and children, etcetera)
- *
- * <p>This method also sets the reference count to an invalid value (-1) to signify that it
- * has been fully released. Any subsequent calls to this method will result in an
- * IllegalStateException being thrown due to resource already having been previously
- * released
- */
- @VisibleForTesting
- @GuardedBy("IpSecService.this")
- public void releaseReference() throws RemoteException {
- mRefCount--;
-
- if (mRefCount > 0) {
- return;
- } else if (mRefCount < 0) {
- throw new IllegalStateException(
- "Invalid operation - resource has already been released.");
- }
-
- // Cleanup own resources
- mResource.freeUnderlyingResources();
-
- // Cleanup child resources as needed
- for (RefcountedResource<? extends IResource> child : mChildren) {
- child.releaseReference();
- }
-
- // Enforce that resource cleanup can only be called once
- // By decrementing the refcount (from 0 to -1), the next call will throw an
- // IllegalStateException - it has already been released fully.
- mRefCount--;
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{mResource=")
- .append(mResource)
- .append(", mRefCount=")
- .append(mRefCount)
- .append(", mChildren=")
- .append(mChildren)
- .append("}")
- .toString();
- }
- }
-
- /**
- * Very simple counting class that looks much like a counting semaphore
- *
- * <p>This class is not thread-safe, and expects that that users of this class will ensure
- * synchronization and thread safety by holding the IpSecService.this instance lock.
- */
- @VisibleForTesting
- static class ResourceTracker {
- private final int mMax;
- int mCurrent;
-
- ResourceTracker(int max) {
- mMax = max;
- mCurrent = 0;
- }
-
- boolean isAvailable() {
- return (mCurrent < mMax);
- }
-
- void take() {
- if (!isAvailable()) {
- Log.wtf(TAG, "Too many resources allocated!");
- }
- mCurrent++;
- }
-
- void give() {
- if (mCurrent <= 0) {
- Log.wtf(TAG, "We've released this resource too many times");
- }
- mCurrent--;
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{mCurrent=")
- .append(mCurrent)
- .append(", mMax=")
- .append(mMax)
- .append("}")
- .toString();
- }
- }
-
- @VisibleForTesting
- static final class UserRecord {
- /* Maximum number of each type of resource that a single UID may possess */
-
- // Up to 4 active VPNs/IWLAN with potential soft handover.
- public static final int MAX_NUM_TUNNEL_INTERFACES = 8;
- public static final int MAX_NUM_ENCAP_SOCKETS = 16;
-
- // SPIs and Transforms are both cheap, and are 1:1 correlated.
- public static final int MAX_NUM_TRANSFORMS = 64;
- public static final int MAX_NUM_SPIS = 64;
-
- /**
- * Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing
- * and explicit (user) reference management.
- *
- * <p>These are stored in separate arrays to improve debuggability and dump output clarity.
- *
- * <p>Resources are removed from this array when the user releases their explicit reference
- * by calling one of the releaseResource() methods.
- */
- final RefcountedResourceArray<SpiRecord> mSpiRecords =
- new RefcountedResourceArray<>(SpiRecord.class.getSimpleName());
- final RefcountedResourceArray<TransformRecord> mTransformRecords =
- new RefcountedResourceArray<>(TransformRecord.class.getSimpleName());
- final RefcountedResourceArray<EncapSocketRecord> mEncapSocketRecords =
- new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName());
- final RefcountedResourceArray<TunnelInterfaceRecord> mTunnelInterfaceRecords =
- new RefcountedResourceArray<>(TunnelInterfaceRecord.class.getSimpleName());
-
- /**
- * Trackers for quotas for each of the OwnedResource types.
- *
- * <p>These trackers are separate from the resource arrays, since they are incremented and
- * decremented at different points in time. Specifically, quota is only returned upon final
- * resource deallocation (after all explicit and implicit references are released). Note
- * that it is possible that calls to releaseResource() will not return the used quota if
- * there are other resources that depend on (are parents of) the resource being released.
- */
- final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS);
- final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS);
- final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
- final ResourceTracker mTunnelQuotaTracker = new ResourceTracker(MAX_NUM_TUNNEL_INTERFACES);
-
- void removeSpiRecord(int resourceId) {
- mSpiRecords.remove(resourceId);
- }
-
- void removeTransformRecord(int resourceId) {
- mTransformRecords.remove(resourceId);
- }
-
- void removeTunnelInterfaceRecord(int resourceId) {
- mTunnelInterfaceRecords.remove(resourceId);
- }
-
- void removeEncapSocketRecord(int resourceId) {
- mEncapSocketRecords.remove(resourceId);
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{mSpiQuotaTracker=")
- .append(mSpiQuotaTracker)
- .append(", mTransformQuotaTracker=")
- .append(mTransformQuotaTracker)
- .append(", mSocketQuotaTracker=")
- .append(mSocketQuotaTracker)
- .append(", mTunnelQuotaTracker=")
- .append(mTunnelQuotaTracker)
- .append(", mSpiRecords=")
- .append(mSpiRecords)
- .append(", mTransformRecords=")
- .append(mTransformRecords)
- .append(", mEncapSocketRecords=")
- .append(mEncapSocketRecords)
- .append(", mTunnelInterfaceRecords=")
- .append(mTunnelInterfaceRecords)
- .append("}")
- .toString();
- }
- }
-
- /**
- * This class is not thread-safe, and expects that that users of this class will ensure
- * synchronization and thread safety by holding the IpSecService.this instance lock.
- */
- @VisibleForTesting
- static final class UserResourceTracker {
- private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
-
- /** Lazy-initialization/getter that populates or retrieves the UserRecord as needed */
- public UserRecord getUserRecord(int uid) {
- checkCallerUid(uid);
-
- UserRecord r = mUserRecords.get(uid);
- if (r == null) {
- r = new UserRecord();
- mUserRecords.put(uid, r);
- }
- return r;
- }
-
- /** Safety method; guards against access of other user's UserRecords */
- private void checkCallerUid(int uid) {
- if (uid != Binder.getCallingUid() && Process.SYSTEM_UID != Binder.getCallingUid()) {
- throw new SecurityException("Attempted access of unowned resources");
- }
- }
-
- @Override
- public String toString() {
- return mUserRecords.toString();
- }
- }
-
- @VisibleForTesting final UserResourceTracker mUserResourceTracker = new UserResourceTracker();
-
- /**
- * The OwnedResourceRecord class provides a facility to cleanly and reliably track system
- * resources. It relies on a provided resourceId that should uniquely identify the kernel
- * resource. To use this class, the user should implement the invalidate() and
- * freeUnderlyingResources() methods that are responsible for cleaning up IpSecService resource
- * tracking arrays and kernel resources, respectively.
- *
- * <p>This class associates kernel resources with the UID that owns and controls them.
- */
- private abstract class OwnedResourceRecord implements IResource {
- final int mPid;
- final int mUid;
- protected final int mResourceId;
-
- OwnedResourceRecord(int resourceId) {
- super();
- if (resourceId == INVALID_RESOURCE_ID) {
- throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
- }
- mResourceId = resourceId;
- mPid = Binder.getCallingPid();
- mUid = Binder.getCallingUid();
-
- getResourceTracker().take();
- }
-
- @Override
- public abstract void invalidate() throws RemoteException;
-
- /** Convenience method; retrieves the user resource record for the stored UID. */
- protected UserRecord getUserRecord() {
- return mUserResourceTracker.getUserRecord(mUid);
- }
-
- @Override
- public abstract void freeUnderlyingResources() throws RemoteException;
-
- /** Get the resource tracker for this resource */
- protected abstract ResourceTracker getResourceTracker();
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{mResourceId=")
- .append(mResourceId)
- .append(", pid=")
- .append(mPid)
- .append(", uid=")
- .append(mUid)
- .append("}")
- .toString();
- }
- };
-
- /**
- * Thin wrapper over SparseArray to ensure resources exist, and simplify generic typing.
- *
- * <p>RefcountedResourceArray prevents null insertions, and throws an IllegalArgumentException
- * if a key is not found during a retrieval process.
- */
- static class RefcountedResourceArray<T extends IResource> {
- SparseArray<RefcountedResource<T>> mArray = new SparseArray<>();
- private final String mTypeName;
-
- RefcountedResourceArray(String typeName) {
- this.mTypeName = typeName;
- }
-
- /**
- * Accessor method to get inner resource object.
- *
- * @throws IllegalArgumentException if no resource with provided key is found.
- */
- T getResourceOrThrow(int key) {
- return getRefcountedResourceOrThrow(key).getResource();
- }
-
- /**
- * Accessor method to get reference counting wrapper.
- *
- * @throws IllegalArgumentException if no resource with provided key is found.
- */
- RefcountedResource<T> getRefcountedResourceOrThrow(int key) {
- RefcountedResource<T> resource = mArray.get(key);
- if (resource == null) {
- throw new IllegalArgumentException(
- String.format("No such %s found for given id: %d", mTypeName, key));
- }
-
- return resource;
- }
-
- void put(int key, RefcountedResource<T> obj) {
- Objects.requireNonNull(obj, "Null resources cannot be added");
- mArray.put(key, obj);
- }
-
- void remove(int key) {
- mArray.remove(key);
- }
-
- @Override
- public String toString() {
- return mArray.toString();
- }
- }
-
- /**
- * Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is
- * created, the SpiRecord that originally tracked the SAs will reliquish the
- * responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag.
- */
- private final class TransformRecord extends OwnedResourceRecord {
- private final IpSecConfig mConfig;
- private final SpiRecord mSpi;
- private final EncapSocketRecord mSocket;
-
- TransformRecord(
- int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
- super(resourceId);
- mConfig = config;
- mSpi = spi;
- mSocket = socket;
-
- spi.setOwnedByTransform();
- }
-
- public IpSecConfig getConfig() {
- return mConfig;
- }
-
- public SpiRecord getSpiRecord() {
- return mSpi;
- }
-
- public EncapSocketRecord getSocketRecord() {
- return mSocket;
- }
-
- /** always guarded by IpSecService#this */
- @Override
- public void freeUnderlyingResources() {
- int spi = mSpi.getSpi();
- try {
- 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);
- }
-
- getResourceTracker().give();
- }
-
- @Override
- public void invalidate() throws RemoteException {
- getUserRecord().removeTransformRecord(mResourceId);
- }
-
- @Override
- protected ResourceTracker getResourceTracker() {
- return getUserRecord().mTransformQuotaTracker;
- }
-
- @Override
- public String toString() {
- StringBuilder strBuilder = new StringBuilder();
- strBuilder
- .append("{super=")
- .append(super.toString())
- .append(", mSocket=")
- .append(mSocket)
- .append(", mSpi.mResourceId=")
- .append(mSpi.mResourceId)
- .append(", mConfig=")
- .append(mConfig)
- .append("}");
- return strBuilder.toString();
- }
- }
-
- /**
- * Tracks a single SA in the kernel, and manages cleanup paths. Once used in a Transform, the
- * responsibility for cleaning up underlying resources will be passed to the TransformRecord
- * object
- */
- private final class SpiRecord extends OwnedResourceRecord {
- private final String mSourceAddress;
- private final String mDestinationAddress;
- private int mSpi;
-
- private boolean mOwnedByTransform = false;
-
- SpiRecord(int resourceId, String sourceAddress,
- String destinationAddress, int spi) {
- super(resourceId);
- mSourceAddress = sourceAddress;
- mDestinationAddress = destinationAddress;
- mSpi = spi;
- }
-
- /** always guarded by IpSecService#this */
- @Override
- public void freeUnderlyingResources() {
- try {
- if (!mOwnedByTransform) {
- 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);
- }
-
- mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
-
- getResourceTracker().give();
- }
-
- public int getSpi() {
- return mSpi;
- }
-
- public String getDestinationAddress() {
- return mDestinationAddress;
- }
-
- public void setOwnedByTransform() {
- if (mOwnedByTransform) {
- // Programming error
- throw new IllegalStateException("Cannot own an SPI twice!");
- }
-
- mOwnedByTransform = true;
- }
-
- public boolean getOwnedByTransform() {
- return mOwnedByTransform;
- }
-
- @Override
- public void invalidate() throws RemoteException {
- getUserRecord().removeSpiRecord(mResourceId);
- }
-
- @Override
- protected ResourceTracker getResourceTracker() {
- return getUserRecord().mSpiQuotaTracker;
- }
-
- @Override
- public String toString() {
- StringBuilder strBuilder = new StringBuilder();
- strBuilder
- .append("{super=")
- .append(super.toString())
- .append(", mSpi=")
- .append(mSpi)
- .append(", mSourceAddress=")
- .append(mSourceAddress)
- .append(", mDestinationAddress=")
- .append(mDestinationAddress)
- .append(", mOwnedByTransform=")
- .append(mOwnedByTransform)
- .append("}");
- return strBuilder.toString();
- }
- }
-
- private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray();
- final Range<Integer> mNetIdRange = ConnectivityManager.getIpSecNetIdRange();
- private int mNextTunnelNetId = mNetIdRange.getLower();
-
- /**
- * Reserves a netId within the range of netIds allocated for IPsec tunnel interfaces
- *
- * <p>This method should only be called from Binder threads. Do not call this from within the
- * system server as it will crash the system on failure.
- *
- * @return an integer key within the netId range, if successful
- * @throws IllegalStateException if unsuccessful (all netId are currently reserved)
- */
- @VisibleForTesting
- int reserveNetId() {
- final int range = mNetIdRange.getUpper() - mNetIdRange.getLower() + 1;
- synchronized (mTunnelNetIds) {
- for (int i = 0; i < range; i++) {
- final int netId = mNextTunnelNetId;
- if (++mNextTunnelNetId > mNetIdRange.getUpper()) {
- mNextTunnelNetId = mNetIdRange.getLower();
- }
- if (!mTunnelNetIds.get(netId)) {
- mTunnelNetIds.put(netId, true);
- return netId;
- }
- }
- }
- throw new IllegalStateException("No free netIds to allocate");
- }
-
- @VisibleForTesting
- void releaseNetId(int netId) {
- synchronized (mTunnelNetIds) {
- mTunnelNetIds.delete(netId);
- }
- }
-
- /**
- * Tracks an tunnel interface, and manages cleanup paths.
- *
- * <p>This class is not thread-safe, and expects that that users of this class will ensure
- * synchronization and thread safety by holding the IpSecService.this instance lock
- */
- @VisibleForTesting
- final class TunnelInterfaceRecord extends OwnedResourceRecord {
- private final String mInterfaceName;
-
- // outer addresses
- private final String mLocalAddress;
- private final String mRemoteAddress;
-
- private final int mIkey;
- private final int mOkey;
-
- private final int mIfId;
-
- private Network mUnderlyingNetwork;
-
- TunnelInterfaceRecord(
- int resourceId,
- String interfaceName,
- Network underlyingNetwork,
- String localAddr,
- String remoteAddr,
- int ikey,
- int okey,
- int intfId) {
- super(resourceId);
-
- mInterfaceName = interfaceName;
- mUnderlyingNetwork = underlyingNetwork;
- mLocalAddress = localAddr;
- mRemoteAddress = remoteAddr;
- mIkey = ikey;
- mOkey = okey;
- mIfId = intfId;
- }
-
- /** always guarded by IpSecService#this */
- @Override
- public void freeUnderlyingResources() {
- // Calls to netd
- // Teardown VTI
- // Delete global policies
- try {
- mNetd.ipSecRemoveTunnelInterface(mInterfaceName);
-
- for (int selAddrFamily : ADDRESS_FAMILIES) {
- mNetd.ipSecDeleteSecurityPolicy(
- mUid,
- selAddrFamily,
- IpSecManager.DIRECTION_OUT,
- mOkey,
- 0xffffffff,
- mIfId);
- mNetd.ipSecDeleteSecurityPolicy(
- mUid,
- selAddrFamily,
- IpSecManager.DIRECTION_IN,
- mIkey,
- 0xffffffff,
- mIfId);
- }
- } catch (ServiceSpecificException | RemoteException e) {
- Log.e(
- TAG,
- "Failed to delete VTI with interface name: "
- + mInterfaceName
- + " and id: "
- + mResourceId, e);
- }
-
- getResourceTracker().give();
- releaseNetId(mIkey);
- releaseNetId(mOkey);
- }
-
- @GuardedBy("IpSecService.this")
- public void setUnderlyingNetwork(Network underlyingNetwork) {
- // When #applyTunnelModeTransform is called, this new underlying network will be used to
- // update the output mark of the input transform.
- mUnderlyingNetwork = underlyingNetwork;
- }
-
- @GuardedBy("IpSecService.this")
- public Network getUnderlyingNetwork() {
- return mUnderlyingNetwork;
- }
-
- public String getInterfaceName() {
- return mInterfaceName;
- }
-
- /** Returns the local, outer address for the tunnelInterface */
- public String getLocalAddress() {
- return mLocalAddress;
- }
-
- /** Returns the remote, outer address for the tunnelInterface */
- public String getRemoteAddress() {
- return mRemoteAddress;
- }
-
- public int getIkey() {
- return mIkey;
- }
-
- public int getOkey() {
- return mOkey;
- }
-
- public int getIfId() {
- return mIfId;
- }
-
- @Override
- protected ResourceTracker getResourceTracker() {
- return getUserRecord().mTunnelQuotaTracker;
- }
-
- @Override
- public void invalidate() {
- getUserRecord().removeTunnelInterfaceRecord(mResourceId);
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{super=")
- .append(super.toString())
- .append(", mInterfaceName=")
- .append(mInterfaceName)
- .append(", mUnderlyingNetwork=")
- .append(mUnderlyingNetwork)
- .append(", mLocalAddress=")
- .append(mLocalAddress)
- .append(", mRemoteAddress=")
- .append(mRemoteAddress)
- .append(", mIkey=")
- .append(mIkey)
- .append(", mOkey=")
- .append(mOkey)
- .append("}")
- .toString();
- }
- }
-
- /**
- * Tracks a UDP encap socket, and manages cleanup paths
- *
- * <p>While this class does not manage non-kernel resources, race conditions around socket
- * binding require that the service creates the encap socket, binds it and applies the socket
- * policy before handing it to a user.
- */
- private final class EncapSocketRecord extends OwnedResourceRecord {
- private FileDescriptor mSocket;
- private final int mPort;
-
- EncapSocketRecord(int resourceId, FileDescriptor socket, int port) {
- super(resourceId);
- mSocket = socket;
- mPort = port;
- }
-
- /** always guarded by IpSecService#this */
- @Override
- public void freeUnderlyingResources() {
- Log.d(TAG, "Closing port " + mPort);
- IoUtils.closeQuietly(mSocket);
- mSocket = null;
-
- getResourceTracker().give();
- }
-
- public int getPort() {
- return mPort;
- }
-
- public FileDescriptor getFileDescriptor() {
- return mSocket;
- }
-
- @Override
- protected ResourceTracker getResourceTracker() {
- return getUserRecord().mSocketQuotaTracker;
- }
-
- @Override
- public void invalidate() {
- getUserRecord().removeEncapSocketRecord(mResourceId);
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{super=")
- .append(super.toString())
- .append(", mSocket=")
- .append(mSocket)
- .append(", mPort=")
- .append(mPort)
- .append("}")
- .toString();
- }
- }
-
- /**
- * Constructs a new IpSecService instance
- *
- * @param context Binder context for this service
- */
- public IpSecService(Context context) {
- this(context, new Dependencies());
- }
-
- @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");
- return appOps;
- }
-
- /** @hide */
- @VisibleForTesting
- public IpSecService(Context context, Dependencies deps) {
- this(
- context,
- deps,
- (fd, uid) -> {
- try {
- TrafficStats.setThreadStatsUid(uid);
- TrafficStats.tagFileDescriptor(fd);
- } finally {
- TrafficStats.clearThreadStatsUid();
- }
- });
- }
-
- /** @hide */
- @VisibleForTesting
- public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) {
- mContext = context;
- mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
- mUidFdTagger = uidFdTagger;
- try {
- mNetd = mDeps.getNetdInstance(mContext);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
- * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
- */
- private static void checkInetAddress(String inetAddress) {
- if (TextUtils.isEmpty(inetAddress)) {
- throw new IllegalArgumentException("Unspecified address");
- }
-
- InetAddress checkAddr = InetAddresses.parseNumericAddress(inetAddress);
-
- if (checkAddr.isAnyLocalAddress()) {
- throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
- }
- }
-
- /**
- * Checks the user-provided direction field and throws an IllegalArgumentException if it is not
- * DIRECTION_IN or DIRECTION_OUT
- */
- private void checkDirection(int direction) {
- switch (direction) {
- case IpSecManager.DIRECTION_OUT:
- case IpSecManager.DIRECTION_IN:
- return;
- case IpSecManager.DIRECTION_FWD:
- // Only NETWORK_STACK or MAINLINE_NETWORK_STACK allowed to use forward policies
- PermissionUtils.enforceNetworkStackPermission(mContext);
- return;
- }
- throw new IllegalArgumentException("Invalid Direction: " + direction);
- }
-
- /** Get a new SPI and maintain the reservation in the system server */
- @Override
- public synchronized IpSecSpiResponse allocateSecurityParameterIndex(
- String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException {
- checkInetAddress(destinationAddress);
- // RFC 4303 Section 2.1 - 0=local, 1-255=reserved.
- if (requestedSpi > 0 && requestedSpi < 256) {
- throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255.");
- }
- Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
-
- int callingUid = Binder.getCallingUid();
- UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
- final int resourceId = mNextResourceId++;
-
- int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
- try {
- if (!userRecord.mSpiQuotaTracker.isAvailable()) {
- return new IpSecSpiResponse(
- IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
- }
-
- 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));
- } catch (ServiceSpecificException e) {
- if (e.errorCode == OsConstants.ENOENT) {
- return new IpSecSpiResponse(
- IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
- }
- throw e;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- return new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, spi);
- }
-
- /* This method should only be called from Binder threads. Do not call this from
- * within the system server as it will crash the system on failure.
- */
- private void releaseResource(RefcountedResourceArray resArray, int resourceId)
- throws RemoteException {
- resArray.getRefcountedResourceOrThrow(resourceId).userRelease();
- }
-
- /** Release a previously allocated SPI that has been registered with the system server */
- @Override
- public synchronized void releaseSecurityParameterIndex(int resourceId) throws RemoteException {
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- releaseResource(userRecord.mSpiRecords, resourceId);
- }
-
- /**
- * This function finds and forcibly binds to a random system port, ensuring that the port cannot
- * be unbound.
- *
- * <p>A socket cannot be un-bound from a port if it was bound to that port by number. To select
- * a random open port and then bind by number, this function creates a temp socket, binds to a
- * random port (specifying 0), gets that port number, and then uses is to bind the user's UDP
- * Encapsulation Socket forcibly, so that it cannot be un-bound by the user with the returned
- * FileHandle.
- *
- * <p>The loop in this function handles the inherent race window between un-binding to a port
- * and re-binding, during which the system could *technically* hand that port out to someone
- * else.
- */
- private int bindToRandomPort(FileDescriptor sockFd) throws IOException {
- for (int i = MAX_PORT_BIND_ATTEMPTS; i > 0; i--) {
- try {
- FileDescriptor probeSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- Os.bind(probeSocket, INADDR_ANY, 0);
- int port = ((InetSocketAddress) Os.getsockname(probeSocket)).getPort();
- Os.close(probeSocket);
- Log.v(TAG, "Binding to port " + port);
- Os.bind(sockFd, INADDR_ANY, port);
- return port;
- } catch (ErrnoException e) {
- // Someone miraculously claimed the port just after we closed probeSocket.
- if (e.errno == OsConstants.EADDRINUSE) {
- continue;
- }
- throw e.rethrowAsIOException();
- }
- }
- throw new IOException("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
- }
-
- /**
- * Functional interface to do traffic tagging of given sockets to UIDs.
- *
- * <p>Specifically used by openUdpEncapsulationSocket to ensure data usage on the UDP encap
- * sockets are billed to the UID that the UDP encap socket was created on behalf of.
- *
- * <p>Separate class so that the socket tagging logic can be mocked; TrafficStats uses static
- * methods that cannot be easily mocked/tested.
- */
- @VisibleForTesting
- public interface UidFdTagger {
- /**
- * Sets socket tag to assign all traffic to the provided UID.
- *
- * <p>Since the socket is created on behalf of an unprivileged application, all traffic
- * should be accounted to the UID of the unprivileged application.
- */
- void tag(FileDescriptor fd, int uid) throws IOException;
- }
-
- /**
- * Open a socket via the system server and bind it to the specified port (random if port=0).
- * This will return a PFD to the user that represent a bound UDP socket. The system server will
- * cache the socket and a record of its owner so that it can and must be freed when no longer
- * needed.
- */
- @Override
- public synchronized IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, IBinder binder)
- throws RemoteException {
- if (port != 0 && (port < FREE_PORT_MIN || port > PORT_MAX)) {
- throw new IllegalArgumentException(
- "Specified port number must be a valid non-reserved UDP port");
- }
- Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
-
- int callingUid = Binder.getCallingUid();
- UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
- final int resourceId = mNextResourceId++;
-
- ParcelFileDescriptor pFd = null;
- try {
- if (!userRecord.mSocketQuotaTracker.isAvailable()) {
- return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
- }
-
- 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(
- pFd.getFileDescriptor(),
- OsConstants.IPPROTO_UDP,
- OsConstants.UDP_ENCAP,
- OsConstants.UDP_ENCAP_ESPINUDP);
-
- mNetd.ipSecSetEncapSocketOwner(pFd, callingUid);
- if (port != 0) {
- Log.v(TAG, "Binding to port " + port);
- Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port);
- } else {
- port = bindToRandomPort(pFd.getFileDescriptor());
- }
-
- userRecord.mEncapSocketRecords.put(
- resourceId,
- new RefcountedResource<EncapSocketRecord>(
- new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port),
- binder));
- return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port,
- pFd.getFileDescriptor());
- } catch (IOException | ErrnoException e) {
- 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.
- return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
- }
-
- /** close a socket that has been been allocated by and registered with the system server */
- @Override
- public synchronized void closeUdpEncapsulationSocket(int resourceId) throws RemoteException {
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- releaseResource(userRecord.mEncapSocketRecords, resourceId);
- }
-
- /**
- * Create a tunnel interface for use in IPSec tunnel mode. The system server will cache the
- * tunnel interface and a record of its owner so that it can and must be freed when no longer
- * needed.
- */
- @Override
- public synchronized IpSecTunnelInterfaceResponse createTunnelInterface(
- String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
- String callingPackage) {
- enforceTunnelFeatureAndPermissions(callingPackage);
- Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface");
- Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
- checkInetAddress(localAddr);
- checkInetAddress(remoteAddr);
-
- // TODO: Check that underlying network exists, and IP addresses not assigned to a different
- // network (b/72316676).
-
- int callerUid = Binder.getCallingUid();
- UserRecord userRecord = mUserResourceTracker.getUserRecord(callerUid);
- if (!userRecord.mTunnelQuotaTracker.isAvailable()) {
- return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
- }
-
- final int resourceId = mNextResourceId++;
- final int ikey = reserveNetId();
- final int okey = reserveNetId();
- String intfName = String.format("%s%d", INetd.IPSEC_INTERFACE_PREFIX, resourceId);
-
- try {
- // Calls to netd:
- // Create VTI
- // Add inbound/outbound global policies
- // (use reqid = 0)
- mNetd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
-
- BinderUtils.withCleanCallingIdentity(() -> {
- NetdUtils.setInterfaceUp(mNetd, intfName);
- });
-
- for (int selAddrFamily : ADDRESS_FAMILIES) {
- // Always send down correct local/remote addresses for template.
- mNetd.ipSecAddSecurityPolicy(
- callerUid,
- selAddrFamily,
- IpSecManager.DIRECTION_OUT,
- localAddr,
- remoteAddr,
- 0,
- okey,
- 0xffffffff,
- resourceId);
- mNetd.ipSecAddSecurityPolicy(
- callerUid,
- selAddrFamily,
- IpSecManager.DIRECTION_IN,
- remoteAddr,
- localAddr,
- 0,
- ikey,
- 0xffffffff,
- resourceId);
-
- // Add a forwarding policy on the tunnel interface. In order to support forwarding
- // the IpSecTunnelInterface must have a forwarding policy matching the incoming SA.
- //
- // Unless a IpSecTransform is also applied against this interface in DIRECTION_FWD,
- // forwarding will be blocked by default (as would be the case if this policy was
- // absent).
- //
- // This is necessary only on the tunnel interface, and not any the interface to
- // which traffic will be forwarded to.
- mNetd.ipSecAddSecurityPolicy(
- callerUid,
- selAddrFamily,
- IpSecManager.DIRECTION_FWD,
- remoteAddr,
- localAddr,
- 0,
- ikey,
- 0xffffffff,
- resourceId);
- }
-
- userRecord.mTunnelInterfaceRecords.put(
- resourceId,
- new RefcountedResource<TunnelInterfaceRecord>(
- new TunnelInterfaceRecord(
- resourceId,
- intfName,
- underlyingNetwork,
- localAddr,
- remoteAddr,
- ikey,
- okey,
- resourceId),
- binder));
- return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
- } catch (RemoteException e) {
- // Release keys if we got an error.
- releaseNetId(ikey);
- releaseNetId(okey);
- throw e.rethrowFromSystemServer();
- } catch (Throwable t) {
- // Release keys if we got an error.
- releaseNetId(ikey);
- releaseNetId(okey);
- throw t;
- }
- }
-
- /**
- * Adds a new local address to the tunnel interface. This allows packets to be sent and received
- * from multiple local IP addresses over the same tunnel.
- */
- @Override
- public synchronized void addAddressToTunnelInterface(
- int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
- enforceTunnelFeatureAndPermissions(callingPackage);
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
- // Get tunnelInterface record; if no such interface is found, will throw
- // IllegalArgumentException
- TunnelInterfaceRecord tunnelInterfaceInfo =
- userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
- try {
- // We can assume general validity of the IP address, since we get them as a
- // LinkAddress, which does some validation.
- mNetd.interfaceAddAddress(
- tunnelInterfaceInfo.mInterfaceName,
- localAddr.getAddress().getHostAddress(),
- localAddr.getPrefixLength());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Remove a new local address from the tunnel interface. After removal, the address will no
- * longer be available to send from, or receive on.
- */
- @Override
- public synchronized void removeAddressFromTunnelInterface(
- int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
- enforceTunnelFeatureAndPermissions(callingPackage);
-
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- // Get tunnelInterface record; if no such interface is found, will throw
- // IllegalArgumentException
- TunnelInterfaceRecord tunnelInterfaceInfo =
- userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
- try {
- // We can assume general validity of the IP address, since we get them as a
- // LinkAddress, which does some validation.
- mNetd.interfaceDelAddress(
- tunnelInterfaceInfo.mInterfaceName,
- localAddr.getAddress().getHostAddress(),
- localAddr.getPrefixLength());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** Set TunnelInterface to use a specific underlying network. */
- @Override
- public synchronized void setNetworkForTunnelInterface(
- int tunnelResourceId, Network underlyingNetwork, String callingPackage) {
- enforceTunnelFeatureAndPermissions(callingPackage);
- Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
-
- final UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
- // Get tunnelInterface record; if no such interface is found, will throw
- // IllegalArgumentException. userRecord.mTunnelInterfaceRecords is never null
- final TunnelInterfaceRecord tunnelInterfaceInfo =
- userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
- final ConnectivityManager connectivityManager =
- mContext.getSystemService(ConnectivityManager.class);
- final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork);
- if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) {
- throw new IllegalArgumentException(
- "Underlying network cannot be the network being exposed by this tunnel");
- }
-
- // It is meaningless to check if the network exists or is valid because the network might
- // disconnect at any time after it passes the check.
-
- tunnelInterfaceInfo.setUnderlyingNetwork(underlyingNetwork);
- }
-
- /**
- * Delete a TunnelInterface that has been been allocated by and registered with the system
- * server
- */
- @Override
- public synchronized void deleteTunnelInterface(
- int resourceId, String callingPackage) throws RemoteException {
- enforceTunnelFeatureAndPermissions(callingPackage);
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- releaseResource(userRecord.mTunnelInterfaceRecords, resourceId);
- }
-
- @VisibleForTesting
- void validateAlgorithms(IpSecConfig config) throws IllegalArgumentException {
- IpSecAlgorithm auth = config.getAuthentication();
- IpSecAlgorithm crypt = config.getEncryption();
- IpSecAlgorithm aead = config.getAuthenticatedEncryption();
-
- // Validate the algorithm set
- Preconditions.checkArgument(
- aead != null || crypt != null || auth != null,
- "No Encryption or Authentication algorithms specified");
- Preconditions.checkArgument(
- auth == null || auth.isAuthentication(),
- "Unsupported algorithm for Authentication");
- Preconditions.checkArgument(
- crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption");
- Preconditions.checkArgument(
- aead == null || aead.isAead(),
- "Unsupported algorithm for Authenticated Encryption");
- Preconditions.checkArgument(
- aead == null || (auth == null && crypt == null),
- "Authenticated Encryption is mutually exclusive with other Authentication "
- + "or Encryption algorithms");
- }
-
- private int getFamily(String inetAddress) {
- int family = AF_UNSPEC;
- InetAddress checkAddress = InetAddresses.parseNumericAddress(inetAddress);
- if (checkAddress instanceof Inet4Address) {
- family = AF_INET;
- } else if (checkAddress instanceof Inet6Address) {
- family = AF_INET6;
- }
- return family;
- }
-
- /**
- * Checks an IpSecConfig parcel to ensure that the contents are valid and throws an
- * IllegalArgumentException if they are not.
- */
- private void checkIpSecConfig(IpSecConfig config) {
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
- switch (config.getEncapType()) {
- case IpSecTransform.ENCAP_NONE:
- break;
- case IpSecTransform.ENCAP_ESPINUDP:
- case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
- // Retrieve encap socket record; will throw IllegalArgumentException if not found
- userRecord.mEncapSocketRecords.getResourceOrThrow(
- config.getEncapSocketResourceId());
-
- int port = config.getEncapRemotePort();
- if (port <= 0 || port > 0xFFFF) {
- throw new IllegalArgumentException("Invalid remote UDP port: " + port);
- }
- break;
- default:
- throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType());
- }
-
- validateAlgorithms(config);
-
- // Retrieve SPI record; will throw IllegalArgumentException if not found
- SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId());
-
- // Check to ensure that SPI has not already been used.
- if (s.getOwnedByTransform()) {
- throw new IllegalStateException("SPI already in use; cannot be used in new Transforms");
- }
-
- // If no remote address is supplied, then use one from the SPI.
- if (TextUtils.isEmpty(config.getDestinationAddress())) {
- config.setDestinationAddress(s.getDestinationAddress());
- }
-
- // All remote addresses must match
- if (!config.getDestinationAddress().equals(s.getDestinationAddress())) {
- throw new IllegalArgumentException("Mismatched remote addresseses.");
- }
-
- // This check is technically redundant due to the chain of custody between the SPI and
- // the IpSecConfig, but in the future if the dest is allowed to be set explicitly in
- // the transform, this will prevent us from messing up.
- checkInetAddress(config.getDestinationAddress());
-
- // Require a valid source address for all transforms.
- checkInetAddress(config.getSourceAddress());
-
- // Check to ensure source and destination have the same address family.
- String sourceAddress = config.getSourceAddress();
- String destinationAddress = config.getDestinationAddress();
- int sourceFamily = getFamily(sourceAddress);
- int destinationFamily = getFamily(destinationAddress);
- if (sourceFamily != destinationFamily) {
- throw new IllegalArgumentException(
- "Source address ("
- + sourceAddress
- + ") and destination address ("
- + destinationAddress
- + ") have different address families.");
- }
-
- // Throw an error if UDP Encapsulation is not used in IPv4.
- if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) {
- throw new IllegalArgumentException(
- "UDP Encapsulation is not supported for this address family");
- }
-
- switch (config.getMode()) {
- case IpSecTransform.MODE_TRANSPORT:
- break;
- case IpSecTransform.MODE_TUNNEL:
- break;
- default:
- throw new IllegalArgumentException(
- "Invalid IpSecTransform.mode: " + config.getMode());
- }
-
- config.setMarkValue(0);
- config.setMarkMask(0);
- }
-
- private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
-
- private void enforceTunnelFeatureAndPermissions(String callingPackage) {
- if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) {
- throw new UnsupportedOperationException(
- "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
- }
-
- Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels");
-
- // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system
- // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS
- // permission or is the System Server.
- if (AppOpsManager.MODE_ALLOWED == getAppOpsManager().noteOpNoThrow(
- TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
- return;
- }
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
- }
-
- private void createOrUpdateTransform(
- IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
- throws RemoteException {
-
- int encapType = c.getEncapType(), encapLocalPort = 0, encapRemotePort = 0;
- if (encapType != IpSecTransform.ENCAP_NONE) {
- encapLocalPort = socketRecord.getPort();
- encapRemotePort = c.getEncapRemotePort();
- }
-
- IpSecAlgorithm auth = c.getAuthentication();
- IpSecAlgorithm crypt = c.getEncryption();
- IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
-
- String cryptName;
- if (crypt == null) {
- cryptName = (authCrypt == null) ? IpSecAlgorithm.CRYPT_NULL : "";
- } else {
- cryptName = crypt.getName();
- }
-
- 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());
- }
-
- /**
- * Create a IPsec transform, which represents a single security association in the kernel. The
- * transform will be cached by the system server and must be freed when no longer needed. It is
- * possible to free one, deleting the SA from underneath sockets that are using it, which will
- * result in all of those sockets becoming unable to send or receive data.
- */
- @Override
- public synchronized IpSecTransformResponse createTransform(
- IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
- Objects.requireNonNull(c);
- if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
- enforceTunnelFeatureAndPermissions(callingPackage);
- }
- checkIpSecConfig(c);
- Objects.requireNonNull(binder, "Null Binder passed to createTransform");
- final int resourceId = mNextResourceId++;
-
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- List<RefcountedResource> dependencies = new ArrayList<>();
-
- if (!userRecord.mTransformQuotaTracker.isAvailable()) {
- return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
- }
-
- EncapSocketRecord socketRecord = null;
- if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
- RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
- userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
- c.getEncapSocketResourceId());
- dependencies.add(refcountedSocketRecord);
- socketRecord = refcountedSocketRecord.getResource();
- }
-
- RefcountedResource<SpiRecord> refcountedSpiRecord =
- userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
- dependencies.add(refcountedSpiRecord);
- SpiRecord spiRecord = refcountedSpiRecord.getResource();
-
- createOrUpdateTransform(c, resourceId, spiRecord, socketRecord);
-
- // SA was created successfully, time to construct a record and lock it away
- userRecord.mTransformRecords.put(
- resourceId,
- new RefcountedResource<TransformRecord>(
- new TransformRecord(resourceId, c, spiRecord, socketRecord),
- binder,
- dependencies.toArray(new RefcountedResource[dependencies.size()])));
- return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId);
- }
-
- /**
- * Delete a transport mode transform that was previously allocated by + registered with the
- * system server. If this is called on an inactive (or non-existent) transform, it will not
- * return an error. It's safe to de-allocate transforms that may have already been deleted for
- * other reasons.
- */
- @Override
- public synchronized void deleteTransform(int resourceId) throws RemoteException {
- UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- releaseResource(userRecord.mTransformRecords, resourceId);
- }
-
- /**
- * Apply an active transport mode transform to a socket, which will apply the IPsec security
- * association as a correspondent policy to the provided socket
- */
- @Override
- public synchronized void applyTransportModeTransform(
- ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException {
- int callingUid = Binder.getCallingUid();
- UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
- checkDirection(direction);
- // Get transform record; if no transform is found, will throw IllegalArgumentException
- TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
-
- // TODO: make this a function.
- if (info.mPid != getCallingPid() || info.mUid != callingUid) {
- throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
- }
-
- // Get config and check that to-be-applied transform has the correct mode
- IpSecConfig c = info.getConfig();
- Preconditions.checkArgument(
- c.getMode() == IpSecTransform.MODE_TRANSPORT,
- "Transform mode was not Transport mode; cannot be applied to a socket");
-
- mNetd.ipSecApplyTransportModeTransform(
- socket,
- callingUid,
- direction,
- c.getSourceAddress(),
- c.getDestinationAddress(),
- info.getSpiRecord().getSpi());
- }
-
- /**
- * Remove transport mode transforms from a socket, applying the default (empty) policy. This
- * ensures that NO IPsec policy is applied to the socket (would be the equivalent of applying a
- * policy that performs no IPsec). Today the resourceId parameter is passed but not used:
- * reserved for future improved input validation.
- */
- @Override
- public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
- throws RemoteException {
- mNetd.ipSecRemoveTransportModeTransform(socket);
- }
-
- /**
- * Apply an active tunnel mode transform to a TunnelInterface, which will apply the IPsec
- * security association as a correspondent policy to the provided interface
- */
- @Override
- public synchronized void applyTunnelModeTransform(
- int tunnelResourceId, int direction,
- int transformResourceId, String callingPackage) throws RemoteException {
- enforceTunnelFeatureAndPermissions(callingPackage);
- checkDirection(direction);
-
- int callingUid = Binder.getCallingUid();
- UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
-
- // Get transform record; if no transform is found, will throw IllegalArgumentException
- TransformRecord transformInfo =
- userRecord.mTransformRecords.getResourceOrThrow(transformResourceId);
-
- // Get tunnelInterface record; if no such interface is found, will throw
- // IllegalArgumentException
- TunnelInterfaceRecord tunnelInterfaceInfo =
- userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
- // Get config and check that to-be-applied transform has the correct mode
- IpSecConfig c = transformInfo.getConfig();
- Preconditions.checkArgument(
- c.getMode() == IpSecTransform.MODE_TUNNEL,
- "Transform mode was not Tunnel mode; cannot be applied to a tunnel interface");
-
- EncapSocketRecord socketRecord = null;
- if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
- socketRecord =
- userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId());
- }
- SpiRecord spiRecord = transformInfo.getSpiRecord();
-
- int mark =
- (direction == IpSecManager.DIRECTION_OUT)
- ? tunnelInterfaceInfo.getOkey()
- : tunnelInterfaceInfo.getIkey(); // Ikey also used for FWD policies
-
- try {
- // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip
- // SPI matching as part of the template resolution.
- int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
- c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId());
-
- // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream
- // (and backporting) would allow us to narrow the mark space, and ensure that the SA
- // and SPs have matching marks (as VTI are meant to be built).
- // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the
- // config matches the actual allocated resources in the kernel.
- // All SAs will have zero marks (from creation time), and any policy that matches the
- // same src/dst could match these SAs. Non-IpSecService governed processes that
- // establish floating policies with the same src/dst may result in undefined
- // behavior. This is generally limited to vendor code due to the permissions
- // (CAP_NET_ADMIN) required.
- //
- // c.setMarkValue(mark);
- // c.setMarkMask(0xffffffff);
-
- if (direction == IpSecManager.DIRECTION_OUT) {
- // Set output mark via underlying network (output only)
- c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
-
- // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys,
- // but want to guarantee outbound packets are sent over the new SA.
- spi = spiRecord.getSpi();
- }
-
- // Always update the policy with the relevant XFRM_IF_ID
- for (int selAddrFamily : ADDRESS_FAMILIES) {
- 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)
- createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
- } catch (ServiceSpecificException e) {
- if (e.errorCode == EINVAL) {
- throw new IllegalArgumentException(e.toString());
- } else {
- throw e;
- }
- }
- }
-
- @Override
- protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(DUMP, TAG);
-
- pw.println("IpSecService dump:");
- pw.println();
-
- pw.println("mUserResourceTracker:");
- pw.println(mUserResourceTracker);
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
deleted file mode 100644
index ec8d779..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * Copyright (C) 2007 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 com.android.server;
-
-import android.net.LocalSocket;
-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.util.LocalLog;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-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.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 {
- private final static boolean VDBG = false;
-
- private final String TAG;
-
- private String mSocket;
- private OutputStream mOutputStream;
- private LocalLog mLocalLog;
-
- private volatile boolean mDebug = false;
- private volatile Object mWarnIfHeld;
-
- private final ResponseQueue mResponseQueue;
-
- private final PowerManager.WakeLock mWakeLock;
-
- private final Looper mLooper;
-
- private INativeDaemonConnectorCallbacks mCallbacks;
- private Handler mCallbackHandler;
-
- private AtomicInteger mSequenceNumber;
-
- private static final long DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */
- private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */
-
- /** Lock held whenever communicating with native daemon. */
- private final Object mDaemonLock = new Object();
-
- private final int BUFFER_SIZE = 4096;
-
- NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
- int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
- mCallbacks = callbacks;
- mSocket = socket;
- mResponseQueue = new ResponseQueue(responseQueueSize);
- mWakeLock = wl;
- if (mWakeLock != null) {
- mWakeLock.setReferenceCounted(true);
- }
- 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 Log} in addition to internal log.
- */
- public void setDebug(boolean debug) {
- mDebug = debug;
- }
-
- /**
- * Like SystemClock.uptimeMillis, except truncated to an int so it will fit in a message arg.
- * Inaccurate across 49.7 days of uptime, but only used for debugging.
- */
- private int uptimeMillisInt() {
- return (int) SystemClock.uptimeMillis() & Integer.MAX_VALUE;
- }
-
- /**
- * Yell loudly if someone tries making future {@link #execute(Command)}
- * calls while holding a lock on the given object.
- */
- public void setWarnIfHeld(Object warnIfHeld) {
- if (mWarnIfHeld != null) {
- throw new IllegalStateException("warnIfHeld is already set.");
- }
- mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
- }
-
- @Override
- public void run() {
- mCallbackHandler = new Handler(mLooper, this);
-
- while (true) {
- try {
- listenToSocket();
- } catch (Exception e) {
- loge("Error in NativeDaemonConnector: " + e);
- SystemClock.sleep(5000);
- }
- }
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- final String event = (String) msg.obj;
- final int start = uptimeMillisInt();
- final int sent = msg.arg1;
- try {
- if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) {
- log(String.format("Unhandled event '%s'", event));
- }
- } catch (Exception e) {
- loge("Error handling '" + event + "': " + e);
- } finally {
- if (mCallbacks.onCheckHoldWakeLock(msg.what) && mWakeLock != null) {
- mWakeLock.release();
- }
- final int end = uptimeMillisInt();
- if (start > sent && start - sent > WARN_EXECUTE_DELAY_MS) {
- loge(String.format("NDC event {%s} processed too late: %dms", event, start - sent));
- }
- if (end > start && end - start > WARN_EXECUTE_DELAY_MS) {
- loge(String.format("NDC event {%s} took too long: %dms", event, end - start));
- }
- }
- return true;
- }
-
- private LocalSocketAddress determineSocketAddress() {
- // If we're testing, set up a socket in a namespace that's accessible to test code.
- // 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.isDebuggable()) {
- return new LocalSocketAddress(mSocket);
- } else {
- return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED);
- }
- }
-
- private void listenToSocket() throws IOException {
- LocalSocket socket = null;
-
- try {
- socket = new LocalSocket();
- LocalSocketAddress address = determineSocketAddress();
-
- socket.connect(address);
-
- InputStream inputStream = socket.getInputStream();
- synchronized (mDaemonLock) {
- mOutputStream = socket.getOutputStream();
- }
-
- mCallbacks.onDaemonConnected();
-
- FileDescriptor[] fdList = null;
- byte[] buffer = new byte[BUFFER_SIZE];
- int start = 0;
-
- while (true) {
- int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
- if (count < 0) {
- loge("got " + count + " reading with start = " + start);
- break;
- }
- fdList = socket.getAncillaryFileDescriptors();
-
- // Add our starting point to the count and reset the start.
- count += start;
- start = 0;
-
- for (int i = 0; i < count; i++) {
- if (buffer[i] == 0) {
- // Note - do not log this raw message since it may contain
- // sensitive data
- final String rawEvent = new String(
- buffer, start, i - start, StandardCharsets.UTF_8);
-
- boolean releaseWl = false;
- try {
- final NativeDaemonEvent event =
- NativeDaemonEvent.parseRawEvent(rawEvent, fdList);
-
- log("RCV <- {" + event + "}");
-
- if (event.isClassUnsolicited()) {
- // TODO: migrate to sending NativeDaemonEvent instances
- if (mCallbacks.onCheckHoldWakeLock(event.getCode())
- && mWakeLock != null) {
- mWakeLock.acquire();
- releaseWl = true;
- }
- Message msg = mCallbackHandler.obtainMessage(
- event.getCode(), uptimeMillisInt(), 0, event.getRawEvent());
- if (mCallbackHandler.sendMessage(msg)) {
- releaseWl = false;
- }
- } else {
- mResponseQueue.add(event.getCmdNumber(), event);
- }
- } catch (IllegalArgumentException e) {
- log("Problem parsing message " + e);
- } finally {
- if (releaseWl) {
- mWakeLock.release();
- }
- }
-
- start = i + 1;
- }
- }
-
- if (start == 0) {
- log("RCV incomplete");
- }
-
- // We should end at the amount we read. If not, compact then
- // buffer and read again.
- if (start != count) {
- final int remaining = BUFFER_SIZE - start;
- System.arraycopy(buffer, start, buffer, 0, remaining);
- start = remaining;
- } else {
- start = 0;
- }
- }
- } catch (IOException ex) {
- loge("Communications error: " + ex);
- throw ex;
- } finally {
- synchronized (mDaemonLock) {
- if (mOutputStream != null) {
- try {
- loge("closing stream for " + mSocket);
- mOutputStream.close();
- } catch (IOException e) {
- loge("Failed closing output stream: " + e);
- }
- mOutputStream = null;
- }
- }
-
- try {
- if (socket != null) {
- socket.close();
- }
- } catch (IOException ex) {
- loge("Failed closing socket: " + ex);
- }
- }
- }
-
- /**
- * Wrapper around argument that indicates it's sensitive and shouldn't be
- * logged.
- */
- public static class SensitiveArg {
- private final Object mArg;
-
- public SensitiveArg(Object arg) {
- mArg = arg;
- }
-
- @Override
- public String toString() {
- return String.valueOf(mArg);
- }
- }
-
- /**
- * Make command for daemon, escaping arguments as needed.
- */
- @VisibleForTesting
- static void makeCommand(StringBuilder rawBuilder, StringBuilder logBuilder, int sequenceNumber,
- String cmd, Object... args) {
- if (cmd.indexOf('\0') >= 0) {
- throw new IllegalArgumentException("Unexpected command: " + cmd);
- }
- if (cmd.indexOf(' ') >= 0) {
- throw new IllegalArgumentException("Arguments must be separate from command");
- }
-
- rawBuilder.append(sequenceNumber).append(' ').append(cmd);
- logBuilder.append(sequenceNumber).append(' ').append(cmd);
- for (Object arg : args) {
- final String argString = String.valueOf(arg);
- if (argString.indexOf('\0') >= 0) {
- throw new IllegalArgumentException("Unexpected argument: " + arg);
- }
-
- rawBuilder.append(' ');
- logBuilder.append(' ');
-
- appendEscaped(rawBuilder, argString);
- if (arg instanceof SensitiveArg) {
- logBuilder.append("[scrubbed]");
- } else {
- appendEscaped(logBuilder, argString);
- }
- }
-
- rawBuilder.append('\0');
- }
-
- /**
- * Method that waits until all asychronous notifications sent by the native daemon have
- * been processed. This method must not be called on the notification thread or an
- * exception will be thrown.
- */
- public void waitForCallbacks() {
- if (Thread.currentThread() == mLooper.getThread()) {
- throw new IllegalStateException("Must not call this method on callback thread");
- }
-
- final CountDownLatch latch = new CountDownLatch(1);
- mCallbackHandler.post(new Runnable() {
- @Override
- public void run() {
- latch.countDown();
- }
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- Log.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
- }
- }
-
- /**
- * Issue the given command to the native daemon and return a single expected
- * response.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent execute(Command cmd) throws NativeDaemonConnectorException {
- return execute(cmd.mCmd, cmd.mArguments.toArray());
- }
-
- /**
- * Issue the given command to the native daemon and return a single expected
- * response. Any arguments must be separated from base command so they can
- * be properly escaped.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent execute(String cmd, Object... args)
- throws NativeDaemonConnectorException {
- return execute(DEFAULT_TIMEOUT, cmd, args);
- }
-
- public NativeDaemonEvent execute(long timeoutMs, String cmd, Object... args)
- throws NativeDaemonConnectorException {
- final NativeDaemonEvent[] events = executeForList(timeoutMs, cmd, args);
- if (events.length != 1) {
- throw new NativeDaemonConnectorException(
- "Expected exactly one response, but received " + events.length);
- }
- return events[0];
- }
-
- /**
- * Issue the given command to the native daemon and return any
- * {@link NativeDaemonEvent#isClassContinue()} responses, including the
- * final terminal response.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent[] executeForList(Command cmd) throws NativeDaemonConnectorException {
- return executeForList(cmd.mCmd, cmd.mArguments.toArray());
- }
-
- /**
- * Issue the given command to the native daemon and return any
- * {@link NativeDaemonEvent#isClassContinue()} responses, including the
- * final terminal response. Any arguments must be separated from base
- * command so they can be properly escaped.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent[] executeForList(String cmd, Object... args)
- throws NativeDaemonConnectorException {
- return executeForList(DEFAULT_TIMEOUT, cmd, args);
- }
-
- /**
- * Issue the given command to the native daemon and return any {@linke
- * NativeDaemonEvent@isClassContinue()} responses, including the final
- * terminal response. Note that the timeout does not count time in deep
- * sleep. Any arguments must be separated from base command so they can be
- * properly escaped.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
- throws NativeDaemonConnectorException {
- if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- 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 = new ArrayList<>();
-
- final StringBuilder rawBuilder = new StringBuilder();
- final StringBuilder logBuilder = new StringBuilder();
- final int sequenceNumber = mSequenceNumber.incrementAndGet();
-
- makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
-
- final String rawCmd = rawBuilder.toString();
- final String logCmd = logBuilder.toString();
-
- log("SND -> {" + logCmd + "}");
-
- synchronized (mDaemonLock) {
- if (mOutputStream == null) {
- throw new NativeDaemonConnectorException("missing output stream");
- } else {
- try {
- mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
- } catch (IOException e) {
- throw new NativeDaemonConnectorException("problem sending command", e);
- }
- }
- }
-
- NativeDaemonEvent event = null;
- do {
- event = mResponseQueue.remove(sequenceNumber, timeoutMs, logCmd);
- if (event == null) {
- loge("timed-out waiting for response to " + logCmd);
- throw new NativeDaemonTimeoutException(logCmd, event);
- }
- if (VDBG) log("RMV <- {" + event + "}");
- events.add(event);
- } while (event.isClassContinue());
-
- final long endTime = SystemClock.elapsedRealtime();
- if (endTime - startTime > WARN_EXECUTE_DELAY_MS) {
- loge("NDC Command {" + logCmd + "} took too long (" + (endTime - startTime) + "ms)");
- }
-
- if (event.isClassClientError()) {
- throw new NativeDaemonArgumentException(logCmd, event);
- }
- if (event.isClassServerError()) {
- throw new NativeDaemonFailureException(logCmd, event);
- }
-
- return events.toArray(new NativeDaemonEvent[events.size()]);
- }
-
- /**
- * Append the given argument to {@link StringBuilder}, escaping as needed,
- * and surrounding with quotes when it contains spaces.
- */
- @VisibleForTesting
- static void appendEscaped(StringBuilder builder, String arg) {
- final boolean hasSpaces = arg.indexOf(' ') >= 0;
- if (hasSpaces) {
- builder.append('"');
- }
-
- final int length = arg.length();
- for (int i = 0; i < length; i++) {
- final char c = arg.charAt(i);
-
- if (c == '"') {
- builder.append("\\\"");
- } else if (c == '\\') {
- builder.append("\\\\");
- } else {
- builder.append(c);
- }
- }
-
- if (hasSpaces) {
- builder.append('"');
- }
- }
-
- private static class NativeDaemonArgumentException extends NativeDaemonConnectorException {
- public NativeDaemonArgumentException(String command, NativeDaemonEvent event) {
- super(command, event);
- }
-
- @Override
- public IllegalArgumentException rethrowAsParcelableException() {
- throw new IllegalArgumentException(getMessage(), this);
- }
- }
-
- private static class NativeDaemonFailureException extends NativeDaemonConnectorException {
- public NativeDaemonFailureException(String command, NativeDaemonEvent event) {
- super(command, event);
- }
- }
-
- /**
- * Command builder that handles argument list building. Any arguments must
- * be separated from base command so they can be properly escaped.
- */
- public static class Command {
- private String mCmd;
- private ArrayList<Object> mArguments = new ArrayList<>();
-
- public Command(String cmd, Object... args) {
- mCmd = cmd;
- for (Object arg : args) {
- appendArg(arg);
- }
- }
-
- public Command appendArg(Object arg) {
- mArguments.add(arg);
- return this;
- }
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mLocalLog.dump(fd, pw, args);
- pw.println();
- mResponseQueue.dump(fd, pw, args);
- }
-
- private void log(String logstring) {
- if (mDebug) Log.d(TAG, logstring);
- mLocalLog.log(logstring);
- }
-
- private void loge(String logstring) {
- Log.e(TAG, logstring);
- mLocalLog.log(logstring);
- }
-
- private static class ResponseQueue {
-
- private static class PendingCmd {
- public final int cmdNum;
- public final String logCmd;
-
- public BlockingQueue<NativeDaemonEvent> responses =
- new ArrayBlockingQueue<NativeDaemonEvent>(10);
-
- // The availableResponseCount member is used to track when we can remove this
- // instance from the ResponseQueue.
- // This is used under the protection of a sync of the mPendingCmds object.
- // A positive value means we've had more writers retreive this object while
- // a negative value means we've had more readers. When we've had an equal number
- // (it goes to zero) we can remove this object from the mPendingCmds list.
- // Note that we may have more responses for this command (and more readers
- // coming), but that would result in a new PendingCmd instance being created
- // and added with the same cmdNum.
- // Also note that when this goes to zero it just means a parity of readers and
- // writers have retrieved this object - not that they are done using it. The
- // responses queue may well have more responses yet to be read or may get more
- // responses added to it. But all those readers/writers have retreived and
- // hold references to this instance already so it can be removed from
- // mPendingCmds queue.
- public int availableResponseCount;
-
- public PendingCmd(int cmdNum, String logCmd) {
- this.cmdNum = cmdNum;
- this.logCmd = logCmd;
- }
- }
-
- private final LinkedList<PendingCmd> mPendingCmds;
- private int mMaxCount;
-
- ResponseQueue(int maxCount) {
- mPendingCmds = new LinkedList<PendingCmd>();
- mMaxCount = maxCount;
- }
-
- public void add(int cmdNum, NativeDaemonEvent response) {
- PendingCmd found = null;
- synchronized (mPendingCmds) {
- for (PendingCmd pendingCmd : mPendingCmds) {
- if (pendingCmd.cmdNum == cmdNum) {
- found = pendingCmd;
- break;
- }
- }
- if (found == null) {
- // didn't find it - make sure our queue isn't too big before adding
- while (mPendingCmds.size() >= mMaxCount) {
- Log.e("NativeDaemonConnector.ResponseQueue",
- "more buffered than allowed: " + mPendingCmds.size() +
- " >= " + mMaxCount);
- // let any waiter timeout waiting for this
- PendingCmd pendingCmd = mPendingCmds.remove();
- Log.e("NativeDaemonConnector.ResponseQueue",
- "Removing request: " + pendingCmd.logCmd + " (" +
- pendingCmd.cmdNum + ")");
- }
- found = new PendingCmd(cmdNum, null);
- mPendingCmds.add(found);
- }
- found.availableResponseCount++;
- // if a matching remove call has already retrieved this we can remove this
- // instance from our list
- if (found.availableResponseCount == 0) mPendingCmds.remove(found);
- }
- try {
- found.responses.put(response);
- } catch (InterruptedException e) { }
- }
-
- // note that the timeout does not count time in deep sleep. If you don't want
- // the device to sleep, hold a wakelock
- public NativeDaemonEvent remove(int cmdNum, long timeoutMs, String logCmd) {
- PendingCmd found = null;
- synchronized (mPendingCmds) {
- for (PendingCmd pendingCmd : mPendingCmds) {
- if (pendingCmd.cmdNum == cmdNum) {
- found = pendingCmd;
- break;
- }
- }
- if (found == null) {
- found = new PendingCmd(cmdNum, logCmd);
- mPendingCmds.add(found);
- }
- found.availableResponseCount--;
- // if a matching add call has already retrieved this we can remove this
- // instance from our list
- if (found.availableResponseCount == 0) mPendingCmds.remove(found);
- }
- NativeDaemonEvent result = null;
- try {
- result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {}
- if (result == null) {
- Log.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
- }
- return result;
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("Pending requests:");
- synchronized (mPendingCmds) {
- for (PendingCmd pendingCmd : mPendingCmds) {
- pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.logCmd);
- }
- }
- }
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java
deleted file mode 100644
index 4d8881c..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 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 com.android.server;
-
-import android.os.Parcel;
-
-/**
- * An exception that indicates there was an error with a
- * {@link NativeDaemonConnector} operation.
- */
-public class NativeDaemonConnectorException extends Exception {
- private String mCmd;
- private NativeDaemonEvent mEvent;
-
- public NativeDaemonConnectorException(String detailMessage) {
- super(detailMessage);
- }
-
- public NativeDaemonConnectorException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
-
- public NativeDaemonConnectorException(String cmd, NativeDaemonEvent event) {
- super("command '" + cmd + "' failed with '" + event + "'");
- mCmd = cmd;
- mEvent = event;
- }
-
- public int getCode() {
- return mEvent != null ? mEvent.getCode() : -1;
- }
-
- public String getCmd() {
- return mCmd;
- }
-
- /**
- * Rethrow as a {@link RuntimeException} subclass that is handled by
- * {@link Parcel#writeException(Exception)}.
- */
- public IllegalArgumentException rethrowAsParcelableException() {
- throw new IllegalStateException(getMessage(), this);
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
deleted file mode 100644
index 5683694..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
+++ /dev/null
@@ -1,267 +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 com.android.server;
-
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.util.ArrayList;
-
-/**
- * Parsed event from native side of {@link NativeDaemonConnector}.
- */
-public class NativeDaemonEvent {
-
- // TODO: keep class ranges in sync with ResponseCode.h
- // TODO: swap client and server error ranges to roughly mirror HTTP spec
-
- private final int mCmdNumber;
- private final int mCode;
- private final String mMessage;
- private final String mRawEvent;
- private final String mLogMessage;
- private String[] mParsed;
- private FileDescriptor[] mFdList;
-
- private NativeDaemonEvent(int cmdNumber, int code, String message,
- String rawEvent, String logMessage, FileDescriptor[] fdList) {
- mCmdNumber = cmdNumber;
- mCode = code;
- mMessage = message;
- mRawEvent = rawEvent;
- mLogMessage = logMessage;
- mParsed = null;
- mFdList = fdList;
- }
-
- static public final String SENSITIVE_MARKER = "{{sensitive}}";
-
- public int getCmdNumber() {
- return mCmdNumber;
- }
-
- public int getCode() {
- return mCode;
- }
-
- public String getMessage() {
- return mMessage;
- }
-
- public FileDescriptor[] getFileDescriptors() {
- return mFdList;
- }
-
- @Deprecated
- public String getRawEvent() {
- return mRawEvent;
- }
-
- @Override
- public String toString() {
- return mLogMessage;
- }
-
- /**
- * Test if event represents a partial response which is continued in
- * additional subsequent events.
- */
- public boolean isClassContinue() {
- return mCode >= 100 && mCode < 200;
- }
-
- /**
- * Test if event represents a command success.
- */
- public boolean isClassOk() {
- return mCode >= 200 && mCode < 300;
- }
-
- /**
- * Test if event represents a remote native daemon error.
- */
- public boolean isClassServerError() {
- return mCode >= 400 && mCode < 500;
- }
-
- /**
- * Test if event represents a command syntax or argument error.
- */
- public boolean isClassClientError() {
- return mCode >= 500 && mCode < 600;
- }
-
- /**
- * Test if event represents an unsolicited event from native daemon.
- */
- public boolean isClassUnsolicited() {
- return isClassUnsolicited(mCode);
- }
-
- private static boolean isClassUnsolicited(int code) {
- return code >= 600 && code < 700;
- }
-
- /**
- * Verify this event matches the given code.
- *
- * @throws IllegalStateException if {@link #getCode()} doesn't match.
- */
- public void checkCode(int code) {
- if (mCode != code) {
- throw new IllegalStateException("Expected " + code + " but was: " + this);
- }
- }
-
- /**
- * Parse the given raw event into {@link NativeDaemonEvent} instance.
- *
- * @throws IllegalArgumentException when line doesn't match format expected
- * from native side.
- */
- public static NativeDaemonEvent parseRawEvent(String rawEvent, FileDescriptor[] fdList) {
- final String[] parsed = rawEvent.split(" ");
- if (parsed.length < 2) {
- throw new IllegalArgumentException("Insufficient arguments");
- }
-
- int skiplength = 0;
-
- final int code;
- try {
- code = Integer.parseInt(parsed[0]);
- skiplength = parsed[0].length() + 1;
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("problem parsing code", e);
- }
-
- int cmdNumber = -1;
- if (isClassUnsolicited(code) == false) {
- if (parsed.length < 3) {
- throw new IllegalArgumentException("Insufficient arguemnts");
- }
- try {
- cmdNumber = Integer.parseInt(parsed[1]);
- skiplength += parsed[1].length() + 1;
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("problem parsing cmdNumber", e);
- }
- }
-
- String logMessage = rawEvent;
- if (parsed.length > 2 && parsed[2].equals(SENSITIVE_MARKER)) {
- skiplength += parsed[2].length() + 1;
- logMessage = parsed[0] + " " + parsed[1] + " {}";
- }
-
- final String message = rawEvent.substring(skiplength);
-
- return new NativeDaemonEvent(cmdNumber, code, message, rawEvent, logMessage, fdList);
- }
-
- /**
- * Filter the given {@link NativeDaemonEvent} list, returning
- * {@link #getMessage()} for any events matching the requested code.
- */
- public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
- final ArrayList<String> result = new ArrayList<>();
- for (NativeDaemonEvent event : events) {
- if (event.getCode() == matchCode) {
- result.add(event.getMessage());
- }
- }
- return result.toArray(new String[result.size()]);
- }
-
- /**
- * Find the Nth field of the event.
- *
- * This ignores and code or cmdNum, the first return value is given for N=0.
- * Also understands "\"quoted\" multiword responses" and tries them as a single field
- */
- public String getField(int n) {
- if (mParsed == null) {
- mParsed = unescapeArgs(mRawEvent);
- }
- n += 2; // skip code and command#
- if (n > mParsed.length) return null;
- return mParsed[n];
- }
-
- public static String[] unescapeArgs(String rawEvent) {
- final boolean DEBUG_ROUTINE = false;
- final String LOGTAG = "unescapeArgs";
- final ArrayList<String> parsed = new ArrayList<String>();
- final int length = rawEvent.length();
- int current = 0;
- int wordEnd = -1;
- boolean quoted = false;
-
- if (DEBUG_ROUTINE) Log.e(LOGTAG, "parsing '" + rawEvent + "'");
- if (rawEvent.charAt(current) == '\"') {
- quoted = true;
- current++;
- }
- while (current < length) {
- // find the end of the word
- char terminator = quoted ? '\"' : ' ';
- wordEnd = current;
- while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
- if (rawEvent.charAt(wordEnd) == '\\') {
- // skip the escaped char
- ++wordEnd;
- }
- ++wordEnd;
- }
- if (wordEnd > length) wordEnd = length;
- String word = rawEvent.substring(current, wordEnd);
- current += word.length();
- if (!quoted) {
- word = word.trim();
- } else {
- current++; // skip the trailing quote
- }
- // unescape stuff within the word
- word = word.replace("\\\\", "\\");
- word = word.replace("\\\"", "\"");
-
- 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) {
- Log.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
- }
- if (nextQuote > -1 && nextQuote <= nextSpace) {
- quoted = true;
- current = nextQuote + 2;
- } else {
- quoted = false;
- if (nextSpace > -1) {
- current = nextSpace + 1;
- }
- } // else we just start the next word after the current and read til the end
- if (DEBUG_ROUTINE) {
- Log.e(LOGTAG, "next loop - current=" + current
- + ", length=" + length + ", quoted=" + quoted);
- }
- }
- return parsed.toArray(new String[parsed.size()]);
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java
deleted file mode 100644
index 658f7d6..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 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 com.android.server;
-
-/**
- * An exception that indicates there was a timeout with a
- * {@link NativeDaemonConnector} operation.
- */
-public class NativeDaemonTimeoutException extends NativeDaemonConnectorException {
- public NativeDaemonTimeoutException(String command, NativeDaemonEvent event) {
- super(command, event);
- }
-}
-
diff --git a/packages/ConnectivityT/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
deleted file mode 100644
index ddf6d2c..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NsdService.java
+++ /dev/null
@@ -1,1146 +0,0 @@
-/*
- * 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 com.android.server;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.Network;
-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.RemoteException;
-import android.os.UserHandle;
-import android.util.Base64;
-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.State;
-import com.android.internal.util.StateMachine;
-import com.android.net.module.util.DnsSdTxtRecord;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Network Service Discovery Service handles remote service discovery operation requests by
- * implementing the INsdManager interface.
- *
- * @hide
- */
-public class NsdService extends INsdManager.Stub {
- private static final String TAG = "NsdService";
- private static final String MDNS_TAG = "mDnsConnector";
-
- private static final boolean DBG = true;
- private static final long CLEANUP_DELAY_MS = 10000;
- private static final int IFACE_IDX_ANY = 0;
-
- private final Context mContext;
- private final NsdStateMachine mNsdStateMachine;
- private final DaemonConnection mDaemon;
- private final NativeCallbackReceiver mDaemonCallback;
-
- /**
- * Clients receiving asynchronous messages
- */
- 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 long mCleanupDelayMs;
-
- private static final int INVALID_ID = 0;
- private int mUniqueId = 1;
- // The count of the connected legacy clients.
- private int mLegacyClientCount = 0;
-
- private class NsdStateMachine extends StateMachine {
-
- private final DefaultState mDefaultState = new DefaultState();
- private final DisabledState mDisabledState = new DisabledState();
- private final EnabledState mEnabledState = new EnabledState();
-
- @Override
- protected String getWhatToString(int what) {
- return NsdManager.nameOf(what);
- }
-
- private void maybeStartDaemon() {
- mDaemon.maybeStart();
- maybeScheduleStop();
- }
-
- private boolean isAnyRequestActive() {
- return mIdToClientInfoMap.size() != 0;
- }
-
- private void scheduleStop() {
- sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs);
- }
- private void maybeScheduleStop() {
- // The native daemon should stay alive and can't be cleanup
- // if any legacy client connected.
- if (!isAnyRequestActive() && mLegacyClientCount == 0) {
- scheduleStop();
- }
- }
-
- private void cancelStop() {
- this.removeMessages(NsdManager.DAEMON_CLEANUP);
- }
-
- NsdStateMachine(String name, Handler handler) {
- super(name, handler);
- addState(mDefaultState);
- addState(mDisabledState, mDefaultState);
- addState(mEnabledState, mDefaultState);
- State initialState = mEnabledState;
- setInitialState(initialState);
- setLogRecSize(25);
- }
-
- class DefaultState extends State {
- @Override
- public boolean processMessage(Message msg) {
- final ClientInfo cInfo;
- final int clientId = msg.arg2;
- switch (msg.what) {
- 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 NsdManager.UNREGISTER_CLIENT:
- final NsdServiceConnector connector = (NsdServiceConnector) msg.obj;
- cInfo = mClients.remove(connector);
- if (cInfo != null) {
- cInfo.expungeAllRequests();
- if (cInfo.isLegacy()) {
- mLegacyClientCount -= 1;
- }
- }
- maybeScheduleStop();
- break;
- case NsdManager.DISCOVER_SERVICES:
- cInfo = getClientInfoForReply(msg);
- if (cInfo != null) {
- cInfo.onDiscoverServicesFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.STOP_DISCOVERY:
- cInfo = getClientInfoForReply(msg);
- if (cInfo != null) {
- cInfo.onStopDiscoveryFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.REGISTER_SERVICE:
- cInfo = getClientInfoForReply(msg);
- if (cInfo != null) {
- cInfo.onRegisterServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.UNREGISTER_SERVICE:
- cInfo = getClientInfoForReply(msg);
- if (cInfo != null) {
- cInfo.onUnregisterServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.RESOLVE_SERVICE:
- cInfo = getClientInfoForReply(msg);
- if (cInfo != null) {
- cInfo.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.DAEMON_CLEANUP:
- mDaemon.maybeStop();
- break;
- // This event should be only sent by the legacy (target SDK < S) clients.
- // Mark the sending client as legacy.
- case NsdManager.DAEMON_STARTUP:
- cInfo = getClientInfoForReply(msg);
- if (cInfo != null) {
- cancelStop();
- cInfo.setLegacy();
- mLegacyClientCount += 1;
- maybeStartDaemon();
- }
- break;
- case NsdManager.NATIVE_DAEMON_EVENT:
- default:
- 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 {
- @Override
- public void enter() {
- sendNsdStateChangeBroadcast(false);
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case NsdManager.ENABLE:
- transitionTo(mEnabledState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class EnabledState extends State {
- @Override
- public void enter() {
- sendNsdStateChangeBroadcast(true);
- }
-
- @Override
- public void exit() {
- // TODO: it is incorrect to stop the daemon without expunging all requests
- // and sending error callbacks to clients.
- scheduleStop();
- }
-
- private boolean requestLimitReached(ClientInfo clientInfo) {
- if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
- if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo);
- return true;
- }
- return false;
- }
-
- private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
- clientInfo.mClientIds.put(clientId, globalId);
- clientInfo.mClientRequests.put(clientId, what);
- mIdToClientInfoMap.put(globalId, clientInfo);
- // Remove the cleanup event because here comes a new request.
- cancelStop();
- }
-
- private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
- clientInfo.mClientIds.delete(clientId);
- clientInfo.mClientRequests.delete(clientId);
- mIdToClientInfoMap.remove(globalId);
- maybeScheduleStop();
- }
-
- @Override
- public boolean processMessage(Message msg) {
- final ClientInfo clientInfo;
- final int id;
- final int clientId = msg.arg2;
- final ListenerArgs args;
- switch (msg.what) {
- case NsdManager.DISABLE:
- //TODO: cleanup clients
- transitionTo(mDisabledState);
- break;
- case NsdManager.DISCOVER_SERVICES:
- if (DBG) Log.d(TAG, "Discover services");
- args = (ListenerArgs) msg.obj;
- clientInfo = mClients.get(args.connector);
-
- if (requestLimitReached(clientInfo)) {
- clientInfo.onDiscoverServicesFailed(
- clientId, NsdManager.FAILURE_MAX_LIMIT);
- break;
- }
-
- maybeStartDaemon();
- id = getUniqueId();
- if (discoverServices(id, args.serviceInfo)) {
- if (DBG) {
- Log.d(TAG, "Discover " + msg.arg2 + " " + id
- + args.serviceInfo.getServiceType());
- }
- storeRequestMap(clientId, id, clientInfo, msg.what);
- clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
- } else {
- stopServiceDiscovery(id);
- clientInfo.onDiscoverServicesFailed(clientId,
- NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.STOP_DISCOVERY:
- if (DBG) Log.d(TAG, "Stop service discovery");
- args = (ListenerArgs) msg.obj;
- clientInfo = mClients.get(args.connector);
-
- try {
- id = clientInfo.mClientIds.get(clientId);
- } catch (NullPointerException e) {
- clientInfo.onStopDiscoveryFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- break;
- }
- removeRequestMap(clientId, id, clientInfo);
- if (stopServiceDiscovery(id)) {
- clientInfo.onStopDiscoverySucceeded(clientId);
- } else {
- clientInfo.onStopDiscoveryFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.REGISTER_SERVICE:
- if (DBG) Log.d(TAG, "Register service");
- args = (ListenerArgs) msg.obj;
- clientInfo = mClients.get(args.connector);
- if (requestLimitReached(clientInfo)) {
- clientInfo.onRegisterServiceFailed(
- clientId, NsdManager.FAILURE_MAX_LIMIT);
- break;
- }
-
- maybeStartDaemon();
- id = getUniqueId();
- 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);
- clientInfo.onRegisterServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.UNREGISTER_SERVICE:
- 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;
- }
- id = clientInfo.mClientIds.get(clientId);
- removeRequestMap(clientId, id, clientInfo);
- if (unregisterService(id)) {
- clientInfo.onUnregisterServiceSucceeded(clientId);
- } else {
- clientInfo.onUnregisterServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.RESOLVE_SERVICE:
- if (DBG) Log.d(TAG, "Resolve service");
- args = (ListenerArgs) msg.obj;
- clientInfo = mClients.get(args.connector);
-
- if (clientInfo.mResolvedService != null) {
- clientInfo.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
- break;
- }
-
- maybeStartDaemon();
- id = getUniqueId();
- if (resolveService(id, args.serviceInfo)) {
- clientInfo.mResolvedService = new NsdServiceInfo();
- storeRequestMap(clientId, id, clientInfo, msg.what);
- } else {
- clientInfo.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- break;
- case NsdManager.NATIVE_DAEMON_EVENT:
- NativeEvent event = (NativeEvent) msg.obj;
- if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
- return NOT_HANDLED;
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- private boolean handleNativeEvent(int code, String raw, String[] cooked) {
- NsdServiceInfo servInfo;
- int id = Integer.parseInt(cooked[1]);
- ClientInfo clientInfo = mIdToClientInfoMap.get(id);
- if (clientInfo == null) {
- String name = NativeResponseCode.nameOf(code);
- Log.e(TAG, String.format("id %d for %s has no client mapping", id, name));
- return false;
- }
-
- /* This goes in response as msg.arg2 */
- int clientId = clientInfo.getClientId(id);
- if (clientId < 0) {
- // This can happen because of race conditions. For example,
- // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
- // and we may get in this situation.
- String name = NativeResponseCode.nameOf(code);
- 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);
- Log.d(TAG, String.format("Native daemon message %s: %s", name, raw));
- }
- switch (code) {
- case NativeResponseCode.SERVICE_FOUND:
- /* NNN uniqueId serviceName regType domain interfaceIdx netId */
- servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
- final int foundNetId;
- try {
- foundNetId = Integer.parseInt(cooked[6]);
- } catch (NumberFormatException e) {
- Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
- break;
- }
- if (foundNetId == 0L) {
- // Ignore services that do not have a Network: they are not usable
- // by apps, as they would need privileged permissions to use
- // interfaces that do not have an associated Network.
- break;
- }
- servInfo.setNetwork(new Network(foundNetId));
- clientInfo.onServiceFound(clientId, servInfo);
- break;
- case NativeResponseCode.SERVICE_LOST:
- /* NNN uniqueId serviceName regType domain interfaceIdx netId */
- final int lostNetId;
- try {
- lostNetId = Integer.parseInt(cooked[6]);
- } catch (NumberFormatException e) {
- Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
- break;
- }
- servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
- // The network could be null if it was torn down when the service is lost
- // TODO: avoid returning null in that case, possibly by remembering found
- // services on the same interface index and their network at the time
- servInfo.setNetwork(lostNetId == 0 ? null : new Network(lostNetId));
- clientInfo.onServiceLost(clientId, servInfo);
- break;
- case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
- /* NNN uniqueId errorCode */
- clientInfo.onDiscoverServicesFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- break;
- case NativeResponseCode.SERVICE_REGISTERED:
- /* NNN regId serviceName regType */
- servInfo = new NsdServiceInfo(cooked[2], null);
- clientInfo.onRegisterServiceSucceeded(clientId, servInfo);
- break;
- case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
- /* NNN regId errorCode */
- clientInfo.onRegisterServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- break;
- case NativeResponseCode.SERVICE_UPDATED:
- /* NNN regId */
- break;
- case NativeResponseCode.SERVICE_UPDATE_FAILED:
- /* NNN regId errorCode */
- break;
- case NativeResponseCode.SERVICE_RESOLVED:
- /* NNN resolveId fullName hostName port txtlen txtdata interfaceIdx */
- int index = 0;
- while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
- if (cooked[2].charAt(index) == '\\') {
- ++index;
- }
- ++index;
- }
- if (index >= cooked[2].length()) {
- Log.e(TAG, "Invalid service found " + raw);
- break;
- }
-
- String name = cooked[2].substring(0, index);
- String rest = cooked[2].substring(index);
- String type = rest.replace(".local.", "");
-
- name = unescape(name);
-
- clientInfo.mResolvedService.setServiceName(name);
- clientInfo.mResolvedService.setServiceType(type);
- clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
- clientInfo.mResolvedService.setTxtRecords(cooked[6]);
- // Network will be added after SERVICE_GET_ADDR_SUCCESS
-
- stopResolveService(id);
- removeRequestMap(clientId, id, clientInfo);
-
- int id2 = getUniqueId();
- if (getAddrInfo(id2, cooked[3], cooked[7] /* interfaceIdx */)) {
- storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
- } else {
- clientInfo.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- clientInfo.mResolvedService = null;
- }
- break;
- case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
- /* NNN resolveId errorCode */
- stopResolveService(id);
- removeRequestMap(clientId, id, clientInfo);
- clientInfo.mResolvedService = null;
- 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.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- break;
- case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
- /* NNN resolveId hostname ttl addr interfaceIdx netId */
- Network network = null;
- try {
- final int netId = Integer.parseInt(cooked[6]);
- network = netId == 0L ? null : new Network(netId);
- } catch (NumberFormatException e) {
- Log.wtf(TAG, "Invalid network in GET_ADDR_SUCCESS: " + cooked[6], e);
- }
-
- InetAddress serviceHost = null;
- try {
- serviceHost = InetAddress.getByName(cooked[4]);
- } catch (UnknownHostException e) {
- Log.wtf(TAG, "Invalid host in GET_ADDR_SUCCESS", e);
- }
-
- // If the resolved service is on an interface without a network, consider it
- // as a failure: it would not be usable by apps as they would need
- // privileged permissions.
- if (network != null && serviceHost != null) {
- clientInfo.mResolvedService.setHost(serviceHost);
- clientInfo.mResolvedService.setNetwork(network);
- clientInfo.onResolveServiceSucceeded(
- clientId, clientInfo.mResolvedService);
- } else {
- clientInfo.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- stopGetAddrInfo(id);
- removeRequestMap(clientId, id, clientInfo);
- clientInfo.mResolvedService = null;
- break;
- default:
- return false;
- }
- return true;
- }
- }
- }
-
- private String unescape(String s) {
- StringBuilder sb = new StringBuilder(s.length());
- for (int i = 0; i < s.length(); ++i) {
- char c = s.charAt(i);
- if (c == '\\') {
- if (++i >= s.length()) {
- Log.e(TAG, "Unexpected end of escape sequence in: " + s);
- break;
- }
- c = s.charAt(i);
- if (c != '.' && c != '\\') {
- if (i + 2 >= s.length()) {
- 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'));
- i += 2;
- }
- }
- sb.append(c);
- }
- return sb.toString();
- }
-
- @VisibleForTesting
- NsdService(Context ctx, Handler handler, DaemonConnectionSupplier fn, long cleanupDelayMs) {
- mCleanupDelayMs = cleanupDelayMs;
- mContext = ctx;
- mNsdStateMachine = new NsdStateMachine(TAG, handler);
- mNsdStateMachine.start();
- mDaemonCallback = new NativeCallbackReceiver();
- mDaemon = fn.get(mDaemonCallback);
- }
-
- public static NsdService create(Context context) throws InterruptedException {
- HandlerThread thread = new HandlerThread(TAG);
- thread.start();
- Handler handler = new Handler(thread.getLooper());
- NsdService service =
- new NsdService(context, handler, DaemonConnection::new, CLEANUP_DELAY_MS);
- service.mDaemonCallback.awaitConnection();
- return service;
- }
-
- @Override
- public INsdServiceConnector connect(INsdManagerCallback cb) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
- final INsdServiceConnector connector = new NsdServiceConnector();
- mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
- NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb)));
- return connector;
- }
-
- private static class ListenerArgs {
- public final NsdServiceConnector connector;
- public final NsdServiceInfo serviceInfo;
- ListenerArgs(NsdServiceConnector connector, NsdServiceInfo serviceInfo) {
- this.connector = connector;
- this.serviceInfo = serviceInfo;
- }
- }
-
- 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) {
- final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- int nsdState = isEnabled ? NsdManager.NSD_STATE_ENABLED : NsdManager.NSD_STATE_DISABLED;
- intent.putExtra(NsdManager.EXTRA_NSD_STATE, nsdState);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private int getUniqueId() {
- if (++mUniqueId == INVALID_ID) return ++mUniqueId;
- return mUniqueId;
- }
-
- /* These should be in sync with system/netd/server/ResponseCode.h */
- static final class NativeResponseCode {
- public static final int SERVICE_DISCOVERY_FAILED = 602;
- public static final int SERVICE_FOUND = 603;
- public static final int SERVICE_LOST = 604;
-
- public static final int SERVICE_REGISTRATION_FAILED = 605;
- public static final int SERVICE_REGISTERED = 606;
-
- public static final int SERVICE_RESOLUTION_FAILED = 607;
- public static final int SERVICE_RESOLVED = 608;
-
- public static final int SERVICE_UPDATED = 609;
- public static final int SERVICE_UPDATE_FAILED = 610;
-
- public static final int SERVICE_GET_ADDR_FAILED = 611;
- public static final int SERVICE_GET_ADDR_SUCCESS = 612;
-
- private static final SparseArray<String> CODE_NAMES = new SparseArray<>();
- static {
- CODE_NAMES.put(SERVICE_DISCOVERY_FAILED, "SERVICE_DISCOVERY_FAILED");
- CODE_NAMES.put(SERVICE_FOUND, "SERVICE_FOUND");
- CODE_NAMES.put(SERVICE_LOST, "SERVICE_LOST");
- CODE_NAMES.put(SERVICE_REGISTRATION_FAILED, "SERVICE_REGISTRATION_FAILED");
- CODE_NAMES.put(SERVICE_REGISTERED, "SERVICE_REGISTERED");
- CODE_NAMES.put(SERVICE_RESOLUTION_FAILED, "SERVICE_RESOLUTION_FAILED");
- CODE_NAMES.put(SERVICE_RESOLVED, "SERVICE_RESOLVED");
- CODE_NAMES.put(SERVICE_UPDATED, "SERVICE_UPDATED");
- CODE_NAMES.put(SERVICE_UPDATE_FAILED, "SERVICE_UPDATE_FAILED");
- CODE_NAMES.put(SERVICE_GET_ADDR_FAILED, "SERVICE_GET_ADDR_FAILED");
- CODE_NAMES.put(SERVICE_GET_ADDR_SUCCESS, "SERVICE_GET_ADDR_SUCCESS");
- }
-
- static String nameOf(int code) {
- String name = CODE_NAMES.get(code);
- if (name == null) {
- return Integer.toString(code);
- }
- return name;
- }
- }
-
- private class NativeEvent {
- final int code;
- final String raw;
- final String[] cooked;
-
- NativeEvent(int code, String raw, String[] cooked) {
- this.code = code;
- this.raw = raw;
- this.cooked = cooked;
- }
- }
-
- class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
- private final CountDownLatch connected = new CountDownLatch(1);
-
- public void awaitConnection() throws InterruptedException {
- connected.await();
- }
-
- @Override
- public void onDaemonConnected() {
- connected.countDown();
- }
-
- @Override
- public boolean onCheckHoldWakeLock(int code) {
- return false;
- }
-
- @Override
- public boolean onEvent(int code, String raw, String[] cooked) {
- // TODO: NDC translates a message to a callback, we could enhance NDC to
- // directly interact with a state machine through messages
- NativeEvent event = new NativeEvent(code, raw, cooked);
- mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
- return true;
- }
- }
-
- interface DaemonConnectionSupplier {
- DaemonConnection get(NativeCallbackReceiver callback);
- }
-
- @VisibleForTesting
- public static class DaemonConnection {
- final NativeDaemonConnector mNativeConnector;
- boolean mIsStarted = false;
-
- DaemonConnection(NativeCallbackReceiver callback) {
- mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
- new Thread(mNativeConnector, MDNS_TAG).start();
- }
-
- /**
- * Executes the specified cmd on the daemon.
- */
- public boolean execute(Object... args) {
- if (DBG) {
- Log.d(TAG, "mdnssd " + Arrays.toString(args));
- }
- try {
- mNativeConnector.execute("mdnssd", args);
- } catch (NativeDaemonConnectorException e) {
- Log.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
- return false;
- }
- return true;
- }
-
- /**
- * Starts the daemon if it is not already started.
- */
- public void maybeStart() {
- if (mIsStarted) {
- return;
- }
- execute("start-service");
- mIsStarted = true;
- }
-
- /**
- * Stops the daemon if it is started.
- */
- public void maybeStop() {
- if (!mIsStarted) {
- return;
- }
- execute("stop-service");
- mIsStarted = false;
- }
- }
-
- private boolean registerService(int regId, NsdServiceInfo service) {
- if (DBG) {
- Log.d(TAG, "registerService: " + regId + " " + service);
- }
- String name = service.getServiceName();
- String type = service.getServiceType();
- int port = service.getPort();
- byte[] textRecord = service.getTxtRecord();
- String record = Base64.encodeToString(textRecord, Base64.DEFAULT).replace("\n", "");
- return mDaemon.execute("register", regId, name, type, port, record);
- }
-
- private boolean unregisterService(int regId) {
- return mDaemon.execute("stop-register", regId);
- }
-
- private boolean updateService(int regId, DnsSdTxtRecord t) {
- if (t == null) {
- return false;
- }
- return mDaemon.execute("update", regId, t.size(), t.getRawData());
- }
-
- private boolean discoverServices(int discoveryId, NsdServiceInfo serviceInfo) {
- final Network network = serviceInfo.getNetwork();
- final int discoverInterface = getNetworkInterfaceIndex(network);
- if (network != null && discoverInterface == IFACE_IDX_ANY) {
- Log.e(TAG, "Interface to discover service on not found");
- return false;
- }
- return mDaemon.execute("discover", discoveryId, serviceInfo.getServiceType(),
- discoverInterface);
- }
-
- private boolean stopServiceDiscovery(int discoveryId) {
- return mDaemon.execute("stop-discover", discoveryId);
- }
-
- private boolean resolveService(int resolveId, NsdServiceInfo service) {
- final String name = service.getServiceName();
- final String type = service.getServiceType();
- final Network network = service.getNetwork();
- final int resolveInterface = getNetworkInterfaceIndex(network);
- if (network != null && resolveInterface == IFACE_IDX_ANY) {
- Log.e(TAG, "Interface to resolve service on not found");
- return false;
- }
- return mDaemon.execute("resolve", resolveId, name, type, "local.", resolveInterface);
- }
-
- /**
- * Guess the interface to use to resolve or discover a service on a specific network.
- *
- * This is an imperfect guess, as for example the network may be gone or not yet fully
- * registered. This is fine as failing is correct if the network is gone, and a client
- * attempting to resolve/discover on a network not yet setup would have a bad time anyway; also
- * this is to support the legacy mdnsresponder implementation, which historically resolved
- * services on an unspecified network.
- */
- private int getNetworkInterfaceIndex(Network network) {
- if (network == null) return IFACE_IDX_ANY;
-
- final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
- if (cm == null) {
- Log.wtf(TAG, "No ConnectivityManager for resolveService");
- return IFACE_IDX_ANY;
- }
- final LinkProperties lp = cm.getLinkProperties(network);
- if (lp == null) return IFACE_IDX_ANY;
-
- // Only resolve on non-stacked interfaces
- final NetworkInterface iface;
- try {
- iface = NetworkInterface.getByName(lp.getInterfaceName());
- } catch (SocketException e) {
- Log.e(TAG, "Error querying interface", e);
- return IFACE_IDX_ANY;
- }
-
- if (iface == null) {
- Log.e(TAG, "Interface not found: " + lp.getInterfaceName());
- return IFACE_IDX_ANY;
- }
-
- return iface.getIndex();
- }
-
- private boolean stopResolveService(int resolveId) {
- return mDaemon.execute("stop-resolve", resolveId);
- }
-
- private boolean getAddrInfo(int resolveId, String hostname, String interfaceIdx) {
- // interfaceIdx is always obtained (as string) from the service resolved callback
- return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceIdx);
- }
-
- private boolean stopGetAddrInfo(int resolveId) {
- return mDaemon.execute("stop-getaddrinfo", resolveId);
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- 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");
- pw.println(client);
- }
-
- mNsdStateMachine.dump(fd, pw, args);
- }
-
- /* Information tracked per client */
- private class ClientInfo {
-
- private static final int MAX_LIMIT = 10;
- private final INsdManagerCallback mCb;
- /* Remembers a resolved service until getaddrinfo completes */
- private NsdServiceInfo mResolvedService;
-
- /* A map from client id to unique id sent to mDns */
- private final SparseIntArray mClientIds = new SparseIntArray();
-
- /* A map from client id to the type of the request we had received */
- private final SparseIntArray mClientRequests = new SparseIntArray();
-
- // The target SDK of this client < Build.VERSION_CODES.S
- private boolean mIsLegacy = false;
-
- private ClientInfo(INsdManagerCallback cb) {
- mCb = cb;
- if (DBG) Log.d(TAG, "New client");
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("mResolvedService ").append(mResolvedService).append("\n");
- sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
- for(int i = 0; i< mClientIds.size(); i++) {
- int clientID = mClientIds.keyAt(i);
- sb.append("clientId ").append(clientID).
- append(" mDnsId ").append(mClientIds.valueAt(i)).
- append(" type ").append(mClientRequests.get(clientID)).append("\n");
- }
- return sb.toString();
- }
-
- private boolean isLegacy() {
- return mIsLegacy;
- }
-
- private void setLegacy() {
- mIsLegacy = true;
- }
-
- // Remove any pending requests from the global map when we get rid of a client,
- // and send cancellations to the daemon.
- private void expungeAllRequests() {
- int globalId, clientId, i;
- // TODO: to keep handler responsive, do not clean all requests for that client at once.
- for (i = 0; i < mClientIds.size(); i++) {
- clientId = mClientIds.keyAt(i);
- globalId = mClientIds.valueAt(i);
- mIdToClientInfoMap.remove(globalId);
- 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);
- break;
- case NsdManager.RESOLVE_SERVICE:
- stopResolveService(globalId);
- break;
- case NsdManager.REGISTER_SERVICE:
- unregisterService(globalId);
- break;
- default:
- break;
- }
- }
- mClientIds.clear();
- mClientRequests.clear();
- }
-
- // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id,
- // return the corresponding listener id. mDnsClient id is also called a global id.
- private int getClientId(final int globalId) {
- int idx = mClientIds.indexOfValue(globalId);
- if (idx < 0) {
- return idx;
- }
- return mClientIds.keyAt(idx);
- }
-
- void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
- try {
- mCb.onDiscoverServicesStarted(listenerKey, info);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling onDiscoverServicesStarted", e);
- }
- }
-
- void onDiscoverServicesFailed(int listenerKey, int error) {
- try {
- mCb.onDiscoverServicesFailed(listenerKey, error);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling onDiscoverServicesFailed", e);
- }
- }
-
- void onServiceFound(int listenerKey, NsdServiceInfo info) {
- try {
- mCb.onServiceFound(listenerKey, info);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling onServiceFound(", e);
- }
- }
-
- 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/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
deleted file mode 100644
index 25c88eb..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import android.content.Context;
-import android.net.INetd;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.ErrnoException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
-import com.android.net.module.util.BpfMap;
-import com.android.net.module.util.IBpfMap;
-import com.android.net.module.util.InterfaceParams;
-import com.android.net.module.util.Struct.U32;
-
-/**
- * Monitor interface added (without removed) and right interface name and its index to bpf map.
- */
-public class BpfInterfaceMapUpdater {
- private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName();
- // This is current path but may be changed soon.
- private static final String IFACE_INDEX_NAME_MAP_PATH =
- "/sys/fs/bpf/map_netd_iface_index_name_map";
- private final IBpfMap<U32, InterfaceMapValue> mBpfMap;
- private final INetd mNetd;
- private final Handler mHandler;
- private final Dependencies mDeps;
-
- public BpfInterfaceMapUpdater(Context ctx, Handler handler) {
- this(ctx, handler, new Dependencies());
- }
-
- @VisibleForTesting
- public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) {
- mDeps = deps;
- mBpfMap = deps.getInterfaceMap();
- mNetd = deps.getINetd(ctx);
- mHandler = handler;
- }
-
- /**
- * Dependencies of BpfInerfaceMapUpdater, for injection in tests.
- */
- @VisibleForTesting
- public static class Dependencies {
- /** Create BpfMap for updating interface and index mapping. */
- public IBpfMap<U32, InterfaceMapValue> getInterfaceMap() {
- try {
- return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR,
- U32.class, InterfaceMapValue.class);
- } catch (ErrnoException e) {
- Log.e(TAG, "Cannot create interface map: " + e);
- return null;
- }
- }
-
- /** Get InterfaceParams for giving interface name. */
- public InterfaceParams getInterfaceParams(String ifaceName) {
- return InterfaceParams.getByName(ifaceName);
- }
-
- /** Get INetd binder object. */
- public INetd getINetd(Context ctx) {
- return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE));
- }
- }
-
- /**
- * Start listening interface update event.
- * Query current interface names before listening.
- */
- public void start() {
- mHandler.post(() -> {
- if (mBpfMap == null) {
- Log.wtf(TAG, "Fail to start: Null bpf map");
- return;
- }
-
- try {
- // TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead.
- mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver());
- } catch (RemoteException e) {
- Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e);
- }
-
- final String[] ifaces;
- try {
- // TODO: use a netlink dump to get the current interface list.
- ifaces = mNetd.interfaceGetList();
- } catch (RemoteException | ServiceSpecificException e) {
- Log.wtf(TAG, "Unable to query interface names by netd, " + e);
- return;
- }
-
- for (String ifaceName : ifaces) {
- addInterface(ifaceName);
- }
- });
- }
-
- private void addInterface(String ifaceName) {
- final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName);
- if (iface == null) {
- Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName);
- return;
- }
-
- try {
- mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName));
- } catch (ErrnoException e) {
- Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e);
- }
- }
-
- private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener {
- @Override
- public void onInterfaceAdded(String ifName) {
- mHandler.post(() -> addInterface(ifName));
- }
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
deleted file mode 100644
index 443e5b3..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Key for cookie tag map.
- */
-public class CookieTagMapKey extends Struct {
- @Field(order = 0, type = Type.S64)
- public final long socketCookie;
-
- public CookieTagMapKey(final long socketCookie) {
- this.socketCookie = socketCookie;
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
deleted file mode 100644
index 93b9195..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Value for cookie tag map.
- */
-public class CookieTagMapValue extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long uid;
-
- @Field(order = 1, type = Type.U32)
- public final long tag;
-
- public CookieTagMapValue(final long uid, final long tag) {
- this.uid = uid;
- this.tag = tag;
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
deleted file mode 100644
index 35dc455..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.server.net;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.BufferedOutputStream;
-import java.io.DataOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * This class provides APIs to do a delayed data write to a given {@link OutputStream}.
- */
-public class DelayedDiskWrite {
- private static final String TAG = "DelayedDiskWrite";
-
- private HandlerThread mDiskWriteHandlerThread;
- private Handler mDiskWriteHandler;
- /* Tracks multiple writes on the same thread */
- private int mWriteSequence = 0;
-
- /**
- * Used to do a delayed data write to a given {@link OutputStream}.
- */
- public interface Writer {
- /**
- * write data to a given {@link OutputStream}.
- */
- void onWriteCalled(DataOutputStream out) throws IOException;
- }
-
- /**
- * Do a delayed data write to a given output stream opened from filePath.
- */
- public void write(final String filePath, final Writer w) {
- write(filePath, w, true);
- }
-
- /**
- * Do a delayed data write to a given output stream opened from filePath.
- */
- public void write(final String filePath, final Writer w, final boolean open) {
- if (TextUtils.isEmpty(filePath)) {
- throw new IllegalArgumentException("empty file path");
- }
-
- /* Do a delayed write to disk on a separate handler thread */
- synchronized (this) {
- if (++mWriteSequence == 1) {
- mDiskWriteHandlerThread = new HandlerThread("DelayedDiskWriteThread");
- mDiskWriteHandlerThread.start();
- mDiskWriteHandler = new Handler(mDiskWriteHandlerThread.getLooper());
- }
- }
-
- mDiskWriteHandler.post(new Runnable() {
- @Override
- public void run() {
- doWrite(filePath, w, open);
- }
- });
- }
-
- private void doWrite(String filePath, Writer w, boolean open) {
- DataOutputStream out = null;
- try {
- if (open) {
- out = new DataOutputStream(new BufferedOutputStream(
- new FileOutputStream(filePath)));
- }
- w.onWriteCalled(out);
- } catch (IOException e) {
- loge("Error writing data file " + filePath);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (Exception e) { }
- }
-
- // Quit if no more writes sent
- synchronized (this) {
- if (--mWriteSequence == 0) {
- mDiskWriteHandler.getLooper().quit();
- mDiskWriteHandler = null;
- mDiskWriteHandlerThread = null;
- }
- }
- }
- }
-
- private void loge(String s) {
- Log.e(TAG, s);
- }
-}
-
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
deleted file mode 100644
index 42c0044..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * The value of bpf interface index map which is used for NetworkStatsService.
- */
-public class InterfaceMapValue extends Struct {
- @Field(order = 0, type = Type.ByteArray, arraysize = 16)
- public final byte[] interfaceName;
-
- public InterfaceMapValue(String iface) {
- final byte[] ifaceArray = iface.getBytes();
- interfaceName = new byte[16];
- // All array bytes after the interface name, if any, must be 0.
- System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length);
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java b/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java
deleted file mode 100644
index 3a9a544..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.server.net;
-
-import android.net.InetAddresses;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.ProxyInfo;
-import android.net.StaticIpConfiguration;
-import android.net.Uri;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.ProxyUtils;
-
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-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;
-
- protected final DelayedDiskWrite mWriter;
-
- /* IP and proxy configuration keys */
- protected static final String ID_KEY = "id";
- protected static final String IP_ASSIGNMENT_KEY = "ipAssignment";
- protected static final String LINK_ADDRESS_KEY = "linkAddress";
- protected static final String GATEWAY_KEY = "gateway";
- protected static final String DNS_KEY = "dns";
- protected static final String PROXY_SETTINGS_KEY = "proxySettings";
- protected static final String PROXY_HOST_KEY = "proxyHost";
- protected static final String PROXY_PORT_KEY = "proxyPort";
- protected static final String PROXY_PAC_FILE = "proxyPac";
- protected static final String EXCLUSION_LIST_KEY = "exclusionList";
- protected static final String EOS = "eos";
-
- protected static final int IPCONFIG_FILE_VERSION = 3;
-
- public IpConfigStore(DelayedDiskWrite writer) {
- mWriter = writer;
- }
-
- public IpConfigStore() {
- this(new DelayedDiskWrite());
- }
-
- private static boolean writeConfig(DataOutputStream out, String configKey,
- IpConfiguration config) throws IOException {
- 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 {
- boolean written = false;
-
- try {
- switch (config.getIpAssignment()) {
- case STATIC:
- out.writeUTF(IP_ASSIGNMENT_KEY);
- out.writeUTF(config.getIpAssignment().toString());
- StaticIpConfiguration staticIpConfiguration = config.getStaticIpConfiguration();
- if (staticIpConfiguration != null) {
- if (staticIpConfiguration.getIpAddress() != null) {
- LinkAddress ipAddress = staticIpConfiguration.getIpAddress();
- out.writeUTF(LINK_ADDRESS_KEY);
- out.writeUTF(ipAddress.getAddress().getHostAddress());
- out.writeInt(ipAddress.getPrefixLength());
- }
- if (staticIpConfiguration.getGateway() != null) {
- out.writeUTF(GATEWAY_KEY);
- out.writeInt(0); // Default route.
- out.writeInt(1); // Have a gateway.
- out.writeUTF(staticIpConfiguration.getGateway().getHostAddress());
- }
- for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) {
- out.writeUTF(DNS_KEY);
- out.writeUTF(inetAddr.getHostAddress());
- }
- }
- written = true;
- break;
- case DHCP:
- out.writeUTF(IP_ASSIGNMENT_KEY);
- out.writeUTF(config.getIpAssignment().toString());
- written = true;
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid ip assignment while writing");
- break;
- }
-
- switch (config.getProxySettings()) {
- case STATIC:
- ProxyInfo proxyProperties = config.getHttpProxy();
- String exclusionList = ProxyUtils.exclusionListAsString(
- proxyProperties.getExclusionList());
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.getProxySettings().toString());
- out.writeUTF(PROXY_HOST_KEY);
- out.writeUTF(proxyProperties.getHost());
- out.writeUTF(PROXY_PORT_KEY);
- out.writeInt(proxyProperties.getPort());
- if (exclusionList != null) {
- out.writeUTF(EXCLUSION_LIST_KEY);
- out.writeUTF(exclusionList);
- }
- written = true;
- break;
- case PAC:
- ProxyInfo proxyPacProperties = config.getHttpProxy();
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.getProxySettings().toString());
- out.writeUTF(PROXY_PAC_FILE);
- out.writeUTF(proxyPacProperties.getPacFileUrl().toString());
- written = true;
- break;
- case NONE:
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.getProxySettings().toString());
- written = true;
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid proxy settings while writing");
- break;
- }
-
- if (written) {
- out.writeUTF(ID_KEY);
- if (version < 3) {
- out.writeInt(Integer.valueOf(configKey));
- } else {
- out.writeUTF(configKey);
- }
- }
- } catch (NullPointerException e) {
- loge("Failure in writing " + config + e);
- }
- out.writeUTF(EOS);
-
- return written;
- }
-
- /**
- * @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.
- */
- @Deprecated
- public void writeIpAndProxyConfigurationsToFile(String filePath,
- final SparseArray<IpConfiguration> networks) {
- mWriter.write(filePath, out -> {
- out.writeInt(IPCONFIG_FILE_VERSION);
- 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++) {
- 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 {
- bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
- } catch (FileNotFoundException e) {
- // Return an empty array here because callers expect an empty array when the file is
- // not present.
- loge("Error opening configuration file: " + e);
- return new ArrayMap<>(0);
- }
- return readIpConfigurations(bufferedInputStream);
- }
-
- /** @deprecated use {@link #readIpConfigurations(String)} */
- @Deprecated
- public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
- BufferedInputStream bufferedInputStream;
- try {
- bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
- } catch (FileNotFoundException e) {
- // Return an empty array here because callers expect an empty array when the file is
- // not present.
- loge("Error opening configuration file: " + e);
- return new SparseArray<>();
- }
- return readIpAndProxyConfigurations(bufferedInputStream);
- }
-
- /** @deprecated use {@link #readIpConfigurations(InputStream)} */
- @Deprecated
- public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(
- InputStream inputStream) {
- ArrayMap<String, IpConfiguration> networks = readIpConfigurations(inputStream);
- if (networks == null) {
- return null;
- }
-
- SparseArray<IpConfiguration> networksById = new SparseArray<>();
- for (int i = 0; i < networks.size(); i++) {
- int id = Integer.valueOf(networks.keyAt(i));
- networksById.put(id, networks.valueAt(i));
- }
-
- return networksById;
- }
-
- /** Returns a map of network identity token and {@link IpConfiguration}. */
- public static ArrayMap<String, IpConfiguration> readIpConfigurations(
- InputStream inputStream) {
- ArrayMap<String, IpConfiguration> networks = new ArrayMap<>();
- DataInputStream in = null;
- try {
- in = new DataInputStream(inputStream);
-
- int version = in.readInt();
- if (version != 3 && version != 2 && version != 1) {
- loge("Bad version on IP configuration file, ignore read");
- return null;
- }
-
- while (true) {
- String uniqueToken = null;
- // Default is DHCP with no proxy
- IpAssignment ipAssignment = IpAssignment.DHCP;
- ProxySettings proxySettings = ProxySettings.NONE;
- StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
- LinkAddress linkAddress = null;
- InetAddress gatewayAddress = null;
- String proxyHost = null;
- String pacFileUrl = null;
- int proxyPort = -1;
- String exclusionList = null;
- String key;
- final List<InetAddress> dnsServers = new ArrayList<>();
-
- do {
- key = in.readUTF();
- try {
- if (key.equals(ID_KEY)) {
- if (version < 3) {
- int id = in.readInt();
- uniqueToken = String.valueOf(id);
- } else {
- uniqueToken = in.readUTF();
- }
- } else if (key.equals(IP_ASSIGNMENT_KEY)) {
- ipAssignment = IpAssignment.valueOf(in.readUTF());
- } else if (key.equals(LINK_ADDRESS_KEY)) {
- LinkAddress parsedLinkAddress =
- new LinkAddress(
- InetAddresses.parseNumericAddress(in.readUTF()),
- in.readInt());
- if (parsedLinkAddress.getAddress() instanceof Inet4Address
- && linkAddress == null) {
- linkAddress = parsedLinkAddress;
- } else {
- loge("Non-IPv4 or duplicate address: " + parsedLinkAddress);
- }
- } else if (key.equals(GATEWAY_KEY)) {
- LinkAddress dest = null;
- InetAddress gateway = null;
- if (version == 1) {
- // only supported default gateways - leave the dest/prefix empty
- gateway = InetAddresses.parseNumericAddress(in.readUTF());
- if (gatewayAddress == null) {
- gatewayAddress = gateway;
- } else {
- loge("Duplicate gateway: " + gateway.getHostAddress());
- }
- } else {
- if (in.readInt() == 1) {
- dest =
- new LinkAddress(
- InetAddresses.parseNumericAddress(in.readUTF()),
- in.readInt());
- }
- if (in.readInt() == 1) {
- gateway = InetAddresses.parseNumericAddress(in.readUTF());
- }
- // If the destination is a default IPv4 route, use the gateway
- // 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 {
- loge("Non-IPv4 default or duplicate route: "
- + dest.getAddress());
- }
- }
- } else if (key.equals(DNS_KEY)) {
- dnsServers.add(InetAddresses.parseNumericAddress(in.readUTF()));
- } else if (key.equals(PROXY_SETTINGS_KEY)) {
- proxySettings = ProxySettings.valueOf(in.readUTF());
- } else if (key.equals(PROXY_HOST_KEY)) {
- proxyHost = in.readUTF();
- } else if (key.equals(PROXY_PORT_KEY)) {
- proxyPort = in.readInt();
- } else if (key.equals(PROXY_PAC_FILE)) {
- pacFileUrl = in.readUTF();
- } else if (key.equals(EXCLUSION_LIST_KEY)) {
- exclusionList = in.readUTF();
- } else if (key.equals(EOS)) {
- break;
- } else {
- loge("Ignore unknown key " + key + "while reading");
- }
- } catch (IllegalArgumentException e) {
- loge("Ignore invalid address while reading" + e);
- }
- } while (true);
-
- staticIpConfiguration = new StaticIpConfiguration.Builder()
- .setIpAddress(linkAddress)
- .setGateway(gatewayAddress)
- .setDnsServers(dnsServers)
- .build();
-
- if (uniqueToken != null) {
- IpConfiguration config = new IpConfiguration();
- networks.put(uniqueToken, config);
-
- switch (ipAssignment) {
- case STATIC:
- config.setStaticIpConfiguration(staticIpConfiguration);
- config.setIpAssignment(ipAssignment);
- break;
- case DHCP:
- config.setIpAssignment(ipAssignment);
- break;
- case UNASSIGNED:
- loge("BUG: Found UNASSIGNED IP on file, use DHCP");
- config.setIpAssignment(IpAssignment.DHCP);
- break;
- default:
- loge("Ignore invalid ip assignment while reading.");
- config.setIpAssignment(IpAssignment.UNASSIGNED);
- break;
- }
-
- switch (proxySettings) {
- case STATIC:
- ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy(proxyHost, proxyPort,
- ProxyUtils.exclusionStringAsList(exclusionList));
- config.setProxySettings(proxySettings);
- config.setHttpProxy(proxyInfo);
- break;
- case PAC:
- ProxyInfo proxyPacProperties =
- ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl));
- config.setProxySettings(proxySettings);
- config.setHttpProxy(proxyPacProperties);
- break;
- case NONE:
- config.setProxySettings(proxySettings);
- break;
- case UNASSIGNED:
- loge("BUG: Found UNASSIGNED proxy on file, use NONE");
- config.setProxySettings(ProxySettings.NONE);
- break;
- default:
- loge("Ignore invalid proxy settings while reading");
- config.setProxySettings(ProxySettings.UNASSIGNED);
- break;
- }
- } else {
- if (DBG) log("Missing id while parsing configuration");
- }
- }
- } catch (EOFException ignore) {
- } catch (IOException e) {
- loge("Error parsing configuration: " + e);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (Exception e) { }
- }
- }
-
- return networks;
- }
-
- protected static void loge(String s) {
- Log.e(TAG, s);
- }
-
- protected static void log(String s) {
- Log.d(TAG, s);
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
deleted file mode 100644
index 3b93f1a..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
+++ /dev/null
@@ -1,505 +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 com.android.server.net;
-
-import static android.net.NetworkStats.INTERFACES_ALL;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.TAG_ALL;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.net.NetworkStats;
-import android.net.UnderlyingNetworkInfo;
-import android.os.ServiceSpecificException;
-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.ProcFileReader;
-import com.android.net.module.util.CollectionUtils;
-import com.android.server.BpfNetMaps;
-
-import libcore.io.IoUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.ProtocolException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Creates {@link NetworkStats} instances by parsing various {@code /proc/}
- * files as needed.
- *
- * @hide
- */
-public class NetworkStatsFactory {
- static {
- System.loadLibrary("service-connectivity");
- }
-
- private static final String TAG = "NetworkStatsFactory";
-
- private static final boolean USE_NATIVE_PARSING = true;
- private static final boolean VALIDATE_NATIVE_STATS = false;
-
- /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
- private final File mStatsXtIfaceAll;
- /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
- private final File mStatsXtIfaceFmt;
- /** Path to {@code /proc/net/xt_qtaguid/stats}. */
- private final File mStatsXtUid;
-
- private final boolean mUseBpfStats;
-
- private final Context mContext;
-
- private final BpfNetMaps mBpfNetMaps;
-
- /**
- * Guards persistent data access in this class
- *
- * <p>In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out
- * to other code that will acquire other locks within the system server. See b/134244752.
- */
- private final Object mPersistentDataLock = new Object();
-
- /** Set containing info about active VPNs and their underlying networks. */
- private volatile UnderlyingNetworkInfo[] mUnderlyingNetworkInfos = new UnderlyingNetworkInfo[0];
-
- // A persistent snapshot of cumulative stats since device start
- @GuardedBy("mPersistentDataLock")
- private NetworkStats mPersistSnapshot;
-
- // The persistent snapshot of tun and 464xlat adjusted stats since device start
- @GuardedBy("mPersistentDataLock")
- private NetworkStats mTunAnd464xlatAdjustedStats;
-
- /**
- * (Stacked interface) -> (base interface) association for all connected ifaces since boot.
- *
- * Because counters must never roll backwards, once a given interface is stacked on top of an
- * underlying interface, the stacked interface can never be stacked on top of
- * another interface. */
- private final ConcurrentHashMap<String, String> mStackedIfaces
- = new ConcurrentHashMap<>();
-
- /** Informs the factory of a new stacked interface. */
- public void noteStackedIface(String stackedIface, String baseIface) {
- if (stackedIface != null && baseIface != null) {
- mStackedIfaces.put(stackedIface, baseIface);
- }
- }
-
- /**
- * Set active VPN information for data usage migration purposes
- *
- * <p>Traffic on TUN-based VPNs inherently all appear to be originated from the VPN providing
- * app's UID. This method is used to support migration of VPN data usage, ensuring data is
- * accurately billed to the real owner of the traffic.
- *
- * @param vpnArray The snapshot of the currently-running VPNs.
- */
- public void updateUnderlyingNetworkInfos(UnderlyingNetworkInfo[] vpnArray) {
- mUnderlyingNetworkInfos = vpnArray.clone();
- }
-
- /**
- * Get a set of interfaces containing specified ifaces and stacked interfaces.
- *
- * <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
- * on which the specified ones are stacked. Stacked interfaces are those noted with
- * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method
- * is called are guaranteed to be included.
- */
- public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) {
- if (requiredIfaces == NetworkStats.INTERFACES_ALL) {
- return null;
- }
-
- HashSet<String> relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces));
- // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse
- // elements as they existed upon construction exactly once, and may
- // (but are not guaranteed to) reflect any modifications subsequent to construction".
- // This is enough here.
- for (Map.Entry<String, String> entry : mStackedIfaces.entrySet()) {
- if (relatedIfaces.contains(entry.getKey())) {
- relatedIfaces.add(entry.getValue());
- } else if (relatedIfaces.contains(entry.getValue())) {
- relatedIfaces.add(entry.getKey());
- }
- }
-
- String[] outArray = new String[relatedIfaces.size()];
- return relatedIfaces.toArray(outArray);
- }
-
- /**
- * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
- * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
- */
- public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic) {
- NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
- }
-
- public NetworkStatsFactory(@NonNull Context ctx) {
- this(ctx, new File("/proc/"), true);
- }
-
- @VisibleForTesting
- public NetworkStatsFactory(@NonNull Context ctx, File procRoot, boolean useBpfStats) {
- 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");
- mUseBpfStats = useBpfStats;
- mBpfNetMaps = new BpfNetMaps();
- synchronized (mPersistentDataLock) {
- mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
- mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
- }
- mContext = ctx;
- }
-
- public NetworkStats readBpfNetworkStatsDev() throws IOException {
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
- if (nativeReadNetworkStatsDev(stats) != 0) {
- throw new IOException("Failed to parse bpf iface stats");
- }
- return stats;
- }
-
- /**
- * Parse and return interface-level summary {@link NetworkStats} measured
- * using {@code /proc/net/dev} style hooks, which may include non IP layer
- * traffic. Values monotonically increase since device boot, and may include
- * details about inactive interfaces.
- *
- * @throws IllegalStateException when problem parsing stats.
- */
- public NetworkStats readNetworkStatsSummaryDev() throws IOException {
-
- // Return xt_bpf stats if switched to bpf module.
- if (mUseBpfStats)
- return readBpfNetworkStatsDev();
-
- final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
-
- ProcFileReader reader = null;
- try {
- reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceAll));
-
- while (reader.hasMoreData()) {
- entry.iface = reader.nextString();
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
-
- final boolean active = reader.nextInt() != 0;
-
- // always include snapshot values
- entry.rxBytes = reader.nextLong();
- entry.rxPackets = reader.nextLong();
- entry.txBytes = reader.nextLong();
- entry.txPackets = reader.nextLong();
-
- // fold in active numbers, but only when active
- if (active) {
- entry.rxBytes += reader.nextLong();
- entry.rxPackets += reader.nextLong();
- entry.txBytes += reader.nextLong();
- entry.txPackets += reader.nextLong();
- }
-
- stats.insertEntry(entry);
- reader.finishLine();
- }
- } catch (NullPointerException|NumberFormatException e) {
- throw protocolExceptionWithCause("problem parsing stats", e);
- } finally {
- IoUtils.closeQuietly(reader);
- StrictMode.setThreadPolicy(savedPolicy);
- }
- return stats;
- }
-
- /**
- * Parse and return interface-level summary {@link NetworkStats}. Designed
- * to return only IP layer traffic. Values monotonically increase since
- * device boot, and may include details about inactive interfaces.
- *
- * @throws IllegalStateException when problem parsing stats.
- */
- public NetworkStats readNetworkStatsSummaryXt() throws IOException {
-
- // Return xt_bpf stats if qtaguid module is replaced.
- if (mUseBpfStats)
- return readBpfNetworkStatsDev();
-
- final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
- // return null when kernel doesn't support
- if (!mStatsXtIfaceFmt.exists()) return null;
-
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
-
- ProcFileReader reader = null;
- try {
- // open and consume header line
- reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceFmt));
- reader.finishLine();
-
- while (reader.hasMoreData()) {
- entry.iface = reader.nextString();
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
-
- entry.rxBytes = reader.nextLong();
- entry.rxPackets = reader.nextLong();
- entry.txBytes = reader.nextLong();
- entry.txPackets = reader.nextLong();
-
- stats.insertEntry(entry);
- reader.finishLine();
- }
- } catch (NullPointerException|NumberFormatException e) {
- throw protocolExceptionWithCause("problem parsing stats", e);
- } finally {
- IoUtils.closeQuietly(reader);
- StrictMode.setThreadPolicy(savedPolicy);
- }
- return stats;
- }
-
- public NetworkStats readNetworkStatsDetail() throws IOException {
- return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL);
- }
-
- @GuardedBy("mPersistentDataLock")
- private void requestSwapActiveStatsMapLocked() throws IOException {
- try {
- // Do a active map stats swap. Once the swap completes, this code
- // can read and clean the inactive map without races.
- mBpfNetMaps.swapActiveStatsMap();
- } catch (ServiceSpecificException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Reads the detailed UID stats based on the provided parameters
- *
- * @param limitUid the UID to limit this query to
- * @param limitIfaces the interfaces to limit this query to. Use {@link
- * NetworkStats.INTERFACES_ALL} to select all interfaces
- * @param limitTag the tags to limit this query to
- * @return the NetworkStats instance containing network statistics at the present time.
- */
- public NetworkStats readNetworkStatsDetail(
- int limitUid, String[] limitIfaces, int limitTag) throws IOException {
- // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other
- // code that will acquire other locks within the system server. See b/134244752.
- synchronized (mPersistentDataLock) {
- // Take a reference. If this gets swapped out, we still have the old reference.
- final UnderlyingNetworkInfo[] vpnArray = mUnderlyingNetworkInfos;
- // Take a defensive copy. mPersistSnapshot is mutated in some cases below
- final NetworkStats prev = mPersistSnapshot.clone();
-
- if (USE_NATIVE_PARSING) {
- final NetworkStats stats =
- new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */);
- if (mUseBpfStats) {
- requestSwapActiveStatsMapLocked();
- // Stats are always read from the inactive map, so they must be read after the
- // swap
- if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
- INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
- throw new IOException("Failed to parse network stats");
- }
-
- // BPF stats are incremental; fold into mPersistSnapshot.
- mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
- mPersistSnapshot.combineAllValues(stats);
- } else {
- if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
- INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
- throw new IOException("Failed to parse network stats");
- }
- if (VALIDATE_NATIVE_STATS) {
- final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid,
- UID_ALL, INTERFACES_ALL, TAG_ALL);
- assertEquals(javaStats, stats);
- }
-
- mPersistSnapshot = stats;
- }
- } else {
- mPersistSnapshot = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL,
- TAG_ALL);
- }
-
- NetworkStats adjustedStats = adjustForTunAnd464Xlat(mPersistSnapshot, prev, vpnArray);
-
- // Filter return values
- adjustedStats.filter(limitUid, limitIfaces, limitTag);
- return adjustedStats;
- }
- }
-
- @GuardedBy("mPersistentDataLock")
- private NetworkStats adjustForTunAnd464Xlat(NetworkStats uidDetailStats,
- NetworkStats previousStats, UnderlyingNetworkInfo[] vpnArray) {
- // Calculate delta from last snapshot
- final NetworkStats delta = uidDetailStats.subtract(previousStats);
-
- // Apply 464xlat adjustments before VPN adjustments. If VPNs are using v4 on a v6 only
- // network, the overhead is their fault.
- // No locking here: apply464xlatAdjustments behaves fine with an add-only
- // ConcurrentHashMap.
- delta.apply464xlatAdjustments(mStackedIfaces);
-
- // Migrate data usage over a VPN to the TUN network.
- for (UnderlyingNetworkInfo info : vpnArray) {
- delta.migrateTun(info.getOwnerUid(), info.getInterface(),
- info.getUnderlyingInterfaces());
- // Filter out debug entries as that may lead to over counting.
- delta.filterDebugEntries();
- }
-
- // Update mTunAnd464xlatAdjustedStats with migrated delta.
- mTunAnd464xlatAdjustedStats.combineAllValues(delta);
- mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime());
-
- return mTunAnd464xlatAdjustedStats.clone();
- }
-
- /**
- * Parse and return {@link NetworkStats} with UID-level details. Values are
- * expected to monotonically increase since device boot.
- */
- @VisibleForTesting
- public static NetworkStats javaReadNetworkStatsDetail(File detailPath, int limitUid,
- String[] limitIfaces, int limitTag)
- throws IOException {
- final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
-
- int idx = 1;
- int lastIdx = 1;
-
- ProcFileReader reader = null;
- try {
- // open and consume header line
- reader = new ProcFileReader(new FileInputStream(detailPath));
- reader.finishLine();
-
- while (reader.hasMoreData()) {
- idx = reader.nextInt();
- if (idx != lastIdx + 1) {
- throw new ProtocolException(
- "inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
- }
- lastIdx = idx;
-
- entry.iface = reader.nextString();
- entry.tag = kernelToTag(reader.nextString());
- entry.uid = reader.nextInt();
- entry.set = reader.nextInt();
- entry.rxBytes = reader.nextLong();
- entry.rxPackets = reader.nextLong();
- entry.txBytes = reader.nextLong();
- entry.txPackets = reader.nextLong();
-
- if ((limitIfaces == null || CollectionUtils.contains(limitIfaces, entry.iface))
- && (limitUid == UID_ALL || limitUid == entry.uid)
- && (limitTag == TAG_ALL || limitTag == entry.tag)) {
- stats.insertEntry(entry);
- }
-
- reader.finishLine();
- }
- } catch (NullPointerException|NumberFormatException e) {
- throw protocolExceptionWithCause("problem parsing idx " + idx, e);
- } finally {
- IoUtils.closeQuietly(reader);
- StrictMode.setThreadPolicy(savedPolicy);
- }
-
- return stats;
- }
-
- public void assertEquals(NetworkStats expected, NetworkStats actual) {
- if (expected.size() != actual.size()) {
- throw new AssertionError(
- "Expected size " + expected.size() + ", actual size " + actual.size());
- }
-
- NetworkStats.Entry expectedRow = null;
- NetworkStats.Entry actualRow = null;
- for (int i = 0; i < expected.size(); i++) {
- expectedRow = expected.getValues(i, expectedRow);
- actualRow = actual.getValues(i, actualRow);
- if (!expectedRow.equals(actualRow)) {
- throw new AssertionError(
- "Expected row " + i + ": " + expectedRow + ", actual row " + actualRow);
- }
- }
- }
-
- /**
- * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
- * format like {@code 0x7fffffff00000000}.
- */
- public static int kernelToTag(String string) {
- int length = string.length();
- if (length > 10) {
- return Long.decode(string.substring(0, length - 8)).intValue();
- } else {
- return 0;
- }
- }
-
- /**
- * Parse statistics from file into given {@link NetworkStats} object. Values
- * are expected to monotonically increase since device boot.
- */
- @VisibleForTesting
- public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
- int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
-
- @VisibleForTesting
- public static native int nativeReadNetworkStatsDev(NetworkStats stats);
-
- private static ProtocolException protocolExceptionWithCause(String message, Throwable cause) {
- ProtocolException pe = new ProtocolException(message);
- pe.initCause(cause);
- return pe;
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
deleted file mode 100644
index fdfc893..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) 2016 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 com.android.server.net;
-
-import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
-
-import android.app.usage.NetworkStatsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.DataUsageRequest;
-import android.net.NetworkIdentitySet;
-import android.net.NetworkStack;
-import android.net.NetworkStats;
-import android.net.NetworkStatsAccess;
-import android.net.NetworkStatsCollection;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.netstats.IUsageCallback;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Manages observers of {@link NetworkStats}. Allows observers to be notified when
- * data usage has been reported in {@link NetworkStatsService}. An observer can set
- * a threshold of how much data it cares about to be notified.
- */
-class NetworkStatsObservers {
- private static final String TAG = "NetworkStatsObservers";
- private static final boolean LOGV = false;
-
- private static final int MSG_REGISTER = 1;
- private static final int MSG_UNREGISTER = 2;
- private static final int MSG_UPDATE_STATS = 3;
-
- // All access to this map must be done from the handler thread.
- // indexed by DataUsageRequest#requestId
- private final SparseArray<RequestInfo> mDataUsageRequests = new SparseArray<>();
-
- // Sequence number of DataUsageRequests
- private final AtomicInteger mNextDataUsageRequestId = new AtomicInteger();
-
- // Lazily instantiated when an observer is registered.
- private volatile Handler mHandler;
-
- /**
- * Creates a wrapper that contains the caller context and a normalized request.
- * The request should be returned to the caller app, and the wrapper should be sent to this
- * object through #addObserver by the service handler.
- *
- * <p>It will register the observer asynchronously, so it is safe to call from any thread.
- *
- * @return the normalized request wrapped within {@link RequestInfo}.
- */
- public DataUsageRequest register(Context context, DataUsageRequest inputRequest,
- IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
- DataUsageRequest request = buildRequest(context, inputRequest, callingUid);
- RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
- accessLevel);
-
- if (LOGV) Log.v(TAG, "Registering observer for " + request);
- getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
- return request;
- }
-
- /**
- * Unregister a data usage observer.
- *
- * <p>It will unregister the observer asynchronously, so it is safe to call from any thread.
- */
- public void unregister(DataUsageRequest request, int callingUid) {
- getHandler().sendMessage(mHandler.obtainMessage(MSG_UNREGISTER, callingUid, 0 /* ignore */,
- request));
- }
-
- /**
- * Updates data usage statistics of registered observers and notifies if limits are reached.
- *
- * <p>It will update stats asynchronously, so it is safe to call from any thread.
- */
- public void updateStats(NetworkStats xtSnapshot, NetworkStats uidSnapshot,
- ArrayMap<String, NetworkIdentitySet> activeIfaces,
- ArrayMap<String, NetworkIdentitySet> activeUidIfaces,
- long currentTime) {
- StatsContext statsContext = new StatsContext(xtSnapshot, uidSnapshot, activeIfaces,
- activeUidIfaces, currentTime);
- getHandler().sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext));
- }
-
- private Handler getHandler() {
- if (mHandler == null) {
- synchronized (this) {
- if (mHandler == null) {
- if (LOGV) Log.v(TAG, "Creating handler");
- mHandler = new Handler(getHandlerLooperLocked(), mHandlerCallback);
- }
- }
- }
- return mHandler;
- }
-
- @VisibleForTesting
- protected Looper getHandlerLooperLocked() {
- HandlerThread handlerThread = new HandlerThread(TAG);
- handlerThread.start();
- return handlerThread.getLooper();
- }
-
- private Handler.Callback mHandlerCallback = new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REGISTER: {
- handleRegister((RequestInfo) msg.obj);
- return true;
- }
- case MSG_UNREGISTER: {
- handleUnregister((DataUsageRequest) msg.obj, msg.arg1 /* callingUid */);
- return true;
- }
- case MSG_UPDATE_STATS: {
- handleUpdateStats((StatsContext) msg.obj);
- return true;
- }
- default: {
- return false;
- }
- }
- }
- };
-
- /**
- * Adds a {@link RequestInfo} as an observer.
- * Should only be called from the handler thread otherwise there will be a race condition
- * on mDataUsageRequests.
- */
- private void handleRegister(RequestInfo requestInfo) {
- mDataUsageRequests.put(requestInfo.mRequest.requestId, requestInfo);
- }
-
- /**
- * Removes a {@link DataUsageRequest} if the calling uid is authorized.
- * Should only be called from the handler thread otherwise there will be a race condition
- * on mDataUsageRequests.
- */
- private void handleUnregister(DataUsageRequest request, int callingUid) {
- RequestInfo requestInfo;
- requestInfo = mDataUsageRequests.get(request.requestId);
- if (requestInfo == null) {
- if (LOGV) Log.v(TAG, "Trying to unregister unknown request " + request);
- return;
- }
- if (Process.SYSTEM_UID != callingUid && requestInfo.mCallingUid != callingUid) {
- Log.w(TAG, "Caller uid " + callingUid + " is not owner of " + request);
- return;
- }
-
- if (LOGV) Log.v(TAG, "Unregistering " + request);
- mDataUsageRequests.remove(request.requestId);
- requestInfo.unlinkDeathRecipient();
- requestInfo.callCallback(NetworkStatsManager.CALLBACK_RELEASED);
- }
-
- private void handleUpdateStats(StatsContext statsContext) {
- if (mDataUsageRequests.size() == 0) {
- return;
- }
-
- for (int i = 0; i < mDataUsageRequests.size(); i++) {
- RequestInfo requestInfo = mDataUsageRequests.valueAt(i);
- requestInfo.updateStats(statsContext);
- }
- }
-
- private DataUsageRequest buildRequest(Context context, DataUsageRequest request,
- int callingUid) {
- // For non-NETWORK_STACK permission uid, cap the minimum threshold to a safe default to
- // avoid too many callbacks.
- final long thresholdInBytes = (context.checkPermission(
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, Process.myPid(), callingUid)
- == PackageManager.PERMISSION_GRANTED ? request.thresholdInBytes
- : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
- if (thresholdInBytes > request.thresholdInBytes) {
- Log.w(TAG, "Threshold was too low for " + request
- + ". Overriding to a safer default of " + thresholdInBytes + " bytes");
- }
- return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(),
- request.template, thresholdInBytes);
- }
-
- private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback,
- int callingUid, @NetworkStatsAccess.Level int accessLevel) {
- if (accessLevel <= NetworkStatsAccess.Level.USER) {
- return new UserUsageRequestInfo(this, request, callback, callingUid,
- accessLevel);
- } else {
- // Safety check in case a new access level is added and we forgot to update this
- if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
- throw new IllegalArgumentException(
- "accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
- }
- return new NetworkUsageRequestInfo(this, request, callback, callingUid,
- accessLevel);
- }
- }
-
- /**
- * Tracks information relevant to a data usage observer.
- * It will notice when the calling process dies so we can self-expire.
- */
- private abstract static class RequestInfo implements IBinder.DeathRecipient {
- private final NetworkStatsObservers mStatsObserver;
- protected final DataUsageRequest mRequest;
- private final IUsageCallback mCallback;
- protected final int mCallingUid;
- protected final @NetworkStatsAccess.Level int mAccessLevel;
- protected NetworkStatsRecorder mRecorder;
- protected NetworkStatsCollection mCollection;
-
- RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
- IUsageCallback callback, int callingUid,
- @NetworkStatsAccess.Level int accessLevel) {
- mStatsObserver = statsObserver;
- mRequest = request;
- mCallback = callback;
- mCallingUid = callingUid;
- mAccessLevel = accessLevel;
-
- try {
- mCallback.asBinder().linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
- }
-
- @Override
- public void binderDied() {
- if (LOGV) {
- Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")");
- }
- mStatsObserver.unregister(mRequest, Process.SYSTEM_UID);
- callCallback(NetworkStatsManager.CALLBACK_RELEASED);
- }
-
- @Override
- public String toString() {
- return "RequestInfo from uid:" + mCallingUid
- + " for " + mRequest + " accessLevel:" + mAccessLevel;
- }
-
- private void unlinkDeathRecipient() {
- mCallback.asBinder().unlinkToDeath(this, 0);
- }
-
- /**
- * Update stats given the samples and interface to identity mappings.
- */
- private void updateStats(StatsContext statsContext) {
- if (mRecorder == null) {
- // First run; establish baseline stats
- resetRecorder();
- recordSample(statsContext);
- return;
- }
- recordSample(statsContext);
-
- if (checkStats()) {
- resetRecorder();
- callCallback(NetworkStatsManager.CALLBACK_LIMIT_REACHED);
- }
- }
-
- private void callCallback(int callbackType) {
- try {
- if (LOGV) {
- Log.v(TAG, "sending notification " + callbackTypeToName(callbackType)
- + " for " + mRequest);
- }
- switch (callbackType) {
- case NetworkStatsManager.CALLBACK_LIMIT_REACHED:
- mCallback.onThresholdReached(mRequest);
- break;
- case NetworkStatsManager.CALLBACK_RELEASED:
- mCallback.onCallbackReleased(mRequest);
- break;
- }
- } catch (RemoteException e) {
- // May occur naturally in the race of binder death.
- Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
- }
- }
-
- private void resetRecorder() {
- mRecorder = new NetworkStatsRecorder();
- mCollection = mRecorder.getSinceBoot();
- }
-
- protected abstract boolean checkStats();
-
- protected abstract void recordSample(StatsContext statsContext);
-
- private String callbackTypeToName(int callbackType) {
- switch (callbackType) {
- case NetworkStatsManager.CALLBACK_LIMIT_REACHED:
- return "LIMIT_REACHED";
- case NetworkStatsManager.CALLBACK_RELEASED:
- return "RELEASED";
- default:
- return "UNKNOWN";
- }
- }
- }
-
- private static class NetworkUsageRequestInfo extends RequestInfo {
- NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
- IUsageCallback callback, int callingUid,
- @NetworkStatsAccess.Level int accessLevel) {
- super(statsObserver, request, callback, callingUid, accessLevel);
- }
-
- @Override
- protected boolean checkStats() {
- long bytesSoFar = getTotalBytesForNetwork(mRequest.template);
- if (LOGV) {
- Log.v(TAG, bytesSoFar + " bytes so far since notification for "
- + mRequest.template);
- }
- if (bytesSoFar > mRequest.thresholdInBytes) {
- return true;
- }
- return false;
- }
-
- @Override
- protected void recordSample(StatsContext statsContext) {
- // Recorder does not need to be locked in this context since only the handler
- // thread will update it. We pass a null VPN array because usage is aggregated by uid
- // for this snapshot, so VPN traffic can't be reattributed to responsible apps.
- mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces,
- statsContext.mCurrentTime);
- }
-
- /**
- * Reads stats matching the given template. {@link NetworkStatsCollection} will aggregate
- * over all buckets, which in this case should be only one since we built it big enough
- * that it will outlive the caller. If it doesn't, then there will be multiple buckets.
- */
- private long getTotalBytesForNetwork(NetworkTemplate template) {
- NetworkStats stats = mCollection.getSummary(template,
- Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */,
- mAccessLevel, mCallingUid);
- return stats.getTotalBytes();
- }
- }
-
- private static class UserUsageRequestInfo extends RequestInfo {
- UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
- IUsageCallback callback, int callingUid,
- @NetworkStatsAccess.Level int accessLevel) {
- super(statsObserver, request, callback, callingUid, accessLevel);
- }
-
- @Override
- protected boolean checkStats() {
- int[] uidsToMonitor = mCollection.getRelevantUids(mAccessLevel, mCallingUid);
-
- for (int i = 0; i < uidsToMonitor.length; i++) {
- long bytesSoFar = getTotalBytesForNetworkUid(mRequest.template, uidsToMonitor[i]);
- if (bytesSoFar > mRequest.thresholdInBytes) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- protected void recordSample(StatsContext statsContext) {
- // Recorder does not need to be locked in this context since only the handler
- // thread will update it. We pass the VPN info so VPN traffic is reattributed to
- // responsible apps.
- mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces,
- statsContext.mCurrentTime);
- }
-
- /**
- * Reads all stats matching the given template and uid. Ther history will likely only
- * contain one bucket per ident since we build it big enough that it will outlive the
- * caller lifetime.
- */
- private long getTotalBytesForNetworkUid(NetworkTemplate template, int uid) {
- try {
- NetworkStatsHistory history = mCollection.getHistory(template, null, uid,
- NetworkStats.SET_ALL, NetworkStats.TAG_NONE,
- NetworkStatsHistory.FIELD_ALL,
- Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */,
- mAccessLevel, mCallingUid);
- return history.getTotalBytes();
- } catch (SecurityException e) {
- if (LOGV) {
- Log.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid "
- + uid);
- }
- return 0;
- }
- }
- }
-
- private static class StatsContext {
- NetworkStats mXtSnapshot;
- NetworkStats mUidSnapshot;
- ArrayMap<String, NetworkIdentitySet> mActiveIfaces;
- ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces;
- long mCurrentTime;
-
- StatsContext(NetworkStats xtSnapshot, NetworkStats uidSnapshot,
- ArrayMap<String, NetworkIdentitySet> activeIfaces,
- ArrayMap<String, NetworkIdentitySet> activeUidIfaces,
- long currentTime) {
- mXtSnapshot = xtSnapshot;
- mUidSnapshot = uidSnapshot;
- mActiveIfaces = activeIfaces;
- mActiveUidIfaces = activeUidIfaces;
- mCurrentTime = currentTime;
- }
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
deleted file mode 100644
index a006cd5..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.server.net;
-
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.TrafficStats.KB_IN_BYTES;
-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.proto.ProtoOutputStream;
-
-import com.android.internal.util.FileRotator;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import libcore.io.IoUtils;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Logic to record deltas between periodic {@link NetworkStats} snapshots into
- * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}.
- * Keeps pending changes in memory until they pass a specific threshold, in
- * bytes. Uses {@link FileRotator} for persistence logic if present.
- * <p>
- * Not inherently thread safe.
- */
-public class NetworkStatsRecorder {
- private static final String TAG = "NetworkStatsRecorder";
- private static final boolean LOGD = false;
- private static final boolean LOGV = false;
-
- private static final String TAG_NETSTATS_DUMP = "netstats_dump";
-
- /** Dump before deleting in {@link #recoverFromWtf()}. */
- private static final boolean DUMP_BEFORE_DELETE = true;
-
- private final FileRotator mRotator;
- private final NonMonotonicObserver<String> mObserver;
- private final DropBoxManager mDropBox;
- private final String mCookie;
-
- private final long mBucketDuration;
- private final boolean mOnlyTags;
-
- private long mPersistThresholdBytes = 2 * MB_IN_BYTES;
- private NetworkStats mLastSnapshot;
-
- private final NetworkStatsCollection mPending;
- private final NetworkStatsCollection mSinceBoot;
-
- private final CombiningRewriter mPendingRewriter;
-
- private WeakReference<NetworkStatsCollection> mComplete;
-
- /**
- * Non-persisted recorder, with only one bucket. Used by {@link NetworkStatsObservers}.
- */
- public NetworkStatsRecorder() {
- mRotator = null;
- mObserver = null;
- mDropBox = null;
- mCookie = null;
-
- // set the bucket big enough to have all data in one bucket, but allow some
- // slack to avoid overflow
- mBucketDuration = YEAR_IN_MILLIS;
- mOnlyTags = false;
-
- mPending = null;
- mSinceBoot = new NetworkStatsCollection(mBucketDuration);
-
- mPendingRewriter = null;
- }
-
- /**
- * Persisted recorder.
- */
- public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
- DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) {
- mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
- mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
- mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
- mCookie = cookie;
-
- mBucketDuration = bucketDuration;
- mOnlyTags = onlyTags;
-
- mPending = new NetworkStatsCollection(bucketDuration);
- mSinceBoot = new NetworkStatsCollection(bucketDuration);
-
- mPendingRewriter = new CombiningRewriter(mPending);
- }
-
- public void setPersistThreshold(long thresholdBytes) {
- if (LOGV) Log.v(TAG, "setPersistThreshold() with " + thresholdBytes);
- mPersistThresholdBytes = NetworkStatsUtils.constrain(
- thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES);
- }
-
- public void resetLocked() {
- mLastSnapshot = null;
- if (mPending != null) {
- mPending.reset();
- }
- if (mSinceBoot != null) {
- mSinceBoot.reset();
- }
- if (mComplete != null) {
- mComplete.clear();
- }
- }
-
- public NetworkStats.Entry getTotalSinceBootLocked(NetworkTemplate template) {
- return mSinceBoot.getSummary(template, Long.MIN_VALUE, Long.MAX_VALUE,
- NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotal(null);
- }
-
- public NetworkStatsCollection getSinceBoot() {
- return mSinceBoot;
- }
-
- /**
- * Load complete history represented by {@link FileRotator}. Caches
- * internally as a {@link WeakReference}, and updated with future
- * {@link #recordSnapshotLocked(NetworkStats, Map, long)} snapshots as long
- * as reference is valid.
- */
- public NetworkStatsCollection getOrLoadCompleteLocked() {
- Objects.requireNonNull(mRotator, "missing FileRotator");
- NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
- if (res == null) {
- res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
- mComplete = new WeakReference<NetworkStatsCollection>(res);
- }
- return res;
- }
-
- public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) {
- Objects.requireNonNull(mRotator, "missing FileRotator");
- NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
- if (res == null) {
- res = loadLocked(start, end);
- }
- return res;
- }
-
- private NetworkStatsCollection loadLocked(long start, long end) {
- if (LOGD) Log.d(TAG, "loadLocked() reading from disk for " + mCookie);
- final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration);
- try {
- mRotator.readMatching(res, start, end);
- res.recordCollection(mPending);
- } catch (IOException e) {
- Log.wtf(TAG, "problem completely reading network stats", e);
- recoverFromWtf();
- } catch (OutOfMemoryError e) {
- Log.wtf(TAG, "problem completely reading network stats", e);
- recoverFromWtf();
- }
- return res;
- }
-
- /**
- * Record any delta that occurred since last {@link NetworkStats} snapshot, using the given
- * {@link Map} to identify network interfaces. First snapshot is considered bootstrap, and is
- * not counted as delta.
- */
- public void recordSnapshotLocked(NetworkStats snapshot,
- Map<String, NetworkIdentitySet> ifaceIdent, long currentTimeMillis) {
- final HashSet<String> unknownIfaces = new HashSet<>();
-
- // skip recording when snapshot missing
- if (snapshot == null) return;
-
- // assume first snapshot is bootstrap and don't record
- if (mLastSnapshot == null) {
- mLastSnapshot = snapshot;
- return;
- }
-
- final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
-
- final NetworkStats delta = NetworkStats.subtract(
- snapshot, mLastSnapshot, mObserver, mCookie);
- final long end = currentTimeMillis;
- final long start = end - delta.getElapsedRealtime();
-
- NetworkStats.Entry entry = null;
- for (int i = 0; i < delta.size(); i++) {
- entry = delta.getValues(i, entry);
-
- // As a last-ditch check, report any negative values and
- // clamp them so recording below doesn't croak.
- if (entry.isNegative()) {
- if (mObserver != null) {
- mObserver.foundNonMonotonic(delta, i, mCookie);
- }
- entry.rxBytes = Math.max(entry.rxBytes, 0);
- entry.rxPackets = Math.max(entry.rxPackets, 0);
- entry.txBytes = Math.max(entry.txBytes, 0);
- entry.txPackets = Math.max(entry.txPackets, 0);
- entry.operations = Math.max(entry.operations, 0);
- }
-
- final NetworkIdentitySet ident = ifaceIdent.get(entry.iface);
- if (ident == null) {
- unknownIfaces.add(entry.iface);
- continue;
- }
-
- // skip when no delta occurred
- if (entry.isEmpty()) continue;
-
- // only record tag data when requested
- if ((entry.tag == TAG_NONE) != mOnlyTags) {
- if (mPending != null) {
- mPending.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry);
- }
-
- // also record against boot stats when present
- if (mSinceBoot != null) {
- mSinceBoot.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry);
- }
-
- // also record against complete dataset when present
- if (complete != null) {
- complete.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry);
- }
- }
- }
-
- mLastSnapshot = snapshot;
-
- if (LOGV && unknownIfaces.size() > 0) {
- Log.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats");
- }
- }
-
- /**
- * Consider persisting any pending deltas, if they are beyond
- * {@link #mPersistThresholdBytes}.
- */
- public void maybePersistLocked(long currentTimeMillis) {
- Objects.requireNonNull(mRotator, "missing FileRotator");
- final long pendingBytes = mPending.getTotalBytes();
- if (pendingBytes >= mPersistThresholdBytes) {
- forcePersistLocked(currentTimeMillis);
- } else {
- mRotator.maybeRotate(currentTimeMillis);
- }
- }
-
- /**
- * Force persisting any pending deltas.
- */
- public void forcePersistLocked(long currentTimeMillis) {
- Objects.requireNonNull(mRotator, "missing FileRotator");
- if (mPending.isDirty()) {
- if (LOGD) Log.d(TAG, "forcePersistLocked() writing for " + mCookie);
- try {
- mRotator.rewriteActive(mPendingRewriter, currentTimeMillis);
- mRotator.maybeRotate(currentTimeMillis);
- mPending.reset();
- } catch (IOException e) {
- Log.wtf(TAG, "problem persisting pending stats", e);
- recoverFromWtf();
- } catch (OutOfMemoryError e) {
- Log.wtf(TAG, "problem persisting pending stats", e);
- recoverFromWtf();
- }
- }
- }
-
- /**
- * Remove the given UID from all {@link FileRotator} history, migrating it
- * to {@link TrafficStats#UID_REMOVED}.
- */
- public void removeUidsLocked(int[] uids) {
- if (mRotator != null) {
- try {
- // Rewrite all persisted data to migrate UID stats
- mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uids));
- } catch (IOException e) {
- Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
- recoverFromWtf();
- } catch (OutOfMemoryError e) {
- Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
- recoverFromWtf();
- }
- }
-
- // Remove any pending stats
- if (mPending != null) {
- mPending.removeUids(uids);
- }
- if (mSinceBoot != null) {
- mSinceBoot.removeUids(uids);
- }
-
- // Clear UID from current stats snapshot
- if (mLastSnapshot != null) {
- mLastSnapshot.removeUids(uids);
- }
-
- final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
- if (complete != null) {
- complete.removeUids(uids);
- }
- }
-
- /**
- * Rewriter that will combine current {@link NetworkStatsCollection} values
- * with anything read from disk, and write combined set to disk. Clears the
- * original {@link NetworkStatsCollection} when finished writing.
- */
- private static class CombiningRewriter implements FileRotator.Rewriter {
- private final NetworkStatsCollection mCollection;
-
- public CombiningRewriter(NetworkStatsCollection collection) {
- mCollection = Objects.requireNonNull(collection, "missing NetworkStatsCollection");
- }
-
- @Override
- public void reset() {
- // ignored
- }
-
- @Override
- public void read(InputStream in) throws IOException {
- mCollection.read(in);
- }
-
- @Override
- public boolean shouldWrite() {
- return true;
- }
-
- @Override
- public void write(OutputStream out) throws IOException {
- mCollection.write(out);
- mCollection.reset();
- }
- }
-
- /**
- * Rewriter that will remove any {@link NetworkStatsHistory} attributed to
- * the requested UID, only writing data back when modified.
- */
- public static class RemoveUidRewriter implements FileRotator.Rewriter {
- private final NetworkStatsCollection mTemp;
- private final int[] mUids;
-
- public RemoveUidRewriter(long bucketDuration, int[] uids) {
- mTemp = new NetworkStatsCollection(bucketDuration);
- mUids = uids;
- }
-
- @Override
- public void reset() {
- mTemp.reset();
- }
-
- @Override
- public void read(InputStream in) throws IOException {
- mTemp.read(in);
- mTemp.clearDirty();
- mTemp.removeUids(mUids);
- }
-
- @Override
- public boolean shouldWrite() {
- return mTemp.isDirty();
- }
-
- @Override
- public void write(OutputStream out) throws IOException {
- mTemp.write(out);
- }
- }
-
- public void importLegacyNetworkLocked(File file) throws IOException {
- Objects.requireNonNull(mRotator, "missing FileRotator");
-
- // legacy file still exists; start empty to avoid double importing
- mRotator.deleteAll();
-
- final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration);
- collection.readLegacyNetwork(file);
-
- final long startMillis = collection.getStartMillis();
- final long endMillis = collection.getEndMillis();
-
- if (!collection.isEmpty()) {
- // process legacy data, creating active file at starting time, then
- // using end time to possibly trigger rotation.
- mRotator.rewriteActive(new CombiningRewriter(collection), startMillis);
- mRotator.maybeRotate(endMillis);
- }
- }
-
- public void importLegacyUidLocked(File file) throws IOException {
- Objects.requireNonNull(mRotator, "missing FileRotator");
-
- // legacy file still exists; start empty to avoid double importing
- mRotator.deleteAll();
-
- final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration);
- collection.readLegacyUid(file, mOnlyTags);
-
- final long startMillis = collection.getStartMillis();
- final long endMillis = collection.getEndMillis();
-
- if (!collection.isEmpty()) {
- // process legacy data, creating active file at starting time, then
- // using end time to possibly trigger rotation.
- mRotator.rewriteActive(new CombiningRewriter(collection), startMillis);
- mRotator.maybeRotate(endMillis);
- }
- }
-
- public void dumpLocked(IndentingPrintWriter pw, boolean fullHistory) {
- if (mPending != null) {
- pw.print("Pending bytes: "); pw.println(mPending.getTotalBytes());
- }
- if (fullHistory) {
- pw.println("Complete history:");
- getOrLoadCompleteLocked().dump(pw);
- } else {
- pw.println("History since boot:");
- mSinceBoot.dump(pw);
- }
- }
-
- public void dumpDebugLocked(ProtoOutputStream proto, long tag) {
- final long start = proto.start(tag);
- if (mPending != null) {
- proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES_FIELD_NUMBER,
- mPending.getTotalBytes());
- }
- getOrLoadCompleteLocked().dumpDebug(proto,
- NetworkStatsRecorderProto.COMPLETE_HISTORY_FIELD_NUMBER);
- proto.end(start);
- }
-
- public void dumpCheckin(PrintWriter pw, long start, long end) {
- // Only load and dump stats from the requested window
- getOrLoadPartialLocked(start, end).dumpCheckin(pw, start, end);
- }
-
- /**
- * Recover from {@link FileRotator} failure by dumping state to
- * {@link DropBoxManager} and deleting contents.
- */
- private void recoverFromWtf() {
- if (DUMP_BEFORE_DELETE) {
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- try {
- mRotator.dumpAll(os);
- } catch (IOException e) {
- // ignore partial contents
- os.reset();
- } finally {
- IoUtils.closeQuietly(os);
- }
- mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0);
- }
-
- mRotator.deleteAll();
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
deleted file mode 100644
index 7db4b8c..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ /dev/null
@@ -1,2528 +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 com.android.server.net;
-
-import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
-import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
-import static android.Manifest.permission.UPDATE_DEVICE_STATS;
-import static android.app.usage.NetworkStatsManager.PREFIX_DEV;
-import static android.content.Intent.ACTION_SHUTDOWN;
-import static android.content.Intent.ACTION_UID_REMOVED;
-import static android.content.Intent.ACTION_USER_REMOVED;
-import static android.content.Intent.EXTRA_UID;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.IFACE_VT;
-import static android.net.NetworkStats.INTERFACES_ALL;
-import static android.net.NetworkStats.METERED_ALL;
-import static android.net.NetworkStats.ROAMING_ALL;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.SET_FOREGROUND;
-import static android.net.NetworkStats.STATS_PER_IFACE;
-import static android.net.NetworkStats.STATS_PER_UID;
-import static android.net.NetworkStats.TAG_ALL;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStatsHistory.FIELD_ALL;
-import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
-import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
-import static android.net.TrafficStats.KB_IN_BYTES;
-import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.net.TrafficStats.UID_TETHERING;
-import static android.net.TrafficStats.UNSUPPORTED;
-import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
-import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
-import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
-import static android.os.Trace.TRACE_TAG_NETWORK;
-import static android.system.OsConstants.ENOENT;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-import static android.text.format.DateUtils.DAY_IN_MILLIS;
-import static android.text.format.DateUtils.HOUR_IN_MILLIS;
-import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-
-import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
-import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.TargetApi;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.usage.NetworkStatsManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.database.ContentObserver;
-import android.net.DataUsageRequest;
-import android.net.INetd;
-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.NetworkPolicyManager;
-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.TetherStatsParcel;
-import android.net.TetheringManager;
-import android.net.TrafficStats;
-import android.net.UnderlyingNetworkInfo;
-import android.net.Uri;
-import android.net.netstats.IUsageCallback;
-import android.net.netstats.provider.INetworkStatsProvider;
-import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.Binder;
-import android.os.Build;
-import android.os.DropBoxManager;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Settings.Global;
-import android.service.NetworkInterfaceProto;
-import android.service.NetworkStatsServiceDumpProto;
-import android.system.ErrnoException;
-import android.telephony.PhoneStateListener;
-import android.telephony.SubscriptionPlan;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.EventLog;
-import android.util.IndentingPrintWriter;
-import android.util.Log;
-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.FileRotator;
-import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
-import com.android.net.module.util.BestClock;
-import com.android.net.module.util.BinderUtils;
-import com.android.net.module.util.BpfMap;
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.IBpfMap;
-import com.android.net.module.util.LocationPermissionChecker;
-import com.android.net.module.util.NetworkStatsUtils;
-import com.android.net.module.util.PermissionUtils;
-import com.android.net.module.util.Struct.U32;
-import com.android.net.module.util.Struct.U8;
-
-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;
-import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Collect and persist detailed network statistics, and provide this data to
- * other system services.
- */
-@TargetApi(Build.VERSION_CODES.TIRAMISU)
-public class NetworkStatsService extends INetworkStatsService.Stub {
- static {
- System.loadLibrary("service-connectivity");
- }
-
- static final String TAG = "NetworkStats";
- static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
- static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
-
- // Perform polling and persist all (FLAG_PERSIST_ALL).
- private static final int MSG_PERFORM_POLL = 1;
- // Perform polling, persist network, and register the global alert again.
- private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
- private static final int MSG_NOTIFY_NETWORK_STATUS = 3;
- // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent
- // deadlock.
- private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4;
-
- /** Flags to control detail level of poll event. */
- private static final int FLAG_PERSIST_NETWORK = 0x1;
- private static final int FLAG_PERSIST_UID = 0x2;
- private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
- private static final int FLAG_PERSIST_FORCE = 0x100;
-
- /**
- * When global alert quota is high, wait for this delay before processing each polling,
- * and do not schedule further polls once there is already one queued.
- * This avoids firing the global alert too often on devices with high transfer speeds and
- * high quota.
- */
- private static final int DEFAULT_PERFORM_POLL_DELAY_MS = 1000;
-
- private static final String TAG_NETSTATS_ERROR = "netstats_error";
-
- /**
- * EventLog tags used when logging into the event log. Note the values must be sync with
- * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct
- * name translation.
- */
- private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100;
- private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101;
-
- // TODO: Replace the hardcoded string and move it into ConnectivitySettingsManager.
- private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED =
- "netstats_combine_subtype_enabled";
-
- // This is current path but may be changed soon.
- private static final String UID_COUNTERSET_MAP_PATH =
- "/sys/fs/bpf/map_netd_uid_counterset_map";
- private static final String COOKIE_TAG_MAP_PATH =
- "/sys/fs/bpf/map_netd_cookie_tag_map";
- private static final String APP_UID_STATS_MAP_PATH =
- "/sys/fs/bpf/map_netd_app_uid_stats_map";
- private static final String STATS_MAP_A_PATH =
- "/sys/fs/bpf/map_netd_stats_map_A";
- private static final String STATS_MAP_B_PATH =
- "/sys/fs/bpf/map_netd_stats_map_B";
-
- private final Context mContext;
- private final NetworkStatsFactory mStatsFactory;
- private final AlarmManager mAlarmManager;
- private final Clock mClock;
- private final NetworkStatsSettings mSettings;
- private final NetworkStatsObservers mStatsObservers;
-
- private final File mSystemDir;
- private final File mBaseDir;
-
- private final PowerManager.WakeLock mWakeLock;
-
- private final ContentObserver mContentObserver;
- private final ContentResolver mContentResolver;
-
- protected INetd mNetd;
- private final AlertObserver mAlertObserver = new AlertObserver();
-
- @VisibleForTesting
- public static final String ACTION_NETWORK_STATS_POLL =
- "com.android.server.action.NETWORK_STATS_POLL";
- public static final String ACTION_NETWORK_STATS_UPDATED =
- "com.android.server.action.NETWORK_STATS_UPDATED";
-
- private PendingIntent mPollIntent;
-
- /**
- * Settings that can be changed externally.
- */
- public interface NetworkStatsSettings {
- long getPollInterval();
- long getPollDelay();
- boolean getSampleEnabled();
- boolean getAugmentEnabled();
- /**
- * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}.
- * When disabled, mobile data is broken down by a granular ratType representative of the
- * actual ratType. {@see android.app.usage.NetworkStatsManager#getCollapsedRatType}.
- * Enabling this decreases the level of detail but saves performance, disk space and
- * amount of data logged.
- */
- boolean getCombineSubtypeEnabled();
-
- class Config {
- public final long bucketDuration;
- public final long rotateAgeMillis;
- public final long deleteAgeMillis;
-
- public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
- this.bucketDuration = bucketDuration;
- this.rotateAgeMillis = rotateAgeMillis;
- this.deleteAgeMillis = deleteAgeMillis;
- }
- }
-
- Config getDevConfig();
- Config getXtConfig();
- Config getUidConfig();
- Config getUidTagConfig();
-
- long getGlobalAlertBytes(long def);
- long getDevPersistBytes(long def);
- long getXtPersistBytes(long def);
- long getUidPersistBytes(long def);
- long getUidTagPersistBytes(long def);
- }
-
- private final Object mStatsLock = new Object();
-
- /** Set of currently active ifaces. */
- @GuardedBy("mStatsLock")
- private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
-
- /** Set of currently active ifaces for UID stats. */
- @GuardedBy("mStatsLock")
- private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
-
- /** Current default active iface. */
- @GuardedBy("mStatsLock")
- private String mActiveIface;
-
- /** Set of any ifaces associated with mobile networks since boot. */
- private volatile String[] mMobileIfaces = new String[0];
-
- /** Set of any ifaces associated with wifi networks since boot. */
- private volatile String[] mWifiIfaces = new String[0];
-
- /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
- @GuardedBy("mStatsLock")
- private Network[] mDefaultNetworks = new Network[0];
-
- /** Last states of all networks sent from ConnectivityService. */
- @GuardedBy("mStatsLock")
- @Nullable
- private NetworkStateSnapshot[] mLastNetworkStateSnapshots = null;
-
- private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
- new DropBoxNonMonotonicObserver();
-
- private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100;
- private final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList =
- new CopyOnWriteArrayList<>();
- /** Semaphore used to wait for stats provider to respond to request stats update. */
- private final Semaphore mStatsProviderSem = new Semaphore(0, true);
-
- @GuardedBy("mStatsLock")
- private NetworkStatsRecorder mDevRecorder;
- @GuardedBy("mStatsLock")
- private NetworkStatsRecorder mXtRecorder;
- @GuardedBy("mStatsLock")
- private NetworkStatsRecorder mUidRecorder;
- @GuardedBy("mStatsLock")
- private NetworkStatsRecorder mUidTagRecorder;
-
- /** Cached {@link #mXtRecorder} stats. */
- @GuardedBy("mStatsLock")
- private NetworkStatsCollection mXtStatsCached;
-
- /**
- * Current counter sets for each UID.
- * TODO: maybe remove mActiveUidCounterSet and read UidCouneterSet value from mUidCounterSetMap
- * directly ? But if mActiveUidCounterSet would be accessed very frequently, maybe keep
- * mActiveUidCounterSet to avoid accessing kernel too frequently.
- */
- private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
- private final IBpfMap<U32, U8> mUidCounterSetMap;
- private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap;
- private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapA;
- private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapB;
- private final IBpfMap<UidStatsMapKey, StatsMapValue> mAppUidStatsMap;
-
- /** Data layer operation counters for splicing into other structures. */
- private NetworkStats mUidOperations = new NetworkStats(0L, 10);
-
- @NonNull
- private final Handler mHandler;
-
- private volatile boolean mSystemReady;
- private long mPersistThreshold = 2 * MB_IN_BYTES;
- private long mGlobalAlertBytes;
-
- private static final long POLL_RATE_LIMIT_MS = 15_000;
-
- private long mLastStatsSessionPoll;
-
- /** Map from UID to number of opened sessions */
- @GuardedBy("mOpenSessionCallsPerUid")
- private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
-
- private final static int DUMP_STATS_SESSION_COUNT = 20;
-
- @NonNull
- private final Dependencies mDeps;
-
- @NonNull
- private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
-
- @NonNull
- private final LocationPermissionChecker mLocationPermissionChecker;
-
- @NonNull
- private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
-
- private static @NonNull File getDefaultSystemDir() {
- return new File(Environment.getDataDirectory(), "system");
- }
-
- private static @NonNull File getDefaultBaseDir() {
- File baseDir = new File(getDefaultSystemDir(), "netstats");
- baseDir.mkdirs();
- return baseDir;
- }
-
- private static @NonNull Clock getDefaultClock() {
- return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
- Clock.systemUTC());
- }
-
- private final class NetworkStatsHandler extends Handler {
- NetworkStatsHandler(@NonNull Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_PERFORM_POLL: {
- performPoll(FLAG_PERSIST_ALL);
- break;
- }
- case MSG_NOTIFY_NETWORK_STATUS: {
- // If no cached states, ignore.
- if (mLastNetworkStateSnapshots == null) break;
- // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing.
- handleNotifyNetworkStatus(
- mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
- break;
- }
- case MSG_PERFORM_POLL_REGISTER_ALERT: {
- performPoll(FLAG_PERSIST_NETWORK);
- registerGlobalAlert();
- break;
- }
- case MSG_BROADCAST_NETWORK_STATS_UPDATED: {
- final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
- updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
- READ_NETWORK_USAGE_HISTORY);
- break;
- }
- }
- }
- }
-
- /** Creates a new NetworkStatsService */
- public static NetworkStatsService create(Context context) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- 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,
- INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
- alarmManager, wakeLock, getDefaultClock(),
- new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context),
- new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
- new Dependencies());
-
- return service;
- }
-
- // This must not be called outside of tests, even within the same package, as this constructor
- // does not register the local service. Use the create() helper above.
- @VisibleForTesting
- NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager,
- PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings,
- NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
- File baseDir, @NonNull Dependencies deps) {
- mContext = Objects.requireNonNull(context, "missing Context");
- mNetd = Objects.requireNonNull(netd, "missing Netd");
- mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
- mClock = Objects.requireNonNull(clock, "missing Clock");
- mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
- mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
- mStatsFactory = Objects.requireNonNull(factory, "missing factory");
- mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
- mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
- mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
- mDeps = Objects.requireNonNull(deps, "missing Dependencies");
-
- final HandlerThread handlerThread = mDeps.makeHandlerThread();
- handlerThread.start();
- mHandler = new NetworkStatsHandler(handlerThread.getLooper());
- mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
- (command) -> mHandler.post(command) , this);
- mContentResolver = mContext.getContentResolver();
- mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
- mNetworkStatsSubscriptionsMonitor);
- mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
- mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
- mInterfaceMapUpdater.start();
- mUidCounterSetMap = mDeps.getUidCounterSetMap();
- mCookieTagMap = mDeps.getCookieTagMap();
- mStatsMapA = mDeps.getStatsMapA();
- mStatsMapB = mDeps.getStatsMapB();
- mAppUidStatsMap = mDeps.getAppUidStatsMap();
- }
-
- /**
- * Dependencies of NetworkStatsService, for injection in tests.
- */
- // TODO: Move more stuff into dependencies object.
- @VisibleForTesting
- public static class Dependencies {
- /**
- * Create a HandlerThread to use in NetworkStatsService.
- */
- @NonNull
- public HandlerThread makeHandlerThread() {
- return new HandlerThread(TAG);
- }
-
- /**
- * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change
- * event in NetworkStatsService.
- */
- @NonNull
- public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context,
- @NonNull Executor executor, @NonNull NetworkStatsService service) {
- // TODO: Update RatType passively in NSS, instead of querying into the monitor
- // when notifyNetworkStatus.
- return new NetworkStatsSubscriptionsMonitor(context, executor,
- (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
- }
-
- /**
- * Create a ContentObserver instance which is used to observe settings changes,
- * and dispatch onChange events on handler thread.
- */
- public @NonNull ContentObserver makeContentObserver(@NonNull Handler handler,
- @NonNull NetworkStatsSettings settings,
- @NonNull NetworkStatsSubscriptionsMonitor monitor) {
- return new ContentObserver(handler) {
- @Override
- public void onChange(boolean selfChange, @NonNull Uri uri) {
- if (!settings.getCombineSubtypeEnabled()) {
- monitor.start();
- } else {
- monitor.stop();
- }
- }
- };
- }
-
- /**
- * @see LocationPermissionChecker
- */
- public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
- return new LocationPermissionChecker(context);
- }
-
- /** Create BpfInterfaceMapUpdater to update bpf interface map. */
- @NonNull
- public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater(
- @NonNull Context ctx, @NonNull Handler handler) {
- return new BpfInterfaceMapUpdater(ctx, handler);
- }
-
- /** Get counter sets map for each UID. */
- public IBpfMap<U32, U8> getUidCounterSetMap() {
- try {
- return new BpfMap<U32, U8>(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR,
- U32.class, U8.class);
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Cannot open uid counter set map: " + e);
- return null;
- }
- }
-
- /** Gets the cookie tag map */
- public IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
- try {
- return new BpfMap<CookieTagMapKey, CookieTagMapValue>(COOKIE_TAG_MAP_PATH,
- BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class);
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Cannot open cookie tag map: " + e);
- return null;
- }
- }
-
- /** Gets stats map A */
- public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapA() {
- try {
- return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_A_PATH,
- BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Cannot open stats map A: " + e);
- return null;
- }
- }
-
- /** Gets stats map B */
- public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapB() {
- try {
- return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_B_PATH,
- BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Cannot open stats map B: " + e);
- return null;
- }
- }
-
- /** Gets the uid stats map */
- public IBpfMap<UidStatsMapKey, StatsMapValue> getAppUidStatsMap() {
- try {
- return new BpfMap<UidStatsMapKey, StatsMapValue>(APP_UID_STATS_MAP_PATH,
- BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class);
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Cannot open app uid stats map: " + e);
- return null;
- }
- }
- }
-
- /**
- * Observer that watches for {@link INetdUnsolicitedEventListener} alerts.
- */
- @VisibleForTesting
- public class AlertObserver extends BaseNetdUnsolicitedEventListener {
- @Override
- public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
-
- if (LIMIT_GLOBAL_ALERT.equals(alertName)) {
- // kick off background poll to collect network stats unless there is already
- // such a call pending; UID stats are handled during normal polling interval.
- if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
- mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
- mSettings.getPollDelay());
- }
- }
- }
- }
-
- public void systemReady() {
- synchronized (mStatsLock) {
- mSystemReady = true;
-
- // create data recorders along with historical rotators
- mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
- mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
- mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
- mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
-
- updatePersistThresholdsLocked();
-
- // upgrade any legacy stats, migrating them to rotated files
- maybeUpgradeLegacyStatsLocked();
-
- // read historical network stats from disk, since policy service
- // might need them right away.
- mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
-
- // bootstrap initial stats to prevent double-counting later
- bootstrapStatsLocked();
- }
-
- // watch for tethering changes
- final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
- tetheringManager.registerTetheringEventCallback(
- (command) -> mHandler.post(command), mTetherListener);
-
- // listen for periodic polling events
- final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
- mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
-
- // listen for uid removal to clean stats
- final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
- mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
-
- // listen for user changes to clean stats
- final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
- mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
-
- // persist stats during clean shutdown
- final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
- mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
-
- try {
- mNetd.registerUnsolicitedEventListener(mAlertObserver);
- } catch (RemoteException | ServiceSpecificException e) {
- Log.wtf(TAG, "Error registering event listener :", e);
- }
-
- // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
- final PendingIntent pollIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL),
- PendingIntent.FLAG_IMMUTABLE);
-
- final long currentRealtime = SystemClock.elapsedRealtime();
- mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
- mSettings.getPollInterval(), pollIntent);
-
- mContentResolver.registerContentObserver(Settings.Global
- .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED),
- false /* notifyForDescendants */, mContentObserver);
-
- // Post a runnable on handler thread to call onChange(). It's for getting current value of
- // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes.
- mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
- .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED)));
-
- registerGlobalAlert();
- }
-
- private NetworkStatsRecorder buildRecorder(
- String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
- final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
- Context.DROPBOX_SERVICE);
- return new NetworkStatsRecorder(new FileRotator(
- mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
- mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
- }
-
- @GuardedBy("mStatsLock")
- private void shutdownLocked() {
- final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
- tetheringManager.unregisterTetheringEventCallback(mTetherListener);
- mContext.unregisterReceiver(mPollReceiver);
- mContext.unregisterReceiver(mRemovedReceiver);
- mContext.unregisterReceiver(mUserReceiver);
- mContext.unregisterReceiver(mShutdownReceiver);
-
- if (!mSettings.getCombineSubtypeEnabled()) {
- mNetworkStatsSubscriptionsMonitor.stop();
- }
-
- mContentResolver.unregisterContentObserver(mContentObserver);
-
- final long currentTime = mClock.millis();
-
- // persist any pending stats
- mDevRecorder.forcePersistLocked(currentTime);
- mXtRecorder.forcePersistLocked(currentTime);
- mUidRecorder.forcePersistLocked(currentTime);
- mUidTagRecorder.forcePersistLocked(currentTime);
-
- mSystemReady = false;
- }
-
- @GuardedBy("mStatsLock")
- private void maybeUpgradeLegacyStatsLocked() {
- File file;
- try {
- file = new File(mSystemDir, "netstats.bin");
- if (file.exists()) {
- mDevRecorder.importLegacyNetworkLocked(file);
- file.delete();
- }
-
- file = new File(mSystemDir, "netstats_xt.bin");
- if (file.exists()) {
- file.delete();
- }
-
- file = new File(mSystemDir, "netstats_uid.bin");
- if (file.exists()) {
- mUidRecorder.importLegacyUidLocked(file);
- mUidTagRecorder.importLegacyUidLocked(file);
- file.delete();
- }
- } catch (IOException e) {
- Log.wtf(TAG, "problem during legacy upgrade", e);
- } catch (OutOfMemoryError e) {
- Log.wtf(TAG, "problem during legacy upgrade", e);
- }
- }
-
- /**
- * Register for a global alert that is delivered through {@link AlertObserver}
- * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
- * been transferred.
- */
- private void registerGlobalAlert() {
- try {
- mNetd.bandwidthSetGlobalAlert(mGlobalAlertBytes);
- } catch (IllegalStateException e) {
- Log.w(TAG, "problem registering for global alert: " + e);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
- invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes));
- }
-
- @Override
- public INetworkStatsSession openSession() {
- return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
- }
-
- @Override
- public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) {
- return openSessionInternal(flags, callingPackage);
- }
-
- private boolean isRateLimitedForPoll(int callingUid) {
- if (callingUid == android.os.Process.SYSTEM_UID) {
- return false;
- }
-
- final long lastCallTime;
- final long now = SystemClock.elapsedRealtime();
- synchronized (mOpenSessionCallsPerUid) {
- int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
- mOpenSessionCallsPerUid.put(callingUid, calls + 1);
- lastCallTime = mLastStatsSessionPoll;
- mLastStatsSessionPoll = now;
- }
-
- return now - lastCallTime < POLL_RATE_LIMIT_MS;
- }
-
- private int restrictFlagsForCaller(int flags) {
- // All non-privileged callers are not allowed to turn off POLL_ON_OPEN.
- final boolean isPrivileged = PermissionUtils.checkAnyPermissionOf(mContext,
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK);
- if (!isPrivileged) {
- flags |= NetworkStatsManager.FLAG_POLL_ON_OPEN;
- }
- // Non-system uids are rate limited for POLL_ON_OPEN.
- final int callingUid = Binder.getCallingUid();
- flags = isRateLimitedForPoll(callingUid)
- ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
- : flags;
- return flags;
- }
-
- private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
- final int restrictedFlags = restrictFlagsForCaller(flags);
- if ((restrictedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
- | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
- final long ident = Binder.clearCallingIdentity();
- try {
- performPoll(FLAG_PERSIST_ALL);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- // return an IBinder which holds strong references to any loaded stats
- // for its lifetime; when caller closes only weak references remain.
-
- return new INetworkStatsSession.Stub() {
- private final int mCallingUid = Binder.getCallingUid();
- private final String mCallingPackage = callingPackage;
- private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
- callingPackage);
-
- private NetworkStatsCollection mUidComplete;
- private NetworkStatsCollection mUidTagComplete;
-
- private NetworkStatsCollection getUidComplete() {
- synchronized (mStatsLock) {
- if (mUidComplete == null) {
- mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
- }
- return mUidComplete;
- }
- }
-
- private NetworkStatsCollection getUidTagComplete() {
- synchronized (mStatsLock) {
- if (mUidTagComplete == null) {
- mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
- }
- return mUidTagComplete;
- }
- }
-
- @Override
- public int[] getRelevantUids() {
- return getUidComplete().getRelevantUids(mAccessLevel);
- }
-
- @Override
- public NetworkStats getDeviceSummaryForNetwork(
- NetworkTemplate template, long start, long end) {
- enforceTemplatePermissions(template, callingPackage);
- return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
- mAccessLevel, mCallingUid);
- }
-
- @Override
- public NetworkStats getSummaryForNetwork(
- NetworkTemplate template, long start, long end) {
- enforceTemplatePermissions(template, callingPackage);
- return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
- mAccessLevel, mCallingUid);
- }
-
- // TODO: Remove this after all callers are removed.
- @Override
- public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- enforceTemplatePermissions(template, callingPackage);
- return internalGetHistoryForNetwork(template, restrictedFlags, fields,
- mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE);
- }
-
- @Override
- public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template,
- int fields, long start, long end) {
- enforceTemplatePermissions(template, callingPackage);
- // TODO(b/200768422): Redact returned history if the template is location
- // sensitive but the caller is not privileged.
- return internalGetHistoryForNetwork(template, restrictedFlags, fields,
- mAccessLevel, mCallingUid, start, end);
- }
-
- @Override
- public NetworkStats getSummaryForAllUid(
- NetworkTemplate template, long start, long end, boolean includeTags) {
- enforceTemplatePermissions(template, callingPackage);
- try {
- final NetworkStats stats = getUidComplete()
- .getSummary(template, start, end, mAccessLevel, mCallingUid);
- if (includeTags) {
- final NetworkStats tagStats = getUidTagComplete()
- .getSummary(template, start, end, mAccessLevel, mCallingUid);
- stats.combineAllValues(tagStats);
- }
- return stats;
- } catch (NullPointerException e) {
- throw e;
- }
- }
-
- @Override
- public NetworkStats getTaggedSummaryForAllUid(
- NetworkTemplate template, long start, long end) {
- enforceTemplatePermissions(template, callingPackage);
- try {
- final NetworkStats tagStats = getUidTagComplete()
- .getSummary(template, start, end, mAccessLevel, mCallingUid);
- return tagStats;
- } catch (NullPointerException e) {
- throw e;
- }
- }
-
- @Override
- public NetworkStatsHistory getHistoryForUid(
- NetworkTemplate template, int uid, int set, int tag, int fields) {
- enforceTemplatePermissions(template, callingPackage);
- // NOTE: We don't augment UID-level statistics
- if (tag == TAG_NONE) {
- return getUidComplete().getHistory(template, null, uid, set, tag, fields,
- Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
- } else {
- return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
- Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
- }
- }
-
- @Override
- public NetworkStatsHistory getHistoryIntervalForUid(
- NetworkTemplate template, int uid, int set, int tag, int fields,
- long start, long end) {
- enforceTemplatePermissions(template, callingPackage);
- // TODO(b/200768422): Redact returned history if the template is location
- // sensitive but the caller is not privileged.
- // NOTE: We don't augment UID-level statistics
- if (tag == TAG_NONE) {
- return getUidComplete().getHistory(template, null, uid, set, tag, fields,
- start, end, mAccessLevel, mCallingUid);
- } else if (uid == Binder.getCallingUid()) {
- return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
- start, end, mAccessLevel, mCallingUid);
- } else {
- throw new SecurityException("Calling package " + mCallingPackage
- + " cannot access tag information from a different uid");
- }
- }
-
- @Override
- public void close() {
- mUidComplete = null;
- mUidTagComplete = null;
- }
- };
- }
-
- private void enforceTemplatePermissions(@NonNull NetworkTemplate template,
- @NonNull String callingPackage) {
- // For a template with wifi network keys, it is possible for a malicious
- // client to track the user locations via querying data usage. Thus, enforce
- // fine location permission check.
- if (!template.getWifiNetworkKeys().isEmpty()) {
- final boolean canAccessFineLocation = mLocationPermissionChecker
- .checkCallersLocationPermission(callingPackage,
- null /* featureId */,
- Binder.getCallingUid(),
- false /* coarseForTargetSdkLessThanQ */,
- null /* message */);
- if (!canAccessFineLocation) {
- throw new SecurityException("Access fine location is required when querying"
- + " with wifi network keys, make sure the app has the necessary"
- + "permissions and the location toggle is on.");
- }
- }
- }
-
- private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
- return NetworkStatsAccess.checkAccessLevel(
- mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
- }
-
- /**
- * Find the most relevant {@link SubscriptionPlan} for the given
- * {@link NetworkTemplate} and flags. This is typically used to augment
- * local measurement results to match a known anchor from the carrier.
- */
- private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) {
- SubscriptionPlan plan = null;
- if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
- && mSettings.getAugmentEnabled()) {
- if (LOGD) Log.d(TAG, "Resolving plan for " + template);
- final long token = Binder.clearCallingIdentity();
- try {
- plan = mContext.getSystemService(NetworkPolicyManager.class)
- .getSubscriptionPlan(template);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- if (LOGD) Log.d(TAG, "Resolved to plan " + plan);
- }
- return plan;
- }
-
- /**
- * Return network summary, splicing between DEV and XT stats when
- * appropriate.
- */
- private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags,
- long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
- // We've been using pure XT stats long enough that we no longer need to
- // splice DEV and XT together.
- final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
- accessLevel, callingUid, start, end);
-
- final long now = System.currentTimeMillis();
- final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
-
- final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
- entry.txBytes, entry.txPackets, entry.operations));
- return stats;
- }
-
- /**
- * Return network history, splicing between DEV and XT stats when
- * appropriate.
- */
- private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
- int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid,
- long start, long end) {
- // We've been using pure XT stats long enough that we no longer need to
- // splice DEV and XT together.
- final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
- synchronized (mStatsLock) {
- return mXtStatsCached.getHistory(template, augmentPlan,
- UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
- }
- }
-
- private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
- assertSystemReady();
-
- return internalGetSummaryForNetwork(template,
- NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
- NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
- }
-
- private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
- assertSystemReady();
-
- final NetworkStatsCollection uidComplete;
- synchronized (mStatsLock) {
- uidComplete = mUidRecorder.getOrLoadCompleteLocked();
- }
- return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE,
- android.os.Process.SYSTEM_UID);
- }
-
- @Override
- public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
- if (Binder.getCallingUid() != uid) {
- Log.w(TAG, "Snapshots only available for calling UID");
- return new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
-
- // TODO: switch to data layer stats once kernel exports
- // for now, read network layer stats and flatten across all ifaces.
- // This function is used to query NeworkStats for calle's uid. The only caller method
- // TrafficStats#getDataLayerSnapshotForUid alrady claim no special permission to query
- // its own NetworkStats.
- final long ident = Binder.clearCallingIdentity();
- final NetworkStats networkLayer;
- try {
- networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- // splice in operation counts
- networkLayer.spliceOperationsFrom(mUidOperations);
-
- final NetworkStats dataLayer = new NetworkStats(
- networkLayer.getElapsedRealtime(), networkLayer.size());
-
- NetworkStats.Entry entry = null;
- for (int i = 0; i < networkLayer.size(); i++) {
- entry = networkLayer.getValues(i, entry);
- entry.iface = IFACE_ALL;
- dataLayer.combineValues(entry);
- }
-
- return dataLayer;
- }
-
- @Override
- public NetworkStats getUidStatsForTransport(int transport) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- try {
- final String[] relevantIfaces =
- transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces;
- // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
- // interfaces, so this is not useful, remove it.
- final String[] ifacesToQuery =
- mStatsFactory.augmentWithStackedInterfaces(relevantIfaces);
- return getNetworkStatsUidDetail(ifacesToQuery);
- } catch (RemoteException e) {
- Log.wtf(TAG, "Error compiling UID stats", e);
- return new NetworkStats(0L, 0);
- }
- }
-
- @Override
- public String[] getMobileIfaces() {
- // TODO (b/192758557): Remove debug log.
- if (CollectionUtils.contains(mMobileIfaces, null)) {
- throw new NullPointerException(
- "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
- }
- return mMobileIfaces.clone();
- }
-
- @Override
- public void incrementOperationCount(int uid, int tag, int operationCount) {
- if (Binder.getCallingUid() != uid) {
- mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
- }
-
- if (operationCount < 0) {
- throw new IllegalArgumentException("operation count can only be incremented");
- }
- if (tag == TAG_NONE) {
- throw new IllegalArgumentException("operation count must have specific tag");
- }
-
- synchronized (mStatsLock) {
- final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
- mUidOperations.combineValues(
- mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
- mUidOperations.combineValues(
- mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
- }
- }
-
- private void setKernelCounterSet(int uid, int set) {
- if (mUidCounterSetMap == null) {
- Log.wtf(TAG, "Fail to set UidCounterSet: Null bpf map");
- return;
- }
-
- if (set == SET_DEFAULT) {
- try {
- mUidCounterSetMap.deleteEntry(new U32(uid));
- } catch (ErrnoException e) {
- Log.w(TAG, "UidCounterSetMap.deleteEntry(" + uid + ") failed with errno: " + e);
- }
- return;
- }
-
- try {
- mUidCounterSetMap.updateEntry(new U32(uid), new U8((short) set));
- } catch (ErrnoException e) {
- Log.w(TAG, "UidCounterSetMap.updateEntry(" + uid + ", " + set
- + ") failed with errno: " + e);
- }
- }
-
- @VisibleForTesting
- public void noteUidForeground(int uid, boolean uidForeground) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- synchronized (mStatsLock) {
- final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
- final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
- if (oldSet != set) {
- mActiveUidCounterSet.put(uid, set);
- setKernelCounterSet(uid, set);
- }
- }
- }
-
- /**
- * Notify {@code NetworkStatsService} about network status changed.
- */
- public void notifyNetworkStatus(
- @NonNull Network[] defaultNetworks,
- @NonNull NetworkStateSnapshot[] networkStates,
- @Nullable String activeIface,
- @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
-
- final long token = Binder.clearCallingIdentity();
- try {
- handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- // Update the VPN underlying interfaces only after the poll is made and tun data has been
- // migrated. Otherwise the migration would use the new interfaces instead of the ones that
- // were current when the polled data was transferred.
- mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
- }
-
- @Override
- public void forceUpdate() {
- PermissionUtils.enforceNetworkStackPermission(mContext);
-
- final long token = Binder.clearCallingIdentity();
- try {
- performPoll(FLAG_PERSIST_ALL);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /** Advise persistence threshold; may be overridden internally. */
- public void advisePersistThreshold(long thresholdBytes) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- // clamp threshold into safe range
- mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes,
- 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
- if (LOGV) {
- Log.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
- + mPersistThreshold);
- }
-
- final long oldGlobalAlertBytes = mGlobalAlertBytes;
-
- // update and persist if beyond new thresholds
- final long currentTime = mClock.millis();
- synchronized (mStatsLock) {
- if (!mSystemReady) return;
-
- updatePersistThresholdsLocked();
-
- mDevRecorder.maybePersistLocked(currentTime);
- mXtRecorder.maybePersistLocked(currentTime);
- mUidRecorder.maybePersistLocked(currentTime);
- mUidTagRecorder.maybePersistLocked(currentTime);
- }
-
- if (oldGlobalAlertBytes != mGlobalAlertBytes) {
- registerGlobalAlert();
- }
- }
-
- @Override
- public DataUsageRequest registerUsageCallback(@NonNull String callingPackage,
- @NonNull DataUsageRequest request, @NonNull IUsageCallback callback) {
- Objects.requireNonNull(callingPackage, "calling package is null");
- Objects.requireNonNull(request, "DataUsageRequest is null");
- Objects.requireNonNull(request.template, "NetworkTemplate is null");
- Objects.requireNonNull(callback, "callback is null");
-
- int callingUid = Binder.getCallingUid();
- @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
- DataUsageRequest normalizedRequest;
- final long token = Binder.clearCallingIdentity();
- try {
- normalizedRequest = mStatsObservers.register(mContext,
- request, callback, callingUid, accessLevel);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- // Create baseline stats
- mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL));
-
- return normalizedRequest;
- }
-
- @Override
- public void unregisterUsageRequest(DataUsageRequest request) {
- Objects.requireNonNull(request, "DataUsageRequest is null");
-
- int callingUid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- mStatsObservers.unregister(request, callingUid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public long getUidStats(int uid, int type) {
- final int callingUid = Binder.getCallingUid();
- if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
- return UNSUPPORTED;
- }
- return nativeGetUidStat(uid, type);
- }
-
- @Override
- public long getIfaceStats(@NonNull String iface, int type) {
- Objects.requireNonNull(iface);
- long nativeIfaceStats = nativeGetIfaceStat(iface, type);
- if (nativeIfaceStats == -1) {
- return nativeIfaceStats;
- } else {
- // When tethering offload is in use, nativeIfaceStats does not contain usage from
- // offload, add it back here. Note that the included statistics might be stale
- // since polling newest stats from hardware might impact system health and not
- // suitable for TrafficStats API use cases.
- return nativeIfaceStats + getProviderIfaceStats(iface, type);
- }
- }
-
- @Override
- public long getTotalStats(int type) {
- long nativeTotalStats = nativeGetTotalStat(type);
- if (nativeTotalStats == -1) {
- return nativeTotalStats;
- } else {
- // Refer to comment in getIfaceStats
- return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type);
- }
- }
-
- private long getProviderIfaceStats(@Nullable String iface, int type) {
- final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
- final HashSet<String> limitIfaces;
- if (iface == IFACE_ALL) {
- limitIfaces = null;
- } else {
- limitIfaces = new HashSet<>();
- limitIfaces.add(iface);
- }
- final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces);
- switch (type) {
- case TrafficStats.TYPE_RX_BYTES:
- return entry.rxBytes;
- case TrafficStats.TYPE_RX_PACKETS:
- return entry.rxPackets;
- case TrafficStats.TYPE_TX_BYTES:
- return entry.txBytes;
- case TrafficStats.TYPE_TX_PACKETS:
- return entry.txPackets;
- default:
- return 0;
- }
- }
-
- /**
- * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
- * reflect current {@link #mPersistThreshold} value. Always defers to
- * {@link Global} values when defined.
- */
- @GuardedBy("mStatsLock")
- private void updatePersistThresholdsLocked() {
- mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
- mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
- mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
- mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
- mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
- }
-
- /**
- * Listener that watches for {@link TetheringManager} to claim interface pairs.
- */
- 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
- public void onReceive(Context context, Intent intent) {
- // on background handler thread, and verified UPDATE_DEVICE_STATS
- // permission above.
- performPoll(FLAG_PERSIST_ALL);
-
- // verify that we're watching global alert
- registerGlobalAlert();
- }
- };
-
- private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // on background handler thread, and UID_REMOVED is protected
- // broadcast.
-
- final int uid = intent.getIntExtra(EXTRA_UID, -1);
- if (uid == -1) return;
-
- synchronized (mStatsLock) {
- mWakeLock.acquire();
- try {
- removeUidsLocked(uid);
- } finally {
- mWakeLock.release();
- }
- }
- }
- };
-
- private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // On background handler thread, and USER_REMOVED is protected
- // broadcast.
-
- final UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
- if (userHandle == null) return;
-
- synchronized (mStatsLock) {
- mWakeLock.acquire();
- try {
- removeUserLocked(userHandle);
- } finally {
- mWakeLock.release();
- }
- }
- }
- };
-
- private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // SHUTDOWN is protected broadcast.
- synchronized (mStatsLock) {
- shutdownLocked();
- }
- }
- };
-
- /**
- * Handle collapsed RAT type changed event.
- */
- @VisibleForTesting
- public void handleOnCollapsedRatTypeChanged() {
- // Protect service from frequently updating. Remove pending messages if any.
- mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS);
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay());
- }
-
- private void handleNotifyNetworkStatus(
- Network[] defaultNetworks,
- NetworkStateSnapshot[] snapshots,
- String activeIface) {
- synchronized (mStatsLock) {
- mWakeLock.acquire();
- try {
- mActiveIface = activeIface;
- handleNotifyNetworkStatusLocked(defaultNetworks, snapshots);
- } finally {
- mWakeLock.release();
- }
- }
- }
-
- /**
- * Inspect all current {@link NetworkStateSnapshot}s to derive mapping from {@code iface} to
- * {@link NetworkStatsHistory}. When multiple networks are active on a single {@code iface},
- * they are combined under a single {@link NetworkIdentitySet}.
- */
- @GuardedBy("mStatsLock")
- private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
- @NonNull NetworkStateSnapshot[] snapshots) {
- if (!mSystemReady) return;
- 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
- // the updated network.
-
- // poll, but only persist network stats to keep codepath fast. UID stats
- // will be persisted during next alarm poll event.
- performPollLocked(FLAG_PERSIST_NETWORK);
-
- // Rebuild active interfaces based on connected networks
- mActiveIfaces.clear();
- mActiveUidIfaces.clear();
- // Update the list of default networks.
- mDefaultNetworks = defaultNetworks;
-
- mLastNetworkStateSnapshots = snapshots;
-
- final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
- final ArraySet<String> mobileIfaces = new ArraySet<>();
- final ArraySet<String> wifiIfaces = new ArraySet<>();
- for (NetworkStateSnapshot snapshot : snapshots) {
- final int displayTransport =
- getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
- final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
- final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport);
- final boolean isDefault = CollectionUtils.contains(
- mDefaultNetworks, snapshot.getNetwork());
- final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL
- : getRatTypeForStateSnapshot(snapshot);
- final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
- isDefault, ratType);
-
- // Traffic occurring on the base interface is always counted for
- // both total usage and UID details.
- final String baseIface = snapshot.getLinkProperties().getInterfaceName();
- if (baseIface != null) {
- findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
- findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
-
- // Build a separate virtual interface for VT (Video Telephony) data usage.
- // Only do this when IMS is not metered, but VT is metered.
- // If IMS is metered, then the IMS network usage has already included VT usage.
- // VT is considered always metered in framework's layer. If VT is not metered
- // per carrier's policy, modem will report 0 usage for VT calls.
- if (snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
-
- // Copy the identify from IMS one but mark it as metered.
- NetworkIdentity vtIdent = new NetworkIdentity.Builder()
- .setType(ident.getType())
- .setRatType(ident.getRatType())
- .setSubscriberId(ident.getSubscriberId())
- .setWifiNetworkKey(ident.getWifiNetworkKey())
- .setRoaming(ident.isRoaming()).setMetered(true)
- .setDefaultNetwork(true)
- .setOemManaged(ident.getOemManaged())
- .setSubId(ident.getSubId()).build();
- final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
- findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
- findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);
- }
-
- if (isMobile) {
- mobileIfaces.add(baseIface);
- }
- if (isWifi) {
- wifiIfaces.add(baseIface);
- }
- }
-
- // Traffic occurring on stacked interfaces is usually clatd.
- //
- // UID stats are always counted on the stacked interface and never on the base
- // interface, because the packets on the base interface do not actually match
- // application sockets (they're not IPv4) and thus the app uid is not known.
- // For receive this is obvious: packets must be translated from IPv6 to IPv4
- // before the application socket can be found.
- // For transmit: either they go through the clat daemon which by virtue of going
- // through userspace strips the original socket association during the IPv4 to
- // IPv6 translation process, or they are offloaded by eBPF, which doesn't:
- // However, on an ebpf device the accounting is done in cgroup ebpf hooks,
- // which don't trigger again post ebpf translation.
- // (as such stats accounted to the clat uid are ignored)
- //
- // Interface stats are more complicated.
- //
- // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus
- // *all* statistics are collected by iptables on the stacked v4-* interface.
- //
- // Additionally for ingress all packets bound for the clat IPv6 address are dropped
- // in ip6tables raw prerouting and thus even non-offloaded packets are only
- // accounted for on the stacked interface.
- //
- // For egress, packets subject to eBPF offload never appear on the base interface
- // and only appear on the stacked interface. Thus to ensure packets increment
- // interface stats, we must collate data from stacked interfaces. For xt_qtaguid
- // (or non eBPF offloaded) TX they would appear on both, however egress interface
- // accounting is explicitly bypassed for traffic from the clat uid.
- //
- // TODO: This code might be combined to above code.
- for (String iface : snapshot.getLinkProperties().getAllInterfaceNames()) {
- // baseIface has been handled, so ignore it.
- if (TextUtils.equals(baseIface, iface)) continue;
- if (iface != null) {
- findOrCreateNetworkIdentitySet(mActiveIfaces, iface).add(ident);
- findOrCreateNetworkIdentitySet(mActiveUidIfaces, iface).add(ident);
- if (isMobile) {
- mobileIfaces.add(iface);
- }
- if (isWifi) {
- wifiIfaces.add(iface);
- }
-
- mStatsFactory.noteStackedIface(iface, baseIface);
- }
- }
- }
-
- mMobileIfaces = mobileIfaces.toArray(new String[0]);
- mWifiIfaces = wifiIfaces.toArray(new String[0]);
- // TODO (b/192758557): Remove debug log.
- if (CollectionUtils.contains(mMobileIfaces, null)) {
- throw new NullPointerException(
- "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
- }
- if (CollectionUtils.contains(mWifiIfaces, null)) {
- throw new NullPointerException(
- "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces));
- }
- }
-
- private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
- if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR");
- }
-
- final NetworkSpecifier spec = state.getNetworkCapabilities().getNetworkSpecifier();
- if (spec instanceof TelephonyNetworkSpecifier) {
- return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
- } else {
- Log.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
- return INVALID_SUBSCRIPTION_ID;
- }
- }
-
- /**
- * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through
- * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
- * transport types do not actually fill this value.
- */
- private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
- if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- return 0;
- }
-
- return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.getSubscriberId());
- }
-
- private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
- ArrayMap<K, NetworkIdentitySet> map, K key) {
- NetworkIdentitySet ident = map.get(key);
- if (ident == null) {
- ident = new NetworkIdentitySet();
- map.put(key, ident);
- }
- return ident;
- }
-
- @GuardedBy("mStatsLock")
- private void recordSnapshotLocked(long currentTime) throws RemoteException {
- // snapshot and record current counters; read UID stats first to
- // avoid over counting dev stats.
- Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
- final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
- Trace.traceEnd(TRACE_TAG_NETWORK);
- Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
- final NetworkStats xtSnapshot = readNetworkStatsSummaryXt();
- Trace.traceEnd(TRACE_TAG_NETWORK);
- Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
- final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
- Trace.traceEnd(TRACE_TAG_NETWORK);
-
- // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
- // from stats providers that isn't already counted by dev and XT stats.
- Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
- final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
- Trace.traceEnd(TRACE_TAG_NETWORK);
- xtSnapshot.combineAllValues(providersnapshot);
- devSnapshot.combineAllValues(providersnapshot);
-
- // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
- // can't be reattributed to responsible apps.
- Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
- mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
- Trace.traceEnd(TRACE_TAG_NETWORK);
- Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
- mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
- Trace.traceEnd(TRACE_TAG_NETWORK);
-
- // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
- Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
- mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
- Trace.traceEnd(TRACE_TAG_NETWORK);
- Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
- mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
- Trace.traceEnd(TRACE_TAG_NETWORK);
-
- // We need to make copies of member fields that are sent to the observer to avoid
- // a race condition between the service handler thread and the observer's
- mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
- new ArrayMap<>(mActiveUidIfaces), currentTime);
- }
-
- /**
- * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
- * so we have baseline values without double-counting.
- */
- @GuardedBy("mStatsLock")
- private void bootstrapStatsLocked() {
- final long currentTime = mClock.millis();
-
- try {
- recordSnapshotLocked(currentTime);
- } catch (IllegalStateException e) {
- Log.w(TAG, "problem reading network stats: " + e);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
- }
-
- private void performPoll(int flags) {
- synchronized (mStatsLock) {
- mWakeLock.acquire();
-
- try {
- performPollLocked(flags);
- } finally {
- mWakeLock.release();
- }
- }
- }
-
- /**
- * Periodic poll operation, reading current statistics and recording into
- * {@link NetworkStatsHistory}.
- */
- @GuardedBy("mStatsLock")
- private void performPollLocked(int flags) {
- if (!mSystemReady) return;
- 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;
- final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
- final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
-
- performPollFromProvidersLocked();
-
- // TODO: consider marking "untrusted" times in historical stats
- final long currentTime = mClock.millis();
-
- try {
- recordSnapshotLocked(currentTime);
- } catch (IllegalStateException e) {
- Log.wtf(TAG, "problem reading network stats", e);
- return;
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- return;
- }
-
- // persist any pending data depending on requested flags
- Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
- if (persistForce) {
- mDevRecorder.forcePersistLocked(currentTime);
- mXtRecorder.forcePersistLocked(currentTime);
- mUidRecorder.forcePersistLocked(currentTime);
- mUidTagRecorder.forcePersistLocked(currentTime);
- } else {
- if (persistNetwork) {
- mDevRecorder.maybePersistLocked(currentTime);
- mXtRecorder.maybePersistLocked(currentTime);
- }
- if (persistUid) {
- mUidRecorder.maybePersistLocked(currentTime);
- mUidTagRecorder.maybePersistLocked(currentTime);
- }
- }
- Trace.traceEnd(TRACE_TAG_NETWORK);
-
- if (mSettings.getSampleEnabled()) {
- // sample stats after each full poll
- performSampleLocked();
- }
-
- // finally, dispatch updated event to any listeners
- mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED));
-
- Trace.traceEnd(TRACE_TAG_NETWORK);
- }
-
- @GuardedBy("mStatsLock")
- private void performPollFromProvidersLocked() {
- // Request asynchronous stats update from all providers for next poll. And wait a bit of
- // time to allow providers report-in given that normally binder call should be fast. Note
- // that size of list might be changed because addition/removing at the same time. For
- // addition, the stats of the missed provider can only be collected in next poll;
- // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
- // once that happened.
- // TODO: request with a valid token.
- Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
- final int registeredCallbackCount = mStatsProviderCbList.size();
- mStatsProviderSem.drainPermits();
- invokeForAllStatsProviderCallbacks(
- (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
- try {
- mStatsProviderSem.tryAcquire(registeredCallbackCount,
- MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- // Strictly speaking it's possible a provider happened to deliver between the timeout
- // and the log, and that doesn't matter too much as this is just a debug log.
- Log.d(TAG, "requestStatsUpdate - providers responded "
- + mStatsProviderSem.availablePermits()
- + "/" + registeredCallbackCount + " : " + e);
- }
- Trace.traceEnd(TRACE_TAG_NETWORK);
- }
-
- /**
- * Sample recent statistics summary into {@link EventLog}.
- */
- @GuardedBy("mStatsLock")
- private void performSampleLocked() {
- // TODO: migrate trustedtime fixes to separate binary log events
- final long currentTime = mClock.millis();
-
- NetworkTemplate template;
- NetworkStats.Entry devTotal;
- NetworkStats.Entry xtTotal;
- NetworkStats.Entry uidTotal;
-
- // collect mobile sample
- template = buildTemplateMobileWildcard();
- devTotal = mDevRecorder.getTotalSinceBootLocked(template);
- xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
- uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
-
- EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
- devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
- xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
- uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- currentTime);
-
- // collect wifi sample
- template = buildTemplateWifiWildcard();
- devTotal = mDevRecorder.getTotalSinceBootLocked(template);
- xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
- uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
-
- EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
- devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
- xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
- uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- currentTime);
- }
-
- // deleteKernelTagData can ignore ENOENT; otherwise we should log an error
- private void logErrorIfNotErrNoent(final ErrnoException e, final String msg) {
- if (e.errno != ENOENT) Log.e(TAG, msg, e);
- }
-
- private <K extends StatsMapKey, V extends StatsMapValue> void deleteStatsMapTagData(
- IBpfMap<K, V> statsMap, int uid) {
- try {
- statsMap.forEach((key, value) -> {
- if (key.uid == uid) {
- try {
- statsMap.deleteEntry(key);
- } catch (ErrnoException e) {
- logErrorIfNotErrNoent(e, "Failed to delete data(uid = " + key.uid + ")");
- }
- }
- });
- } catch (ErrnoException e) {
- Log.e(TAG, "FAILED to delete tag data from stats map", e);
- }
- }
-
- /**
- * Deletes uid tag data from CookieTagMap, StatsMapA, StatsMapB, and UidStatsMap
- * @param uid
- */
- private void deleteKernelTagData(int uid) {
- try {
- mCookieTagMap.forEach((key, value) -> {
- // If SkDestroyListener deletes the socket tag while this code is running,
- // forEach will either restart iteration from the beginning or return null,
- // depending on when the deletion happens.
- // If it returns null, continue iteration to delete the data and in fact it would
- // just iterate from first key because BpfMap#getNextKey would return first key
- // if the current key is not exist.
- if (value != null && value.uid == uid) {
- try {
- mCookieTagMap.deleteEntry(key);
- } catch (ErrnoException e) {
- logErrorIfNotErrNoent(e, "Failed to delete data(cookie = " + key + ")");
- }
- }
- });
- } catch (ErrnoException e) {
- Log.e(TAG, "Failed to delete tag data from cookie tag map", e);
- }
-
- deleteStatsMapTagData(mStatsMapA, uid);
- deleteStatsMapTagData(mStatsMapB, uid);
-
- try {
- mUidCounterSetMap.deleteEntry(new U32(uid));
- } catch (ErrnoException e) {
- logErrorIfNotErrNoent(e, "Failed to delete tag data from uid counter set map");
- }
-
- try {
- mAppUidStatsMap.deleteEntry(new UidStatsMapKey(uid));
- } catch (ErrnoException e) {
- logErrorIfNotErrNoent(e, "Failed to delete tag data from app uid stats map");
- }
- }
-
- /**
- * Clean up {@link #mUidRecorder} after UID is removed.
- */
- @GuardedBy("mStatsLock")
- private void removeUidsLocked(int... uids) {
- if (LOGV) Log.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
-
- // Perform one last poll before removing
- performPollLocked(FLAG_PERSIST_ALL);
-
- mUidRecorder.removeUidsLocked(uids);
- mUidTagRecorder.removeUidsLocked(uids);
-
- // Clear kernel stats associated with UID
- for (int uid : uids) {
- deleteKernelTagData(uid);
- }
- }
-
- /**
- * Clean up {@link #mUidRecorder} after user is removed.
- */
- @GuardedBy("mStatsLock")
- private void removeUserLocked(@NonNull UserHandle userHandle) {
- if (LOGV) Log.v(TAG, "removeUserLocked() for UserHandle=" + userHandle);
-
- // Build list of UIDs that we should clean up
- 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(app.uid);
- uids.add(uid);
- }
-
- removeUidsLocked(CollectionUtils.toIntArray(uids));
- }
-
- /**
- * Set the warning and limit to all registered custom network stats providers.
- * Note that invocation of any interface will be sent to all providers.
- */
- public void setStatsProviderWarningAndLimitAsync(
- @NonNull String iface, long warning, long limit) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (LOGV) {
- Log.v(TAG, "setStatsProviderWarningAndLimitAsync("
- + iface + "," + warning + "," + limit + ")");
- }
- invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
- warning, limit));
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
- if (!PermissionUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
-
- long duration = DateUtils.DAY_IN_MILLIS;
- final HashSet<String> argSet = new HashSet<String>();
- for (String arg : args) {
- argSet.add(arg);
-
- if (arg.startsWith("--duration=")) {
- try {
- duration = Long.parseLong(arg.substring(11));
- } catch (NumberFormatException ignored) {
- }
- }
- }
-
- // usage: dumpsys netstats --full --uid --tag --poll --checkin
- final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
- final boolean checkin = argSet.contains("--checkin");
- final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
- final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
- final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
-
- final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " ");
-
- synchronized (mStatsLock) {
- if (args.length > 0 && "--proto".equals(args[0])) {
- // In this case ignore all other arguments.
- dumpProtoLocked(fd);
- return;
- }
-
- if (poll) {
- performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
- pw.println("Forced poll");
- return;
- }
-
- if (checkin) {
- final long end = System.currentTimeMillis();
- final long start = end - duration;
-
- pw.print("v1,");
- pw.print(start / SECOND_IN_MILLIS); pw.print(',');
- pw.print(end / SECOND_IN_MILLIS); pw.println();
-
- pw.println("xt");
- mXtRecorder.dumpCheckin(rawWriter, start, end);
-
- if (includeUid) {
- pw.println("uid");
- mUidRecorder.dumpCheckin(rawWriter, start, end);
- }
- if (includeTag) {
- pw.println("tag");
- mUidTagRecorder.dumpCheckin(rawWriter, start, end);
- }
- return;
- }
-
- pw.println("Configs:");
- pw.increaseIndent();
- 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.print("iface", mActiveIfaces.keyAt(i));
- pw.print("ident", mActiveIfaces.valueAt(i));
- pw.println();
- }
- pw.decreaseIndent();
-
- pw.println("Active UID interfaces:");
- pw.increaseIndent();
- for (int i = 0; i < mActiveUidIfaces.size(); i++) {
- pw.print("iface", mActiveUidIfaces.keyAt(i));
- pw.print("ident", mActiveUidIfaces.valueAt(i));
- pw.println();
- }
- pw.decreaseIndent();
-
- // Get the top openSession callers
- final SparseIntArray calls;
- synchronized (mOpenSessionCallsPerUid) {
- calls = mOpenSessionCallsPerUid.clone();
- }
-
- final int N = calls.size();
- final long[] values = new long[N];
- for (int j = 0; j < N; j++) {
- values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
- }
- Arrays.sort(values);
-
- pw.println("Top openSession callers (uid=count):");
- pw.increaseIndent();
- final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
- for (int j = N - 1; j >= end; j--) {
- final int uid = (int) (values[j] & 0xffffffff);
- final int count = (int) (values[j] >> 32);
- pw.print(uid); pw.print("="); pw.println(count);
- }
- pw.decreaseIndent();
- pw.println();
-
- pw.println("Stats Providers:");
- pw.increaseIndent();
- invokeForAllStatsProviderCallbacks((cb) -> {
- pw.println(cb.mTag + " Xt:");
- pw.increaseIndent();
- pw.print(cb.getCachedStats(STATS_PER_IFACE).toString());
- pw.decreaseIndent();
- if (includeUid) {
- pw.println(cb.mTag + " Uid:");
- pw.increaseIndent();
- pw.print(cb.getCachedStats(STATS_PER_UID).toString());
- pw.decreaseIndent();
- }
- });
- pw.decreaseIndent();
-
- pw.println("Dev stats:");
- pw.increaseIndent();
- mDevRecorder.dumpLocked(pw, fullHistory);
- pw.decreaseIndent();
-
- pw.println("Xt stats:");
- pw.increaseIndent();
- mXtRecorder.dumpLocked(pw, fullHistory);
- pw.decreaseIndent();
-
- if (includeUid) {
- pw.println("UID stats:");
- pw.increaseIndent();
- mUidRecorder.dumpLocked(pw, fullHistory);
- pw.decreaseIndent();
- }
-
- if (includeTag) {
- pw.println("UID tag stats:");
- pw.increaseIndent();
- mUidTagRecorder.dumpLocked(pw, fullHistory);
- pw.decreaseIndent();
- }
- }
- }
-
- @GuardedBy("mStatsLock")
- private void dumpProtoLocked(FileDescriptor fd) {
- final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd));
-
- // TODO Right now it writes all history. Should it limit to the "since-boot" log?
-
- dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES_FIELD_NUMBER,
- mActiveIfaces);
- dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES_FIELD_NUMBER,
- mActiveUidIfaces);
- mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS_FIELD_NUMBER);
- mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS_FIELD_NUMBER);
- mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS_FIELD_NUMBER);
- mUidTagRecorder.dumpDebugLocked(proto,
- NetworkStatsServiceDumpProto.UID_TAG_STATS_FIELD_NUMBER);
-
- proto.flush();
- }
-
- private static void dumpInterfaces(ProtoOutputStream proto, long tag,
- ArrayMap<String, NetworkIdentitySet> ifaces) {
- for (int i = 0; i < ifaces.size(); i++) {
- final long start = proto.start(tag);
-
- proto.write(NetworkInterfaceProto.INTERFACE_FIELD_NUMBER, ifaces.keyAt(i));
- ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES_FIELD_NUMBER);
-
- proto.end(start);
- }
- }
-
- private NetworkStats readNetworkStatsSummaryDev() {
- try {
- return mStatsFactory.readNetworkStatsSummaryDev();
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private NetworkStats readNetworkStatsSummaryXt() {
- try {
- return mStatsFactory.readNetworkStatsSummaryXt();
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private NetworkStats readNetworkStatsUidDetail(int uid, String[] ifaces, int tag) {
- try {
- return mStatsFactory.readNetworkStatsDetail(uid, ifaces, tag);
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- /**
- * Return snapshot of current UID statistics, including any
- * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations}
- * values.
- *
- * @param ifaces A list of interfaces the stats should be restricted to, or
- * {@link NetworkStats#INTERFACES_ALL}.
- */
- private NetworkStats getNetworkStatsUidDetail(String[] ifaces)
- throws RemoteException {
- final NetworkStats uidSnapshot = readNetworkStatsUidDetail(UID_ALL, ifaces, TAG_ALL);
-
- // fold tethering stats and operations into uid snapshot
- final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
- tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
- mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
- uidSnapshot.combineAllValues(tetherSnapshot);
-
- // get a stale copy of uid stats snapshot provided by providers.
- final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID);
- providerStats.filter(UID_ALL, ifaces, TAG_ALL);
- mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats);
- uidSnapshot.combineAllValues(providerStats);
-
- uidSnapshot.combineAllValues(mUidOperations);
-
- return uidSnapshot;
- }
-
- /**
- * Return snapshot of current non-offloaded tethering statistics. Will return empty
- * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE}
- * since it is already included by {@link #nativeGetIfaceStat}.
- * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats.
- */
- // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
- // tethering stats.
- private @NonNull NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
- // We only need to return per-UID stats. Per-device stats are already counted by
- // interface counters.
- if (how != STATS_PER_UID) {
- return new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
-
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- try {
- final TetherStatsParcel[] tetherStatsParcels = mNetd.tetherGetStats();
- for (TetherStatsParcel tetherStats : tetherStatsParcels) {
- try {
- stats.combineValues(new NetworkStats.Entry(tetherStats.iface, UID_TETHERING,
- SET_DEFAULT, TAG_NONE, tetherStats.rxBytes, tetherStats.rxPackets,
- tetherStats.txBytes, tetherStats.txPackets, 0L));
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalStateException("invalid tethering stats " + e);
- }
- }
- } catch (IllegalStateException e) {
- Log.wtf(TAG, "problem reading network stats", e);
- }
- return stats;
- }
-
- // TODO: It is copied from ConnectivityService, consider refactor these check permission
- // functions to a proper util.
- private boolean checkAnyPermissionOf(String... permissions) {
- for (String permission : permissions) {
- if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
- return true;
- }
- }
- return false;
- }
-
- private void enforceAnyPermissionOf(String... permissions) {
- if (!checkAnyPermissionOf(permissions)) {
- throw new SecurityException("Requires one of the following permissions: "
- + String.join(", ", permissions) + ".");
- }
- }
-
- /**
- * Registers a custom provider of {@link android.net.NetworkStats} to combine the network
- * statistics that cannot be seen by the kernel to system. To unregister, invoke the
- * {@code unregister()} of the returned callback.
- *
- * @param tag a human readable identifier of the custom network stats provider.
- * @param provider the {@link INetworkStatsProvider} binder corresponding to the
- * {@link NetworkStatsProvider} to be registered.
- *
- * @return a {@link INetworkStatsProviderCallback} binder
- * interface, which can be used to report events to the system.
- */
- public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
- @NonNull String tag, @NonNull INetworkStatsProvider provider) {
- enforceAnyPermissionOf(NETWORK_STATS_PROVIDER,
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
- Objects.requireNonNull(provider, "provider is null");
- Objects.requireNonNull(tag, "tag is null");
- final NetworkPolicyManager netPolicyManager = mContext
- .getSystemService(NetworkPolicyManager.class);
- try {
- NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
- tag, provider, mStatsProviderSem, mAlertObserver,
- mStatsProviderCbList, netPolicyManager);
- mStatsProviderCbList.add(callback);
- Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
- + getCallingUid() + "/" + getCallingPid());
- return callback;
- } catch (RemoteException e) {
- Log.e(TAG, "registerNetworkStatsProvider failed", e);
- }
- return null;
- }
-
- // Collect stats from local cache of providers.
- private @NonNull NetworkStats getNetworkStatsFromProviders(int how) {
- final NetworkStats ret = new NetworkStats(0L, 0);
- invokeForAllStatsProviderCallbacks((cb) -> ret.combineAllValues(cb.getCachedStats(how)));
- return ret;
- }
-
- @FunctionalInterface
- private interface ThrowingConsumer<S, T extends Throwable> {
- void accept(S s) throws T;
- }
-
- private void invokeForAllStatsProviderCallbacks(
- @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) {
- for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) {
- try {
- task.accept(cb);
- } catch (RemoteException e) {
- Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e);
- }
- }
- }
-
- private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub
- implements IBinder.DeathRecipient {
- @NonNull final String mTag;
-
- @NonNull final INetworkStatsProvider mProvider;
- @NonNull private final Semaphore mSemaphore;
- @NonNull final AlertObserver mAlertObserver;
- @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
- @NonNull final NetworkPolicyManager mNetworkPolicyManager;
-
- @NonNull private final Object mProviderStatsLock = new Object();
-
- @GuardedBy("mProviderStatsLock")
- // Track STATS_PER_IFACE and STATS_PER_UID separately.
- private final NetworkStats mIfaceStats = new NetworkStats(0L, 0);
- @GuardedBy("mProviderStatsLock")
- private final NetworkStats mUidStats = new NetworkStats(0L, 0);
-
- NetworkStatsProviderCallbackImpl(
- @NonNull String tag, @NonNull INetworkStatsProvider provider,
- @NonNull Semaphore semaphore,
- @NonNull AlertObserver alertObserver,
- @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList,
- @NonNull NetworkPolicyManager networkPolicyManager)
- throws RemoteException {
- mTag = tag;
- mProvider = provider;
- mProvider.asBinder().linkToDeath(this, 0);
- mSemaphore = semaphore;
- mAlertObserver = alertObserver;
- mStatsProviderCbList = cbList;
- mNetworkPolicyManager = networkPolicyManager;
- }
-
- @NonNull
- public NetworkStats getCachedStats(int how) {
- synchronized (mProviderStatsLock) {
- NetworkStats stats;
- switch (how) {
- case STATS_PER_IFACE:
- stats = mIfaceStats;
- break;
- case STATS_PER_UID:
- stats = mUidStats;
- break;
- default:
- throw new IllegalArgumentException("Invalid type: " + how);
- }
- // Callers might be able to mutate the returned object. Return a defensive copy
- // instead of local reference.
- return stats.clone();
- }
- }
-
- @Override
- public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
- @Nullable NetworkStats uidStats) {
- // TODO: 1. Use token to map ifaces to correct NetworkIdentity.
- // 2. Store the difference and store it directly to the recorder.
- synchronized (mProviderStatsLock) {
- if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats);
- if (uidStats != null) mUidStats.combineAllValues(uidStats);
- }
- mSemaphore.release();
- }
-
- @Override
- public void notifyAlertReached() throws RemoteException {
- // 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.onQuotaLimitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
- }
-
- @Override
- public void notifyWarningReached() {
- Log.d(TAG, mTag + ": notifyWarningReached");
- BinderUtils.withCleanCallingIdentity(() ->
- mNetworkPolicyManager.notifyStatsProviderWarningReached());
- }
-
- @Override
- public void notifyLimitReached() {
- Log.d(TAG, mTag + ": notifyLimitReached");
- BinderUtils.withCleanCallingIdentity(() ->
- mNetworkPolicyManager.notifyStatsProviderLimitReached());
- }
-
- @Override
- public void binderDied() {
- Log.d(TAG, mTag + ": binderDied");
- mStatsProviderCbList.remove(this);
- }
-
- @Override
- public void unregister() {
- Log.d(TAG, mTag + ": unregister");
- mStatsProviderCbList.remove(this);
- }
-
- }
-
- private void assertSystemReady() {
- if (!mSystemReady) {
- throw new IllegalStateException("System not ready");
- }
- }
-
- private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
- @Override
- public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
- int rightIndex, String cookie) {
- Log.w(TAG, "Found non-monotonic values; saving to dropbox");
-
- // record error for debugging
- final StringBuilder builder = new StringBuilder();
- builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
- + "] - right[" + rightIndex + "]\n");
- builder.append("left=").append(left).append('\n');
- builder.append("right=").append(right).append('\n');
-
- mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
- builder.toString());
- }
-
- @Override
- public void foundNonMonotonic(
- NetworkStats stats, int statsIndex, String cookie) {
- Log.w(TAG, "Found non-monotonic values; saving to dropbox");
-
- final StringBuilder builder = new StringBuilder();
- builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
- builder.append("stats=").append(stats).append('\n');
-
- mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
- builder.toString());
- }
- }
-
- /**
- * Default external settings that read from
- * {@link android.provider.Settings.Global}.
- */
- private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
- DefaultNetworkStatsSettings() {}
-
- @Override
- public long getPollInterval() {
- return 30 * MINUTE_IN_MILLIS;
- }
- @Override
- public long getPollDelay() {
- return DEFAULT_PERFORM_POLL_DELAY_MS;
- }
- @Override
- public long getGlobalAlertBytes(long def) {
- return def;
- }
- @Override
- public boolean getSampleEnabled() {
- return true;
- }
- @Override
- public boolean getAugmentEnabled() {
- return true;
- }
- @Override
- public boolean getCombineSubtypeEnabled() {
- return false;
- }
- @Override
- public Config getDevConfig() {
- return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
- }
- @Override
- public Config getXtConfig() {
- return getDevConfig();
- }
- @Override
- public Config getUidConfig() {
- return new Config(2 * HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
- }
- @Override
- public Config getUidTagConfig() {
- return new Config(2 * HOUR_IN_MILLIS, 5 * DAY_IN_MILLIS, 15 * DAY_IN_MILLIS);
- }
- @Override
- public long getDevPersistBytes(long def) {
- return def;
- }
- @Override
- public long getXtPersistBytes(long def) {
- return def;
- }
- @Override
- public long getUidPersistBytes(long def) {
- return def;
- }
- @Override
- public long getUidTagPersistBytes(long def) {
- return def;
- }
- }
-
- 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/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
deleted file mode 100644
index 65ccd20..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.server.net;
-
-import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA;
-import static android.app.usage.NetworkStatsManager.getCollapsedRatType;
-import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
-import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
-
-import android.annotation.NonNull;
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyCallback;
-import android.telephony.TelephonyDisplayInfo;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-
-/**
- * Helper class that watches for events that are triggered per subscription.
- */
-@TargetApi(Build.VERSION_CODES.TIRAMISU)
-public class NetworkStatsSubscriptionsMonitor extends
- SubscriptionManager.OnSubscriptionsChangedListener {
-
- /**
- * Interface that this monitor uses to delegate event handling to NetworkStatsService.
- */
- public interface Delegate {
- /**
- * Notify that the collapsed RAT type has been changed for any subscription. The method
- * will also be triggered for any existing sub when start and stop monitoring.
- *
- * @param subscriberId IMSI of the subscription.
- * @param collapsedRatType collapsed RAT type.
- * @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int).
- */
- void onCollapsedRatTypeChanged(@NonNull String subscriberId, int collapsedRatType);
- }
- private final Delegate mDelegate;
-
- /**
- * Receivers that watches for {@link TelephonyDisplayInfo} changes for each subscription, to
- * monitor the transitioning between Radio Access Technology(RAT) types for each sub.
- */
- @NonNull
- private final CopyOnWriteArrayList<RatTypeListener> mRatListeners =
- new CopyOnWriteArrayList<>();
-
- @NonNull
- private final SubscriptionManager mSubscriptionManager;
- @NonNull
- private final TelephonyManager mTeleManager;
-
- @NonNull
- private final Executor mExecutor;
-
- NetworkStatsSubscriptionsMonitor(@NonNull Context context,
- @NonNull Executor executor, @NonNull Delegate delegate) {
- super();
- mSubscriptionManager = (SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mExecutor = executor;
- mDelegate = delegate;
- }
-
- @Override
- public void onSubscriptionsChanged() {
- // Collect active subId list, hidden subId such as opportunistic subscriptions are
- // also needed to track CBRS.
- final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
-
- // IMSI is needed for every newly added sub. Listener stores subscriberId into it to
- // 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 = 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.any(mRatListeners, it -> it.equalsKey(sub.first, sub.second))) {
- continue;
- }
-
- final RatTypeListener listener = new RatTypeListener(this, sub.first, sub.second);
- mRatListeners.add(listener);
-
- // Register listener to the telephony manager that associated with specific sub.
- mTeleManager.createForSubscriptionId(sub.first)
- .registerTelephonyCallback(mExecutor, listener);
- Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
- }
-
- for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
- // If there is no subId and IMSI matched the listener, removes it.
- if (!CollectionUtils.any(filteredNewSubs,
- it -> listener.equalsKey(it.first, it.second))) {
- handleRemoveRatTypeListener(listener);
- }
- }
- }
-
- @NonNull
- private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) {
- final ArrayList<Integer> ret = new ArrayList<>();
- final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList();
- for (int id : ids) ret.add(id);
- return ret;
- }
-
- /**
- * Get a collapsed RatType for the given subscriberId.
- *
- * @param subscriberId the target subscriberId
- * @return collapsed RatType for the given subscriberId
- */
- public int getRatTypeForSubscriberId(@NonNull String subscriberId) {
- final int index = CollectionUtils.indexOf(mRatListeners,
- it -> TextUtils.equals(subscriberId, it.mSubscriberId));
- return index != -1 ? mRatListeners.get(index).mLastCollapsedRatType
- : TelephonyManager.NETWORK_TYPE_UNKNOWN;
- }
-
- /**
- * Start monitoring events that triggered per subscription.
- */
- public void start() {
- mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this);
- }
-
- /**
- * Unregister subscription changes and all listeners for each subscription.
- */
- public void stop() {
- mSubscriptionManager.removeOnSubscriptionsChangedListener(this);
-
- for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
- handleRemoveRatTypeListener(listener);
- }
- }
-
- private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
- mTeleManager.createForSubscriptionId(listener.mSubId)
- .unregisterTelephonyCallback(listener);
- Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
- mRatListeners.remove(listener);
-
- // Removal of subscriptions doesn't generate RAT changed event, fire it for every
- // RatTypeListener.
- mDelegate.onCollapsedRatTypeChanged(
- listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN);
- }
-
- static class RatTypeListener extends TelephonyCallback
- implements TelephonyCallback.DisplayInfoListener {
- // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}.
- @NonNull
- private final int mSubId;
-
- // IMSI to identifying the corresponding network from {@link NetworkState}.
- // See {@link TelephonyManager#getSubscriberId}.
- @NonNull
- private final String mSubscriberId;
-
- private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- @NonNull
- private final NetworkStatsSubscriptionsMonitor mMonitor;
-
- RatTypeListener(@NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
- @NonNull String subscriberId) {
- mSubId = subId;
- mSubscriberId = subscriberId;
- mMonitor = monitor;
- }
-
- @Override
- public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
- // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony
- // would report RAT = 5G_NR.
- // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and
- // network allocates a secondary 5G cell so telephony reports RAT = LTE along with
- // NR state as connected. In such case, attributes the data usage to NR.
- // See b/160727498.
- final boolean is5GNsa = displayInfo.getNetworkType() == NETWORK_TYPE_LTE
- && (displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_NSA
- || displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
-
- final int networkType =
- (is5GNsa ? NETWORK_TYPE_5G_NSA : displayInfo.getNetworkType());
- final int collapsedRatType = getCollapsedRatType(networkType);
- if (collapsedRatType == mLastCollapsedRatType) return;
-
- if (NetworkStatsService.LOGD) {
- Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): "
- + mLastCollapsedRatType + " -> " + collapsedRatType);
- }
- mLastCollapsedRatType = collapsedRatType;
- mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType);
- }
-
- @VisibleForTesting
- public int getSubId() {
- return mSubId;
- }
-
- boolean equalsKey(int subId, @NonNull String subscriberId) {
- return mSubId == subId && TextUtils.equals(mSubscriberId, subscriberId);
- }
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
deleted file mode 100644
index ea8d8363..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Key for both stats maps.
- */
-public class StatsMapKey extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long uid;
-
- @Field(order = 1, type = Type.U32)
- public final long tag;
-
- @Field(order = 2, type = Type.U32)
- public final long counterSet;
-
- @Field(order = 3, type = Type.U32)
- public final long ifaceIndex;
-
- public StatsMapKey(final long uid, final long tag, final long counterSet,
- final long ifaceIndex) {
- this.uid = uid;
- this.tag = tag;
- this.counterSet = counterSet;
- this.ifaceIndex = ifaceIndex;
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
deleted file mode 100644
index 48f26ce..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Value used for both stats maps and uid stats map.
- */
-public class StatsMapValue extends Struct {
- @Field(order = 0, type = Type.U63)
- public final long rxPackets;
-
- @Field(order = 1, type = Type.U63)
- public final long rxBytes;
-
- @Field(order = 2, type = Type.U63)
- public final long txPackets;
-
- @Field(order = 3, type = Type.U63)
- public final long txBytes;
-
- public StatsMapValue(final long rxPackets, final long rxBytes, final long txPackets,
- final long txBytes) {
- this.rxPackets = rxPackets;
- this.rxBytes = rxBytes;
- this.txPackets = txPackets;
- this.txBytes = txBytes;
- }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
deleted file mode 100644
index 2849f94..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Key for uid stats map.
- */
-public class UidStatsMapKey extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long uid;
-
- public UidStatsMapKey(final long uid) {
- this.uid = uid;
- }
-}
diff --git a/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
deleted file mode 100644
index e2253a2..0000000
--- a/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
+++ /dev/null
@@ -1,97 +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 com.android.server;
-
-import static com.android.server.NativeDaemonConnector.appendEscaped;
-import static com.android.server.NativeDaemonConnector.makeCommand;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.server.NativeDaemonConnector.SensitiveArg;
-
-/**
- * Tests for {@link NativeDaemonConnector}.
- */
-@MediumTest
-public class NativeDaemonConnectorTest extends AndroidTestCase {
- private static final String TAG = "NativeDaemonConnectorTest";
-
- public void testArgumentNormal() throws Exception {
- final StringBuilder builder = new StringBuilder();
-
- builder.setLength(0);
- appendEscaped(builder, "");
- assertEquals("", builder.toString());
-
- builder.setLength(0);
- appendEscaped(builder, "foo");
- assertEquals("foo", builder.toString());
-
- builder.setLength(0);
- appendEscaped(builder, "foo\"bar");
- assertEquals("foo\\\"bar", builder.toString());
-
- builder.setLength(0);
- appendEscaped(builder, "foo\\bar\\\"baz");
- assertEquals("foo\\\\bar\\\\\\\"baz", builder.toString());
- }
-
- public void testArgumentWithSpaces() throws Exception {
- final StringBuilder builder = new StringBuilder();
-
- builder.setLength(0);
- appendEscaped(builder, "foo bar");
- assertEquals("\"foo bar\"", builder.toString());
-
- builder.setLength(0);
- appendEscaped(builder, "foo\"bar\\baz foo");
- assertEquals("\"foo\\\"bar\\\\baz foo\"", builder.toString());
- }
-
- public void testArgumentWithUtf() throws Exception {
- final StringBuilder builder = new StringBuilder();
-
- builder.setLength(0);
- appendEscaped(builder, "caf\u00E9 c\u00F6ffee");
- assertEquals("\"caf\u00E9 c\u00F6ffee\"", builder.toString());
- }
-
- public void testSensitiveArgs() throws Exception {
- final StringBuilder rawBuilder = new StringBuilder();
- final StringBuilder logBuilder = new StringBuilder();
-
- rawBuilder.setLength(0);
- logBuilder.setLength(0);
- makeCommand(rawBuilder, logBuilder, 1, "foo", "bar", "baz");
- assertEquals("1 foo bar baz\0", rawBuilder.toString());
- assertEquals("1 foo bar baz", logBuilder.toString());
-
- rawBuilder.setLength(0);
- logBuilder.setLength(0);
- makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("bar"), "baz");
- assertEquals("1 foo bar baz\0", rawBuilder.toString());
- assertEquals("1 foo [scrubbed] baz", logBuilder.toString());
-
- rawBuilder.setLength(0);
- logBuilder.setLength(0);
- makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("foo bar"), "baz baz",
- new SensitiveArg("wat"));
- assertEquals("1 foo \"foo bar\" \"baz baz\" wat\0", rawBuilder.toString());
- assertEquals("1 foo [scrubbed] \"baz baz\" [scrubbed]", logBuilder.toString());
- }
-}
diff --git a/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
deleted file mode 100644
index ad0be58..0000000
--- a/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.net;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import android.net.InetAddresses;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.ProxyInfo;
-import android.net.StaticIpConfiguration;
-import android.util.ArrayMap;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Unit tests for {@link IpConfigStore}
- */
-@RunWith(AndroidJUnit4.class)
-public class IpConfigStoreTest {
- private static final int KEY_CONFIG = 17;
- private static final String IFACE_1 = "eth0";
- private static final String IFACE_2 = "eth1";
- private static final String IP_ADDR_1 = "192.168.1.10/24";
- private static final String IP_ADDR_2 = "192.168.1.20/24";
- private static final String DNS_IP_ADDR_1 = "1.2.3.4";
- private static final String DNS_IP_ADDR_2 = "5.6.7.8";
-
- @Test
- public void backwardCompatibility2to3() throws IOException {
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- DataOutputStream outputStream = new DataOutputStream(byteStream);
-
- final IpConfiguration expectedConfig =
- newIpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
-
- // Emulate writing to old format.
- writeDhcpConfigV2(outputStream, KEY_CONFIG, expectedConfig);
-
- InputStream in = new ByteArrayInputStream(byteStream.toByteArray());
- ArrayMap<String, IpConfiguration> configurations = IpConfigStore.readIpConfigurations(in);
-
- assertNotNull(configurations);
- assertEquals(1, configurations.size());
- IpConfiguration actualConfig = configurations.get(String.valueOf(KEY_CONFIG));
- assertNotNull(actualConfig);
- assertEquals(expectedConfig, actualConfig);
- }
-
- @Test
- public void staticIpMultiNetworks() throws Exception {
- final ArrayList<InetAddress> dnsServers = new ArrayList<>();
- dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1));
- dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2));
- final StaticIpConfiguration staticIpConfiguration1 = new StaticIpConfiguration.Builder()
- .setIpAddress(new LinkAddress(IP_ADDR_1))
- .setDnsServers(dnsServers).build();
- final StaticIpConfiguration staticIpConfiguration2 = new StaticIpConfiguration.Builder()
- .setIpAddress(new LinkAddress(IP_ADDR_2))
- .setDnsServers(dnsServers).build();
-
- ProxyInfo proxyInfo =
- ProxyInfo.buildDirectProxy("10.10.10.10", 88, Arrays.asList("host1", "host2"));
-
- IpConfiguration expectedConfig1 = newIpConfiguration(IpAssignment.STATIC,
- ProxySettings.STATIC, staticIpConfiguration1, proxyInfo);
- IpConfiguration expectedConfig2 = newIpConfiguration(IpAssignment.STATIC,
- ProxySettings.STATIC, staticIpConfiguration2, proxyInfo);
-
- ArrayMap<String, IpConfiguration> expectedNetworks = new ArrayMap<>();
- expectedNetworks.put(IFACE_1, expectedConfig1);
- expectedNetworks.put(IFACE_2, expectedConfig2);
-
- MockedDelayedDiskWrite writer = new MockedDelayedDiskWrite();
- IpConfigStore store = new IpConfigStore(writer);
- store.writeIpConfigurations("file/path/not/used/", expectedNetworks);
-
- InputStream in = new ByteArrayInputStream(writer.byteStream.toByteArray());
- ArrayMap<String, IpConfiguration> actualNetworks = IpConfigStore.readIpConfigurations(in);
- assertNotNull(actualNetworks);
- assertEquals(2, actualNetworks.size());
- assertEquals(expectedNetworks.get(IFACE_1), actualNetworks.get(IFACE_1));
- assertEquals(expectedNetworks.get(IFACE_2), actualNetworks.get(IFACE_2));
- }
-
- private IpConfiguration newIpConfiguration(IpAssignment ipAssignment,
- ProxySettings proxySettings, StaticIpConfiguration staticIpConfig, ProxyInfo info) {
- final IpConfiguration config = new IpConfiguration();
- config.setIpAssignment(ipAssignment);
- config.setProxySettings(proxySettings);
- config.setStaticIpConfiguration(staticIpConfig);
- config.setHttpProxy(info);
- return config;
- }
-
- // This is simplified snapshot of code that was used to store values in V2 format (key as int).
- private static void writeDhcpConfigV2(DataOutputStream out, int configKey,
- IpConfiguration config) throws IOException {
- out.writeInt(2); // VERSION 2
- switch (config.getIpAssignment()) {
- case DHCP:
- out.writeUTF("ipAssignment");
- out.writeUTF(config.getIpAssignment().toString());
- break;
- default:
- fail("Not supported in test environment");
- }
-
- out.writeUTF("id");
- out.writeInt(configKey);
- out.writeUTF("eos");
- }
-
- /** Synchronously writes into given byte steam */
- private static class MockedDelayedDiskWrite extends DelayedDiskWrite {
- final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
-
- @Override
- public void write(String filePath, Writer w) {
- DataOutputStream outputStream = new DataOutputStream(mByteStream);
-
- try {
- w.onWriteCalled(outputStream);
- } catch (IOException e) {
- fail();
- }
- }
- }
-}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index b439f84..998aeeab 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -23,9 +23,11 @@
import android.os.Build;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.os.image.DynamicSystemManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Log;
+import android.util.Range;
import android.webkit.URLUtil;
import org.json.JSONException;
@@ -48,7 +50,12 @@
private static final String TAG = "InstallationAsyncTask";
- private static final int READ_BUFFER_SIZE = 1 << 13;
+ private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB
+ private static final int MAX_SHARED_MEMORY_SIZE = 1024 << 10; // 1MiB
+ private static final int DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB
+ private static final String SHARED_MEMORY_SIZE_PROP =
+ "dynamic_system.data_transfer.shared_memory.size";
+
private static final long MIN_PROGRESS_TO_PUBLISH = 1 << 27;
private static final List<String> UNSUPPORTED_PARTITIONS =
@@ -131,6 +138,7 @@
void onResult(int resultCode, Throwable detail);
}
+ private final int mSharedMemorySize;
private final String mUrl;
private final String mDsuSlot;
private final String mPublicKey;
@@ -164,6 +172,11 @@
Context context,
DynamicSystemManager dynSystem,
ProgressListener listener) {
+ mSharedMemorySize =
+ Range.create(MIN_SHARED_MEMORY_SIZE, MAX_SHARED_MEMORY_SIZE)
+ .clamp(
+ SystemProperties.getInt(
+ SHARED_MEMORY_SIZE_PROP, DEFAULT_SHARED_MEMORY_SIZE));
mUrl = url;
mDsuSlot = dsuSlot;
mPublicKey = publicKey;
@@ -541,10 +554,10 @@
Log.d(TAG, "Start installing: " + partitionName);
- MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, READ_BUFFER_SIZE);
+ MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, mSharedMemorySize);
ParcelFileDescriptor pfd = new ParcelFileDescriptor(memoryFile.getFileDescriptor());
- mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE);
+ mInstallationSession.setAshmem(pfd, memoryFile.length());
mPartitionName = partitionName;
mPartitionSize = partitionSize;
@@ -553,10 +566,10 @@
long prevInstalledSize = 0;
long installedSize = 0;
- byte[] bytes = new byte[READ_BUFFER_SIZE];
+ byte[] bytes = new byte[memoryFile.length()];
int numBytesRead;
- while ((numBytesRead = sis.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {
+ while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) {
if (isCancelled()) {
return;
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
index 4117d0f..7d23266 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -133,36 +133,32 @@
return mLeft == 0;
}
- /**
- * It overrides the InputStream.read(byte[] buf)
- */
- public int read(byte[] buf) throws IOException {
+ @Override
+ public int read(byte[] buf, int off, int len) throws IOException {
if (!mIsSparse) {
- return mIn.read(buf);
+ return mIn.read(buf, off, len);
}
if (prepareChunk()) return -1;
int n = -1;
switch (mCur.mChunkType) {
case SparseChunk.RAW:
- n = mIn.read(buf, 0, (int) min(mLeft, buf.length));
+ n = mIn.read(buf, off, (int) min(mLeft, len));
mLeft -= n;
return n;
case SparseChunk.DONTCARE:
- n = (int) min(mLeft, buf.length);
- Arrays.fill(buf, 0, n - 1, (byte) 0);
+ n = (int) min(mLeft, len);
+ Arrays.fill(buf, off, off + n, (byte) 0);
mLeft -= n;
return n;
case SparseChunk.FILL:
// The FILL type is rarely used, so use a simple implmentation.
- return super.read(buf);
+ return super.read(buf, off, len);
default:
throw new IOException("Unsupported Chunk:" + mCur.toString());
}
}
- /**
- * It overrides the InputStream.read()
- */
+ @Override
public int read() throws IOException {
if (!mIsSparse) {
return mIn.read();
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 8323e32..6c8a92d 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -72,6 +72,7 @@
xuqiu@google.com
zakcohen@google.com
jernej@google.com
+jglazier@google.com
#Android Auto
hseog@google.com
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e00b941..6f46b70 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -664,4 +664,17 @@
<!-- Flag to enable privacy dot views, it shall be true for normal case -->
<bool name="config_enablePrivacyDot">true</bool>
+ <!-- Icons that don't show in a collapsed non-keyguard statusbar -->
+ <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false">
+ <item>@*android:string/status_bar_volume</item>
+ <item>@*android:string/status_bar_alarm_clock</item>
+ <item>@*android:string/status_bar_call_strength</item>
+ </string-array>
+
+ <!-- Icons that don't show in a collapsed statusbar on keyguard -->
+ <string-array name="config_keyguard_statusbar_icon_blocklist" translatable="false">
+ <item>@*android:string/status_bar_volume</item>
+ <item>@*android:string/status_bar_alarm_clock</item>
+ <item>@*android:string/status_bar_call_strength</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index e7d5724..810b95b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -263,10 +263,8 @@
);
Resources r = getResources();
- mBlockedIcons = Collections.unmodifiableList(Arrays.asList(
- r.getString(com.android.internal.R.string.status_bar_volume),
- r.getString(com.android.internal.R.string.status_bar_alarm_clock),
- r.getString(com.android.internal.R.string.status_bar_call_strength)));
+ mBlockedIcons = Arrays.asList(r.getStringArray(
+ R.array.config_keyguard_statusbar_icon_blocklist));
mNotificationsHeaderCollideDistance = r.getDimensionPixelSize(
R.dimen.header_notifications_collide_distance);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index d6ba6f3..2670ed8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -69,6 +69,7 @@
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
@@ -190,9 +191,8 @@
}
mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons), mFeatureFlags);
mDarkIconManager.setShouldLog(true);
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_volume));
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
+ mBlockedIcons = Arrays.asList(getResources().getStringArray(
+ R.array.config_collapsed_statusbar_icon_blocklist));
mDarkIconManager.setBlockList(mBlockedIcons);
mStatusBarIconController.addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
diff --git a/services/Android.bp b/services/Android.bp
index e730321..3613c58 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -92,7 +92,6 @@
":services.searchui-sources",
":services.smartspace-sources",
":services.speech-sources",
- ":services.startop.iorap-sources",
":services.systemcaptions-sources",
":services.translation-sources",
":services.texttospeech-sources",
@@ -147,7 +146,6 @@
"services.searchui",
"services.smartspace",
"services.speech",
- "services.startop",
"services.systemcaptions",
"services.translation",
"services.texttospeech",
@@ -200,7 +198,6 @@
" --hide-annotation android.annotation.Hide" +
" --hide InternalClasses" + // com.android.* classes are okay in this interface
// TODO: remove the --hide options below
- " --hide-package com.google.android.startop.iorap" +
" --hide DeprecationMismatch" +
" --hide HiddenTypedefConstant",
visibility: ["//frameworks/base:__subpackages__"],
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 1095ba3..5fed6d3 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -129,14 +129,10 @@
DiskStatsFreeSpaceProto.FOLDER_METADATA);
boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
- boolean blockBased = fileBased ? false : StorageManager.isBlockEncrypted();
if (protoFormat) {
if (fileBased) {
proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
DiskStatsServiceDumpProto.ENCRYPTION_FILE_BASED);
- } else if (blockBased) {
- proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
- DiskStatsServiceDumpProto.ENCRYPTION_FULL_DISK);
} else {
proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
DiskStatsServiceDumpProto.ENCRYPTION_NONE);
diff --git a/services/core/java/com/android/server/SmartStorageMaintIdler.java b/services/core/java/com/android/server/SmartStorageMaintIdler.java
index 2dff72f..8996926 100644
--- a/services/core/java/com/android/server/SmartStorageMaintIdler.java
+++ b/services/core/java/com/android/server/SmartStorageMaintIdler.java
@@ -46,7 +46,7 @@
}
// ... and try again in a next period
scheduleSmartIdlePass(SmartStorageMaintIdler.this,
- StorageManagerService.SMART_IDLE_MAINT_PERIOD);
+ StorageManagerService.sSmartIdleMaintPeriod);
}
};
@@ -70,7 +70,7 @@
/**
* Schedule the smart storage idle maintenance job
*/
- public static void scheduleSmartIdlePass(Context context, int nHours) {
+ public static void scheduleSmartIdlePass(Context context, int nMinutes) {
StorageManagerService ms = StorageManagerService.sSelf;
if ((ms == null) || ms.isPassedLifetimeThresh()) {
return;
@@ -78,7 +78,7 @@
JobScheduler tm = context.getSystemService(JobScheduler.class);
- long nextScheduleTime = TimeUnit.HOURS.toMillis(nHours);
+ long nextScheduleTime = TimeUnit.MINUTES.toMillis(nMinutes);
JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID,
SMART_STORAGE_MAINT_SERVICE);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 9f32888..9e60cf6 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -38,7 +38,6 @@
import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
-import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
import static android.os.storage.OnObbStateChangeListener.MOUNTED;
@@ -333,13 +332,15 @@
@Nullable public static String sMediaStoreAuthorityProcessName;
- // Run period in hour for smart idle maintenance
- static final int SMART_IDLE_MAINT_PERIOD = 1;
+ // Smart idle maintenance running period in minute
+ static volatile int sSmartIdleMaintPeriod = 60;
private final AtomicFile mSettingsFile;
- private final AtomicFile mHourlyWriteFile;
+ private final AtomicFile mWriteRecordFile;
- private static final int MAX_HOURLY_WRITE_RECORDS = 72;
+ // 72 hours (3 days)
+ private static final int MAX_PERIOD_WRITE_RECORD = 72 * 60;
+ private volatile int mMaxWriteRecords;
/**
* Default config values for smart idle maintenance
@@ -347,6 +348,10 @@
*/
// Decide whether smart idle maintenance is enabled or not
private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false;
+ // Run period in minute for smart idle maintenance
+ private static final int DEFAULT_SMART_IDLE_MAINT_PERIOD = 60;
+ private static final int MIN_SMART_IDLE_MAINT_PERIOD = 10;
+ private static final int MAX_SMART_IDLE_MAINT_PERIOD = 24 * 60;
// Storage lifetime percentage threshold to decide to turn off the feature
private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70;
// Minimum required number of dirty + free segments to trigger GC
@@ -369,8 +374,8 @@
private volatile boolean mNeedGC;
private volatile boolean mPassedLifetimeThresh;
- // Tracking storage hourly write amounts
- private volatile int[] mStorageHourlyWrites;
+ // Tracking storage write amounts in one period
+ private volatile int[] mStorageWriteRecords;
/**
* <em>Never</em> hold the lock while performing downcalls into vold, since
@@ -595,12 +600,6 @@
}
}
- /** List of crypto types.
- * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
- * corresponding commands in CommandListener.cpp */
- public static final String[] CRYPTO_TYPES
- = { "password", "default", "pattern", "pin" };
-
private final Context mContext;
private final ContentResolver mResolver;
@@ -619,18 +618,6 @@
private final Callbacks mCallbacks;
private final LockPatternUtils mLockPatternUtils;
- /**
- * The size of the crypto algorithm key in bits for OBB files. Currently
- * Twofish is used which takes 128-bit keys.
- */
- private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
-
- /**
- * The number of times to run SHA1 in the PBKDF2 function for OBB files.
- * 1024 is reasonably secure and not too slow.
- */
- private static final int PBKDF2_HASH_ROUNDS = 1024;
-
private static final String ANR_DELAY_MILLIS_DEVICE_CONFIG_KEY =
"anr_delay_millis";
@@ -933,7 +920,7 @@
private void handleSystemReady() {
if (prepareSmartIdleMaint()) {
- SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, SMART_IDLE_MAINT_PERIOD);
+ SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, sSmartIdleMaintPeriod);
}
// Start scheduling nominally-daily fstrim operations
@@ -1908,10 +1895,19 @@
mSettingsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
- mHourlyWriteFile = new AtomicFile(
- new File(Environment.getDataSystemDirectory(), "storage-hourly-writes"));
+ mWriteRecordFile = new AtomicFile(
+ new File(Environment.getDataSystemDirectory(), "storage-write-records"));
- mStorageHourlyWrites = new int[MAX_HOURLY_WRITE_RECORDS];
+ sSmartIdleMaintPeriod = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+ "smart_idle_maint_period", DEFAULT_SMART_IDLE_MAINT_PERIOD);
+ if (sSmartIdleMaintPeriod < MIN_SMART_IDLE_MAINT_PERIOD) {
+ sSmartIdleMaintPeriod = MIN_SMART_IDLE_MAINT_PERIOD;
+ } else if (sSmartIdleMaintPeriod > MAX_SMART_IDLE_MAINT_PERIOD) {
+ sSmartIdleMaintPeriod = MAX_SMART_IDLE_MAINT_PERIOD;
+ }
+
+ mMaxWriteRecords = MAX_PERIOD_WRITE_RECORD / sSmartIdleMaintPeriod;
+ mStorageWriteRecords = new int[mMaxWriteRecords];
synchronized (mLock) {
readSettingsLocked();
@@ -2657,7 +2653,7 @@
// maintenance to avoid the conflict
mNeedGC = false;
- loadStorageHourlyWrites();
+ loadStorageWriteRecords();
try {
mVold.refreshLatestWrite();
} catch (Exception e) {
@@ -2673,13 +2669,17 @@
return mPassedLifetimeThresh;
}
- private void loadStorageHourlyWrites() {
+ private void loadStorageWriteRecords() {
FileInputStream fis = null;
try {
- fis = mHourlyWriteFile.openRead();
+ fis = mWriteRecordFile.openRead();
ObjectInputStream ois = new ObjectInputStream(fis);
- mStorageHourlyWrites = (int[])ois.readObject();
+
+ int periodValue = ois.readInt();
+ if (periodValue == sSmartIdleMaintPeriod) {
+ mStorageWriteRecords = (int[]) ois.readObject();
+ }
} catch (FileNotFoundException e) {
// Missing data is okay, probably first boot
} catch (Exception e) {
@@ -2689,24 +2689,26 @@
}
}
- private int getAverageHourlyWrite() {
- return Arrays.stream(mStorageHourlyWrites).sum() / MAX_HOURLY_WRITE_RECORDS;
+ private int getAverageWriteAmount() {
+ return Arrays.stream(mStorageWriteRecords).sum() / mMaxWriteRecords;
}
- private void updateStorageHourlyWrites(int latestWrite) {
+ private void updateStorageWriteRecords(int latestWrite) {
FileOutputStream fos = null;
- System.arraycopy(mStorageHourlyWrites,0, mStorageHourlyWrites, 1,
- MAX_HOURLY_WRITE_RECORDS - 1);
- mStorageHourlyWrites[0] = latestWrite;
+ System.arraycopy(mStorageWriteRecords, 0, mStorageWriteRecords, 1,
+ mMaxWriteRecords - 1);
+ mStorageWriteRecords[0] = latestWrite;
try {
- fos = mHourlyWriteFile.startWrite();
+ fos = mWriteRecordFile.startWrite();
ObjectOutputStream oos = new ObjectOutputStream(fos);
- oos.writeObject(mStorageHourlyWrites);
- mHourlyWriteFile.finishWrite(fos);
+
+ oos.writeInt(sSmartIdleMaintPeriod);
+ oos.writeObject(mStorageWriteRecords);
+ mWriteRecordFile.finishWrite(fos);
} catch (IOException e) {
if (fos != null) {
- mHourlyWriteFile.failWrite(fos);
+ mWriteRecordFile.failWrite(fos);
}
}
}
@@ -2770,22 +2772,23 @@
return;
}
- int latestHourlyWrite = mVold.getWriteAmount();
- if (latestHourlyWrite == -1) {
- Slog.w(TAG, "Failed to get storage hourly write");
+ int latestWrite = mVold.getWriteAmount();
+ if (latestWrite == -1) {
+ Slog.w(TAG, "Failed to get storage write record");
return;
}
- updateStorageHourlyWrites(latestHourlyWrite);
- int avgHourlyWrite = getAverageHourlyWrite();
+ updateStorageWriteRecords(latestWrite);
+ int avgWriteAmount = getAverageWriteAmount();
- Slog.i(TAG, "Set smart idle maintenance: " + "latest hourly write: " +
- latestHourlyWrite + ", average hourly write: " + avgHourlyWrite +
+ Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " +
+ latestWrite + ", average write amount: " + avgWriteAmount +
", min segment threshold: " + mMinSegmentsThreshold +
", dirty reclaim rate: " + mDirtyReclaimRate +
- ", segment reclaim weight:" + mSegmentReclaimWeight);
- mVold.setGCUrgentPace(avgHourlyWrite, mMinSegmentsThreshold, mDirtyReclaimRate,
- mSegmentReclaimWeight);
+ ", segment reclaim weight: " + mSegmentReclaimWeight +
+ ", period: " + sSmartIdleMaintPeriod);
+ mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
+ mSegmentReclaimWeight, sSmartIdleMaintPeriod);
} else {
Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 382359a..06b3311 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -91,7 +91,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
-import com.android.internal.telephony.ICarrierPrivilegesListener;
+import com.android.internal.telephony.ICarrierPrivilegesCallback;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ITelephonyRegistry;
@@ -151,7 +151,7 @@
IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
- ICarrierPrivilegesListener carrierPrivilegesListener;
+ ICarrierPrivilegesCallback carrierPrivilegesCallback;
int callerUid;
int callerPid;
@@ -176,8 +176,8 @@
return (onOpportunisticSubscriptionsChangedListenerCallback != null);
}
- boolean matchCarrierPrivilegesListener() {
- return carrierPrivilegesListener != null;
+ boolean matchCarrierPrivilegesCallback() {
+ return carrierPrivilegesCallback != null;
}
boolean canReadCallLog() {
@@ -197,7 +197,7 @@
+ onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback="
+ onOpportunisticSubscriptionsChangedListenerCallback
- + " carrierPrivilegesListener=" + carrierPrivilegesListener
+ + " carrierPrivilegesCallback=" + carrierPrivilegesCallback
+ " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
}
}
@@ -412,7 +412,9 @@
mPreciseDataConnectionStates;
/** Per-phoneId snapshot of privileged packages (names + UIDs). */
- private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
+ @NonNull private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
+ /** Per-phoneId of CarrierService (PackageName, UID) pair. */
+ @NonNull private List<Pair<String, Integer>> mCarrierServiceStates;
/**
* Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
@@ -702,22 +704,23 @@
cutListToSize(mPhysicalChannelConfigs, mNumPhones);
cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
cutListToSize(mCarrierPrivilegeStates, mNumPhones);
+ cutListToSize(mCarrierServiceStates, mNumPhones);
return;
}
// mNumPhones > oldNumPhones: ss -> ds switch
for (int i = oldNumPhones; i < mNumPhones; i++) {
- mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
+ mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
mDataConnectionState[i] = TelephonyManager.DATA_UNKNOWN;
mVoiceActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
- mCallIncomingNumber[i] = "";
- mServiceState[i] = new ServiceState();
- mSignalStrength[i] = null;
+ mCallIncomingNumber[i] = "";
+ mServiceState[i] = new ServiceState();
+ mSignalStrength[i] = null;
mUserMobileDataState[i] = false;
- mMessageWaiting[i] = false;
- mCallForwarding[i] = false;
+ mMessageWaiting[i] = false;
+ mCallForwarding[i] = false;
mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
@@ -743,6 +746,7 @@
mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
+ mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
}
}
@@ -809,6 +813,7 @@
mDataEnabledReason = new int[numPhones];
mLinkCapacityEstimateLists = new ArrayList<>();
mCarrierPrivilegeStates = new ArrayList<>();
+ mCarrierServiceStates = new ArrayList<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -847,6 +852,7 @@
mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
+ mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -2780,16 +2786,16 @@
}
@Override
- public void addCarrierPrivilegesListener(
+ public void addCarrierPrivilegesCallback(
int phoneId,
- ICarrierPrivilegesListener callback,
- String callingPackage,
- String callingFeatureId) {
+ @NonNull ICarrierPrivilegesCallback callback,
+ @NonNull String callingPackage,
+ @NonNull String callingFeatureId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
- "addCarrierPrivilegesListener");
+ "addCarrierPrivilegesCallback");
if (VDBG) {
log(
"listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId
@@ -2809,7 +2815,7 @@
if (r == null) return;
r.context = mContext;
- r.carrierPrivilegesListener = callback;
+ r.carrierPrivilegesCallback = callback;
r.callingPackage = callingPackage;
r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
@@ -2821,10 +2827,18 @@
}
Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId);
+ Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(phoneId);
try {
- r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
- Collections.unmodifiableList(state.first),
- Arrays.copyOf(state.second, state.second.length));
+ if (r.matchCarrierPrivilegesCallback()) {
+ // Here, two callbacks are triggered in quick succession on the same binder.
+ // In typical case, we expect the callers to care about only one or the other.
+ r.carrierPrivilegesCallback.onCarrierPrivilegesChanged(
+ Collections.unmodifiableList(state.first),
+ Arrays.copyOf(state.second, state.second.length));
+
+ r.carrierPrivilegesCallback.onCarrierServiceChanged(carrierServiceState.first,
+ carrierServiceState.second);
+ }
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -2832,12 +2846,12 @@
}
@Override
- public void removeCarrierPrivilegesListener(
- ICarrierPrivilegesListener callback, String callingPackage) {
+ public void removeCarrierPrivilegesCallback(
+ @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage) {
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
- "removeCarrierPrivilegesListener");
+ "removeCarrierPrivilegesCallback");
remove(callback.asBinder());
}
@@ -2860,13 +2874,13 @@
for (Record r : mRecords) {
// Listeners are per-slot, not per-subscription. This is to provide a stable
// view across SIM profile switches.
- if (!r.matchCarrierPrivilegesListener()
+ if (!r.matchCarrierPrivilegesCallback()
|| !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
continue;
}
try {
// Make sure even in-process listeners can't modify the values.
- r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
+ r.carrierPrivilegesCallback.onCarrierPrivilegesChanged(
Collections.unmodifiableList(privilegedPackageNames),
Arrays.copyOf(privilegedUids, privilegedUids.length));
} catch (RemoteException ex) {
@@ -2878,6 +2892,34 @@
}
@Override
+ public void notifyCarrierServiceChanged(int phoneId, @Nullable String packageName, int uid) {
+ if (!checkNotifyPermission("notifyCarrierServiceChanged")) return;
+ if (!validatePhoneId(phoneId)) return;
+ if (VDBG) {
+ log("notifyCarrierServiceChanged: phoneId=" + phoneId
+ + ", package=" + pii(packageName) + ", uid=" + uid);
+ }
+
+ synchronized (mRecords) {
+ mCarrierServiceStates.set(
+ phoneId, new Pair<>(packageName, uid));
+ for (Record r : mRecords) {
+ // Listeners are per-slot, not per-subscription.
+ if (!r.matchCarrierPrivilegesCallback()
+ || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
+ continue;
+ }
+ try {
+ r.carrierPrivilegesCallback.onCarrierServiceChanged(packageName, uid);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2931,6 +2973,9 @@
pw.println(
"mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first)
+ ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">");
+ Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i);
+ pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first)
+ + ", uid=" + carrierServiceState.second + ">");
pw.decreaseIndent();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f978b2b..0f450e1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16306,8 +16306,8 @@
}
@Override
- public void deletePendingTopUid(int uid) {
- mPendingStartActivityUids.delete(uid);
+ public void deletePendingTopUid(int uid, long nowElapsed) {
+ mPendingStartActivityUids.delete(uid, nowElapsed);
}
@Override
diff --git a/services/core/java/com/android/server/am/DataConnectionStats.java b/services/core/java/com/android/server/am/DataConnectionStats.java
index 651e98c..6e39a4c 100644
--- a/services/core/java/com/android/server/am/DataConnectionStats.java
+++ b/services/core/java/com/android/server/am/DataConnectionStats.java
@@ -73,8 +73,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
- mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler,
- Context.RECEIVER_NOT_EXPORTED);
+ mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
}
@Override
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 96ea6db..9e04410 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1378,7 +1378,7 @@
mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
}
}
- mService.mInternal.deletePendingTopUid(uidRec.getUid());
+ mService.mInternal.deletePendingTopUid(uidRec.getUid(), nowElapsed);
}
if (mLocalPowerManager != null) {
mLocalPowerManager.finishUidChanges();
diff --git a/services/core/java/com/android/server/am/PendingStartActivityUids.java b/services/core/java/com/android/server/am/PendingStartActivityUids.java
index 6bf9d4e..20f6bb2 100644
--- a/services/core/java/com/android/server/am/PendingStartActivityUids.java
+++ b/services/core/java/com/android/server/am/PendingStartActivityUids.java
@@ -50,9 +50,15 @@
}
}
- synchronized void delete(int uid) {
+ synchronized void delete(int uid, long nowElapsed) {
final Pair<Integer, Long> pendingPid = mPendingUids.get(uid);
if (pendingPid != null) {
+ if (nowElapsed < pendingPid.second) {
+ Slog.i(TAG,
+ "updateOomAdj start time is before than pendingPid added,"
+ + " don't delete it");
+ return;
+ }
final long delay = SystemClock.elapsedRealtime() - pendingPid.second;
if (delay >= 1000 /*ms*/) {
Slog.i(TAG,
@@ -75,4 +81,4 @@
synchronized boolean isPendingTopUid(int uid) {
return mPendingUids.get(uid) != null;
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index de41611..a3c6f0a 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1102,6 +1102,7 @@
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
+ setCurrentAudioRouteNameIfPossible(name, /*fromA2dp=*/false);
}
if (streamType == AudioSystem.STREAM_DEFAULT) {
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 108e7bc..b9efdf5 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -71,7 +71,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
-import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@@ -222,8 +221,10 @@
"Can't get TelephonyManager for subId %d", mSubId));
}
- subscriberId = Objects.requireNonNull(tele.getSubscriberId(),
- "Null subscriber Id for subId " + mSubId);
+ subscriberId = tele.getSubscriberId();
+ if (subscriberId == null) {
+ throw new IllegalStateException("Null subscriber Id for subId " + mSubId);
+ }
mNetworkTemplate = new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
.setSubscriberIds(Set.of(subscriberId))
.setMeteredness(NetworkStats.METERED_YES)
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 71cc361..67b4469 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -118,9 +118,7 @@
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
import static com.android.internal.util.XmlUtils.readStringAttribute;
-import static com.android.internal.util.XmlUtils.readThisIntArrayXml;
import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
-import static com.android.internal.util.XmlUtils.writeIntArrayXml;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
@@ -243,7 +241,6 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.StatLogger;
-import com.android.internal.util.XmlUtils;
import com.android.net.module.util.NetworkIdentityUtils;
import com.android.net.module.util.NetworkStatsUtils;
import com.android.net.module.util.PermissionUtils;
@@ -257,8 +254,6 @@
import libcore.io.IoUtils;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -334,7 +329,8 @@
private static final int VERSION_ADDED_CYCLE = 11;
private static final int VERSION_ADDED_NETWORK_TYPES = 12;
private static final int VERSION_SUPPORTED_CARRIER_USAGE = 13;
- private static final int VERSION_LATEST = VERSION_SUPPORTED_CARRIER_USAGE;
+ private static final int VERSION_REMOVED_SUBSCRIPTION_PLANS = 14;
+ private static final int VERSION_LATEST = VERSION_REMOVED_SUBSCRIPTION_PLANS;
@VisibleForTesting
public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING;
@@ -347,7 +343,6 @@
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
- private static final String TAG_SUBSCRIPTION_PLAN = "subscription-plan";
private static final String TAG_UID_POLICY = "uid-policy";
private static final String TAG_APP_POLICY = "app-policy";
private static final String TAG_WHITELIST = "whitelist";
@@ -426,6 +421,13 @@
* obj = oldBlockedReasons
*/
private static final int MSG_BLOCKED_REASON_CHANGED = 21;
+ /**
+ * Message to indicate that subscription plans expired and should be cleared.
+ * arg1 = subId
+ * arg2 = setSubscriptionPlans call ID
+ * obj = callingPackage
+ */
+ private static final int MSG_CLEAR_SUBSCRIPTION_PLANS = 22;
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -492,6 +494,12 @@
/** Map from subId to package name that owns subscription plans. */
@GuardedBy("mNetworkPoliciesSecondLock")
final SparseArray<String> mSubscriptionPlansOwner = new SparseArray<>();
+ /** Map from subId to the ID of the clear plans request. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ final SparseIntArray mSetSubscriptionPlansIds = new SparseIntArray();
+ /** Atomic integer to generate a new ID for each clear plans request. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ int mSetSubscriptionPlansIdCounter = 0;
/** Map from subId to daily opportunistic quota. */
@GuardedBy("mNetworkPoliciesSecondLock")
@@ -2553,56 +2561,6 @@
warningBytes, limitBytes, lastWarningSnooze,
lastLimitSnooze, metered, inferred));
}
-
- } else if (TAG_SUBSCRIPTION_PLAN.equals(tag)) {
- final String start = readStringAttribute(in, ATTR_CYCLE_START);
- final String end = readStringAttribute(in, ATTR_CYCLE_END);
- final String period = readStringAttribute(in, ATTR_CYCLE_PERIOD);
- final SubscriptionPlan.Builder builder = new SubscriptionPlan.Builder(
- RecurrenceRule.convertZonedDateTime(start),
- RecurrenceRule.convertZonedDateTime(end),
- RecurrenceRule.convertPeriod(period));
- builder.setTitle(readStringAttribute(in, ATTR_TITLE));
- builder.setSummary(readStringAttribute(in, ATTR_SUMMARY));
-
- final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES,
- SubscriptionPlan.BYTES_UNKNOWN);
- final int limitBehavior = readIntAttribute(in, ATTR_LIMIT_BEHAVIOR,
- SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN);
- if (limitBytes != SubscriptionPlan.BYTES_UNKNOWN
- && limitBehavior != SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN) {
- builder.setDataLimit(limitBytes, limitBehavior);
- }
-
- final long usageBytes = readLongAttribute(in, ATTR_USAGE_BYTES,
- SubscriptionPlan.BYTES_UNKNOWN);
- final long usageTime = readLongAttribute(in, ATTR_USAGE_TIME,
- SubscriptionPlan.TIME_UNKNOWN);
- if (usageBytes != SubscriptionPlan.BYTES_UNKNOWN
- && usageTime != SubscriptionPlan.TIME_UNKNOWN) {
- builder.setDataUsage(usageBytes, usageTime);
- }
-
- final int subId = readIntAttribute(in, ATTR_SUB_ID);
- final String ownerPackage = readStringAttribute(in, ATTR_OWNER_PACKAGE);
-
- if (version >= VERSION_ADDED_NETWORK_TYPES) {
- final int depth = in.getDepth();
- while (XmlUtils.nextElementWithin(in, depth)) {
- if (TAG_XML_UTILS_INT_ARRAY.equals(in.getName())
- && ATTR_NETWORK_TYPES.equals(
- readStringAttribute(in, ATTR_XML_UTILS_NAME))) {
- final int[] networkTypes =
- readThisIntArrayXml(in, TAG_XML_UTILS_INT_ARRAY, null);
- builder.setNetworkTypes(networkTypes);
- }
- }
- }
-
- final SubscriptionPlan plan = builder.build();
- mSubscriptionPlans.put(subId, ArrayUtils.appendElement(
- SubscriptionPlan.class, mSubscriptionPlans.get(subId), plan));
- mSubscriptionPlansOwner.put(subId, ownerPackage);
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
final int policy = readIntAttribute(in, ATTR_POLICY);
@@ -2793,38 +2751,6 @@
out.endTag(null, TAG_NETWORK_POLICY);
}
- // write all known subscription plans
- for (int i = 0; i < mSubscriptionPlans.size(); i++) {
- final int subId = mSubscriptionPlans.keyAt(i);
- if (subId == INVALID_SUBSCRIPTION_ID) continue;
- final String ownerPackage = mSubscriptionPlansOwner.get(subId);
- final SubscriptionPlan[] plans = mSubscriptionPlans.valueAt(i);
- if (ArrayUtils.isEmpty(plans)) continue;
-
- for (SubscriptionPlan plan : plans) {
- out.startTag(null, TAG_SUBSCRIPTION_PLAN);
- writeIntAttribute(out, ATTR_SUB_ID, subId);
- writeStringAttribute(out, ATTR_OWNER_PACKAGE, ownerPackage);
- final RecurrenceRule cycleRule = plan.getCycleRule();
- writeStringAttribute(out, ATTR_CYCLE_START,
- RecurrenceRule.convertZonedDateTime(cycleRule.start));
- writeStringAttribute(out, ATTR_CYCLE_END,
- RecurrenceRule.convertZonedDateTime(cycleRule.end));
- writeStringAttribute(out, ATTR_CYCLE_PERIOD,
- RecurrenceRule.convertPeriod(cycleRule.period));
- writeStringAttribute(out, ATTR_TITLE, plan.getTitle());
- writeStringAttribute(out, ATTR_SUMMARY, plan.getSummary());
- writeLongAttribute(out, ATTR_LIMIT_BYTES, plan.getDataLimitBytes());
- writeIntAttribute(out, ATTR_LIMIT_BEHAVIOR, plan.getDataLimitBehavior());
- writeLongAttribute(out, ATTR_USAGE_BYTES, plan.getDataUsageBytes());
- writeLongAttribute(out, ATTR_USAGE_TIME, plan.getDataUsageTime());
- try {
- writeIntArrayXml(plan.getNetworkTypes(), ATTR_NETWORK_TYPES, out);
- } catch (XmlPullParserException ignored) { }
- out.endTag(null, TAG_SUBSCRIPTION_PLAN);
- }
- }
-
// write all known uid policies
for (int i = 0; i < mUidPolicy.size(); i++) {
final int uid = mUidPolicy.keyAt(i);
@@ -3698,7 +3624,8 @@
}
@Override
- public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
+ public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans,
+ long expirationDurationMillis, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
enforceSubscriptionPlanValidity(plans);
@@ -3708,34 +3635,47 @@
final long token = Binder.clearCallingIdentity();
try {
- synchronized (mUidRulesFirstLock) {
- synchronized (mNetworkPoliciesSecondLock) {
- mSubscriptionPlans.put(subId, plans);
- mSubscriptionPlansOwner.put(subId, callingPackage);
-
- final String subscriberId = mSubIdToSubscriberId.get(subId, null);
- if (subscriberId != null) {
- ensureActiveCarrierPolicyAL(subId, subscriberId);
- maybeUpdateCarrierPolicyCycleAL(subId, subscriberId);
- } else {
- Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
- }
-
- handleNetworkPoliciesUpdateAL(true);
- }
- }
-
- final Intent intent = new Intent(SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
- mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
- mHandler.sendMessage(
- mHandler.obtainMessage(MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
+ setSubscriptionPlansInternal(subId, plans, expirationDurationMillis, callingPackage);
} finally {
Binder.restoreCallingIdentity(token);
}
}
+ private void setSubscriptionPlansInternal(int subId, SubscriptionPlan[] plans,
+ long expirationDurationMillis, String callingPackage) {
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ mSubscriptionPlans.put(subId, plans);
+ mSubscriptionPlansOwner.put(subId, callingPackage);
+
+ final String subscriberId = mSubIdToSubscriberId.get(subId, null);
+ if (subscriberId != null) {
+ ensureActiveCarrierPolicyAL(subId, subscriberId);
+ maybeUpdateCarrierPolicyCycleAL(subId, subscriberId);
+ } else {
+ Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
+ }
+
+ handleNetworkPoliciesUpdateAL(true);
+
+ final Intent intent = new Intent(
+ SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+ mContext.sendBroadcast(intent,
+ android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
+ mHandler.sendMessage(mHandler.obtainMessage(
+ MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
+ final int setPlansId = mSetSubscriptionPlansIdCounter++;
+ mSetSubscriptionPlansIds.put(subId, setPlansId);
+ if (expirationDurationMillis > 0) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_SUBSCRIPTION_PLANS,
+ subId, setPlansId, callingPackage), expirationDurationMillis);
+ }
+ }
+ }
+ }
+
/**
* Only visible for testing purposes. This doesn't give any access to
* existing plans; it simply lets the debug package define new plans.
@@ -3758,7 +3698,7 @@
@Override
public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue,
- int[] networkTypes, long timeoutMillis, String callingPackage) {
+ int[] networkTypes, long expirationDurationMillis, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
final ArraySet<Integer> allNetworksSet = new ArraySet<>();
@@ -3796,10 +3736,10 @@
args.arg3 = overrideValue;
args.arg4 = applicableNetworks.toArray();
mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args));
- if (timeoutMillis > 0) {
+ if (expirationDurationMillis > 0) {
args.arg3 = 0;
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args),
- timeoutMillis);
+ expirationDurationMillis);
}
}
}
@@ -4187,7 +4127,7 @@
if (mRestrictedNetworkingMode) {
// Note: setUidFirewallRule also updates mUidFirewallRestrictedModeRules.
// In this case, default firewall rules can also be added.
- setUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, uid,
+ setUidFirewallRuleUL(FIREWALL_CHAIN_RESTRICTED, uid,
getRestrictedModeFirewallRule(uidBlockedState));
}
}
@@ -4351,9 +4291,9 @@
final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid,
chain == FIREWALL_CHAIN_DOZABLE);
if (isWhitelisted || isUidForegroundOnRestrictPowerUL(uid)) {
- setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
+ setUidFirewallRuleUL(chain, uid, FIREWALL_RULE_ALLOW);
} else {
- setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
+ setUidFirewallRuleUL(chain, uid, FIREWALL_RULE_DEFAULT);
}
}
}
@@ -4399,10 +4339,10 @@
int appId = UserHandle.getAppId(uid);
if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
&& !isUidForegroundOnRestrictPowerUL(uid)) {
- setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
+ setUidFirewallRuleUL(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
if (LOGD) Log.d(TAG, "updateRuleForAppIdleUL DENY " + uid);
} else {
- setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
+ setUidFirewallRuleUL(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
if (LOGD) Log.d(TAG, "updateRuleForAppIdleUL " + uid + " to DEFAULT");
}
} finally {
@@ -5214,6 +5154,22 @@
mListeners.finishBroadcast();
return true;
}
+ case MSG_CLEAR_SUBSCRIPTION_PLANS: {
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ int subId = msg.arg1;
+ if (msg.arg2 == mSetSubscriptionPlansIds.get(subId)) {
+ if (LOGD) Slog.d(TAG, "Clearing expired subscription plans.");
+ setSubscriptionPlansInternal(subId, new SubscriptionPlan[]{},
+ 0 /* expirationDurationMillis */,
+ (String) msg.obj /* callingPackage */);
+ } else {
+ if (LOGD) Slog.d(TAG, "Ignoring stale CLEAR_SUBSCRIPTION_PLANS.");
+ }
+ }
+ }
+ return true;
+ }
case MSG_BLOCKED_REASON_CHANGED: {
final int uid = msg.arg1;
final int newBlockedReasons = msg.arg2;
@@ -5450,10 +5406,11 @@
/**
* Add or remove a uid to the firewall denylist for all network ifaces.
*/
- private void setUidFirewallRule(int chain, int uid, int rule) {
+ @GuardedBy("mUidRulesFirstLock")
+ private void setUidFirewallRuleUL(int chain, int uid, int rule) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
- "setUidFirewallRule: " + chain + "/" + uid + "/" + rule);
+ "setUidFirewallRuleUL: " + chain + "/" + uid + "/" + rule);
}
try {
if (chain == FIREWALL_CHAIN_DOZABLE) {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 5a5f9ef..f16ee927 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -256,6 +256,17 @@
}
/**
+ * Sets in Installd that it is first boot after data wipe
+ */
+ public void setFirstBoot() throws InstallerException {
+ try {
+ mInstalld.setFirstBoot();
+ } catch (RemoteException e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ /**
* Class that collects multiple {@code installd} operations together in an
* attempt to more efficiently execute them in bulk.
* <p>
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 94dd4be..fad18d2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7554,6 +7554,16 @@
/* excludePreCreated= */ false));
t.traceEnd();
+ if (mFirstBoot) {
+ t.traceBegin("setFirstBoot: ");
+ try {
+ mInstaller.setFirstBoot();
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Could not set First Boot: ", e);
+ }
+ t.traceEnd();
+ }
+
mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions);
mPermissionManager.readLegacyPermissionStateTEMP();
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 30e2617..89470ec 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -39,7 +39,7 @@
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
-import android.telephony.TelephonyManager.CarrierPrivilegesListener;
+import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -98,8 +98,7 @@
@NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener;
@NonNull
- private final List<CarrierPrivilegesListener> mCarrierPrivilegesChangedListeners =
- new ArrayList<>();
+ private final List<CarrierPrivilegesCallback> mCarrierPrivilegesCallbacks = new ArrayList<>();
@NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot;
@@ -146,25 +145,26 @@
filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED);
- mContext.registerReceiver(this, filter, null, mHandler, Context.RECEIVER_NOT_EXPORTED);
+ mContext.registerReceiver(this, filter, null, mHandler);
mSubscriptionManager.addOnSubscriptionsChangedListener(
executor, mSubscriptionChangedListener);
mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
- registerCarrierPrivilegesListeners();
+ registerCarrierPrivilegesCallbacks();
}
- private void registerCarrierPrivilegesListeners() {
+ // TODO(b/221306368): Refactor with the new onCarrierServiceChange in the new CPCallback
+ private void registerCarrierPrivilegesCallbacks() {
final HandlerExecutor executor = new HandlerExecutor(mHandler);
final int modemCount = mTelephonyManager.getActiveModemCount();
try {
for (int i = 0; i < modemCount; i++) {
- CarrierPrivilegesListener carrierPrivilegesListener =
- new CarrierPrivilegesListener() {
+ CarrierPrivilegesCallback carrierPrivilegesCallback =
+ new CarrierPrivilegesCallback() {
@Override
public void onCarrierPrivilegesChanged(
- @NonNull List<String> privilegedPackageNames,
- @NonNull int[] privilegedUids) {
+ @NonNull Set<String> privilegedPackageNames,
+ @NonNull Set<Integer> privilegedUids) {
// Re-trigger the synchronous check (which is also very cheap due
// to caching in CarrierPrivilegesTracker). This allows consistency
// with the onSubscriptionsChangedListener and broadcasts.
@@ -172,9 +172,9 @@
}
};
- mTelephonyManager.addCarrierPrivilegesListener(
- i, executor, carrierPrivilegesListener);
- mCarrierPrivilegesChangedListeners.add(carrierPrivilegesListener);
+ mTelephonyManager.registerCarrierPrivilegesCallback(
+ i, executor, carrierPrivilegesCallback);
+ mCarrierPrivilegesCallbacks.add(carrierPrivilegesCallback);
}
} catch (IllegalArgumentException e) {
Slog.wtf(TAG, "Encounted exception registering carrier privileges listeners", e);
@@ -191,15 +191,15 @@
mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener);
mTelephonyManager.unregisterTelephonyCallback(mActiveDataSubIdListener);
- unregisterCarrierPrivilegesListeners();
+ unregisterCarrierPrivilegesCallbacks();
}
- private void unregisterCarrierPrivilegesListeners() {
- for (CarrierPrivilegesListener carrierPrivilegesListener :
- mCarrierPrivilegesChangedListeners) {
- mTelephonyManager.removeCarrierPrivilegesListener(carrierPrivilegesListener);
+ private void unregisterCarrierPrivilegesCallbacks() {
+ for (CarrierPrivilegesCallback carrierPrivilegesCallback :
+ mCarrierPrivilegesCallbacks) {
+ mTelephonyManager.unregisterCarrierPrivilegesCallback(carrierPrivilegesCallback);
}
- mCarrierPrivilegesChangedListeners.clear();
+ mCarrierPrivilegesCallbacks.clear();
}
/**
@@ -283,7 +283,7 @@
}
private void handleActionMultiSimConfigChanged(Context context, Intent intent) {
- unregisterCarrierPrivilegesListeners();
+ unregisterCarrierPrivilegesCallbacks();
// Clear invalid slotIds from the mReadySubIdsBySlotId map.
final int modemCount = mTelephonyManager.getActiveModemCount();
@@ -296,7 +296,7 @@
}
}
- registerCarrierPrivilegesListeners();
+ registerCarrierPrivilegesCallbacks();
handleSubscriptionsChanged();
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 6fda72e..eddb5e9 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -59,8 +59,8 @@
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
import android.graphics.Color;
+import android.graphics.ImageDecoder;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.display.DisplayManager;
@@ -193,6 +193,8 @@
static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
+ private static final String RECORD_FILE = "decode_record";
+ private static final String RECORD_LOCK_FILE = "decode_lock_record";
// All the various per-user state files we need to be aware of
private static final String[] sPerUserFiles = new String[] {
@@ -674,8 +676,7 @@
}
if (DEBUG) {
- // This is just a quick estimation, may be smaller than it is.
- long estimateSize = options.outWidth * options.outHeight * 4;
+ long estimateSize = (long) options.outWidth * options.outHeight * 4;
Slog.v(TAG, "Null crop of new wallpaper, estimate size="
+ estimateSize + ", success=" + success);
}
@@ -684,9 +685,6 @@
FileOutputStream f = null;
BufferedOutputStream bos = null;
try {
- BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
- wallpaper.wallpaperFile.getAbsolutePath(), false);
-
// This actually downsamples only by powers of two, but that's okay; we do
// a proper scaling blit later. This is to minimize transient RAM use.
// We calculate the largest power-of-two under the actual ratio rather than
@@ -740,8 +738,24 @@
Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize());
}
- Bitmap cropped = decoder.decodeRegion(cropHint, options);
- decoder.recycle();
+ //Create a record file and will delete if ImageDecoder work well.
+ final String recordName =
+ (wallpaper.wallpaperFile.getName().equals(WALLPAPER)
+ ? RECORD_FILE : RECORD_LOCK_FILE);
+ final File record = new File(getWallpaperDir(wallpaper.userId), recordName);
+ record.createNewFile();
+ Slog.v(TAG, "record path =" + record.getPath()
+ + ", record name =" + record.getName());
+
+ final ImageDecoder.Source srcData =
+ ImageDecoder.createSource(wallpaper.wallpaperFile);
+ final int sampleSize = scale;
+ Bitmap cropped = ImageDecoder.decodeBitmap(srcData, (decoder, info, src) -> {
+ decoder.setTargetSampleSize(sampleSize);
+ decoder.setCrop(estimateCrop);
+ });
+
+ record.delete();
if (cropped == null) {
Slog.e(TAG, "Could not decode new wallpaper");
@@ -1779,6 +1793,7 @@
new UserSwitchObserver() {
@Override
public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+ errorCheck(newUserId);
switchUser(newUserId, reply);
}
}, TAG);
@@ -1816,6 +1831,14 @@
@Override
public void onBootPhase(int phase) {
+ // If someone set too large jpg file as wallpaper, system_server may be killed by lmk in
+ // generateCrop(), so we create a file in generateCrop() before ImageDecoder starts working
+ // and delete this file after ImageDecoder finishing. If the specific file exists, that
+ // means ImageDecoder can't handle the original wallpaper file, in order to avoid
+ // system_server restart again and again and rescue party will trigger factory reset,
+ // so we reset default wallpaper in case system_server is trapped into a restart loop.
+ errorCheck(UserHandle.USER_SYSTEM);
+
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
systemReady();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
@@ -1823,6 +1846,38 @@
}
}
+ private static final HashMap<Integer, String> sWallpaperType = new HashMap<Integer, String>() {
+ {
+ put(FLAG_SYSTEM, RECORD_FILE);
+ put(FLAG_LOCK, RECORD_LOCK_FILE);
+ }
+ };
+
+ private void errorCheck(int userID) {
+ sWallpaperType.forEach((type, filename) -> {
+ final File record = new File(getWallpaperDir(userID), filename);
+ if (record.exists()) {
+ Slog.w(TAG, "User:" + userID + ", wallpaper tyep = " + type
+ + ", wallpaper fail detect!! reset to default wallpaper");
+ clearWallpaperData(userID, type);
+ record.delete();
+ }
+ });
+ }
+
+ private void clearWallpaperData(int userID, int wallpaperType) {
+ final WallpaperData wallpaper = new WallpaperData(userID, getWallpaperDir(userID),
+ (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_ORIG : WALLPAPER,
+ (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP);
+ if (wallpaper.sourceExists()) {
+ wallpaper.wallpaperFile.delete();
+ }
+ if (wallpaper.cropExists()) {
+ wallpaper.cropFile.delete();
+ }
+
+ }
+
@Override
public void onUnlockUser(final int userId) {
TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index d69d32e..9e87a17 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -967,6 +967,26 @@
break;
}
+ if (LayoutParams.isSystemAlertWindowType(attrs.type)) {
+ float maxOpacity = mService.mMaximumObscuringOpacityForTouch;
+ if (attrs.alpha > maxOpacity
+ && (attrs.flags & FLAG_NOT_TOUCHABLE) != 0
+ && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) {
+ // The app is posting a SAW with the intent of letting touches pass through, but
+ // they are going to be deemed untrusted and will be blocked. Try to honor the
+ // intent of letting touches pass through at the cost of 0.2 opacity for app
+ // compatibility reasons. More details on b/218777508.
+ Slog.w(TAG, String.format(
+ "App %s has a system alert window (type = %d) with FLAG_NOT_TOUCHABLE and "
+ + "LayoutParams.alpha = %.2f > %.2f, setting alpha to %.2f to "
+ + "let touches pass through (if this is isn't desirable, remove "
+ + "flag FLAG_NOT_TOUCHABLE).",
+ attrs.packageName, attrs.type, attrs.alpha, maxOpacity, maxOpacity));
+ attrs.alpha = maxOpacity;
+ win.mWinAnimator.mAlpha = maxOpacity;
+ }
+ }
+
// Check if alternate bars positions were updated.
if (mStatusBarAlt == win) {
mStatusBarAltPosition = getAltBarPosition(attrs);
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java b/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java
index 92baadf..7a6e86c 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateDenylist.java
@@ -41,9 +41,6 @@
private final String[] mDefaultDenylist;
private final Object mLock = new Object();
- private DeviceConfigInterface mDeviceConfig;
- private OnPropertiesChangedListener mListener = new OnPropertiesChangedListener();
-
static HighRefreshRateDenylist create(@NonNull Resources r) {
return new HighRefreshRateDenylist(r, DeviceConfigInterface.REAL);
}
@@ -51,10 +48,9 @@
@VisibleForTesting
HighRefreshRateDenylist(Resources r, DeviceConfigInterface deviceConfig) {
mDefaultDenylist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
- mDeviceConfig = deviceConfig;
- mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
- BackgroundThread.getExecutor(), mListener);
- final String property = mDeviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
+ final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
KEY_HIGH_REFRESH_RATE_BLACKLIST);
updateDenylist(property);
}
@@ -95,14 +91,6 @@
}
}
- /** Used to prevent WmTests leaking issues. */
- @VisibleForTesting
- void dispose() {
- mDeviceConfig.removeOnPropertiesChangedListener(mListener);
- mDeviceConfig = null;
- mDenylistedPackages.clear();
- }
-
private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
if (properties.getKeyset().contains(KEY_HIGH_REFRESH_RATE_BLACKLIST)) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
index a5ebf9a..ba62091 100644
--- a/services/core/java/com/android/server/wm/WindowManagerConstants.java
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -91,12 +91,6 @@
updateSystemGestureExcludedByPreQStickyImmersive();
}
- @VisibleForTesting
- void dispose() {
- mDeviceConfig.removeOnPropertiesChangedListener(mListenerAndroid);
- mDeviceConfig.removeOnPropertiesChangedListener(mListenerWindowManager);
- }
-
private void onAndroidPropertiesChanged(DeviceConfig.Properties properties) {
synchronized (mGlobalLock) {
boolean updateSystemGestureExclusionLimit = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4258e07..40c7b3b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -769,6 +769,9 @@
private final DisplayHashController mDisplayHashController;
+ volatile float mMaximumObscuringOpacityForTouch =
+ InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH;
+
@VisibleForTesting
final WindowContextListenerController mWindowContextListenerController =
new WindowContextListenerController();
@@ -801,6 +804,8 @@
DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor(
DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
+ private final Uri mMaximumObscuringOpacityForTouchUri = Settings.Global.getUriFor(
+ Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
public SettingsObserver() {
super(new Handler());
@@ -827,6 +832,8 @@
UserHandle.USER_ALL);
resolver.registerContentObserver(mDisplaySettingsPathUri, false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this,
+ UserHandle.USER_ALL);
}
@Override
@@ -875,6 +882,11 @@
return;
}
+ if (mMaximumObscuringOpacityForTouchUri.equals(uri)) {
+ updateMaximumObscuringOpacityForTouch();
+ return;
+ }
+
@UpdateAnimationScaleMode
final int mode;
if (mWindowAnimationScaleUri.equals(uri)) {
@@ -894,6 +906,14 @@
void loadSettings() {
updateSystemUiSettings(false /* handleChange */);
updatePointerLocation();
+ updateMaximumObscuringOpacityForTouch();
+ }
+
+ void updateMaximumObscuringOpacityForTouch() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mMaximumObscuringOpacityForTouch = Settings.Global.getFloat(resolver,
+ Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
+ InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
}
void updateSystemUiSettings(boolean handleChange) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 67b656b..77d40d2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -206,8 +206,6 @@
import dalvik.system.VMRuntime;
-import com.google.android.startop.iorap.IorapForwardingService;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -1552,10 +1550,6 @@
mSystemServiceManager.startService(PinnerService.class);
t.traceEnd();
- t.traceBegin("IorapForwardingService");
- mSystemServiceManager.startService(IorapForwardingService.class);
- t.traceEnd();
-
if (Build.IS_DEBUGGABLE && ProfcollectForwardingService.enabled()) {
t.traceBegin("ProfcollectForwardingService");
mSystemServiceManager.startService(ProfcollectForwardingService.class);
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 66e840b..bbc28d7 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -54,7 +54,7 @@
private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
- private static final long BG_PROCESS_PERIOD = TimeUnit.DAYS.toMillis(1); // every 1 day.
+ private static final long BG_PROCESS_PERIOD = TimeUnit.HOURS.toMillis(4); // every 4 hours.
private IProfCollectd mIProfcollect;
private static ProfcollectForwardingService sSelfService;
diff --git a/services/startop/Android.bp b/services/startop/Android.bp
deleted file mode 100644
index c56c463..0000000
--- a/services/startop/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 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
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library_static {
- name: "services.startop",
- defaults: ["platform_service_defaults"],
-
- static_libs: [
- // frameworks/base/startop/iorap
- "services.startop.iorap",
- ],
-}
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 1393d39..f865a50 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -2238,7 +2238,7 @@
private void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage)
throws InterruptedException {
- mService.setSubscriptionPlans(subId, plans, callingPackage);
+ mService.setSubscriptionPlans(subId, plans, 0, callingPackage);
// setSubscriptionPlans() triggers async events, wait for those to be completed before
// moving forward as they could interfere with the tests later.
postMsgAndWaitForCompletion();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
index 66da2a6..716612c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
@@ -284,7 +284,7 @@
.setCreateActivity(true).build().getTopMostActivity();
activity2.getTask().setResumedActivity(activity2, "test");
- mAtm.mAmInternal.deletePendingTopUid(activity1.getUid());
+ mAtm.mAmInternal.deletePendingTopUid(activity1.getUid(), Long.MAX_VALUE);
clearInvocations(mAtm);
activity1.moveFocusableActivityToTop("test");
assertTrue(mAtm.mAmInternal.isPendingTopUid(activity1.getUid()));
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java
index dfc2e35..38ab683 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateDenylistTest.java
@@ -33,7 +33,6 @@
import com.android.internal.util.Preconditions;
import com.android.server.testutils.FakeDeviceConfigInterface;
-import org.junit.After;
import org.junit.Test;
import java.util.concurrent.Executor;
@@ -51,11 +50,6 @@
private HighRefreshRateDenylist mDenylist;
- @After
- public void tearDown() {
- mDenylist.dispose();
- }
-
@Test
public void testDefaultDenylist() {
final Resources r = createResources(APP1, APP2);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index f41ca65c..db937c1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -27,6 +28,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
@@ -36,6 +38,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.withSettings;
+
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.usage.UsageStatsManagerInternal;
@@ -57,6 +62,7 @@
import android.os.PowerSaveState;
import android.os.StrictMode;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.util.Log;
import android.view.InputChannel;
import android.view.Surface;
@@ -83,10 +89,12 @@
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
+import org.mockito.MockSettings;
import org.mockito.Mockito;
import org.mockito.quality.Strictness;
import java.io.File;
+import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
@@ -107,6 +115,13 @@
.getSystemService(PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
private PowerManager.WakeLock mStubbedWakeLock;
+ /**
+ * The captured listeners will be unregistered in {@link #tearDown()} to avoid keeping static
+ * references of test instances from DeviceConfig.
+ */
+ private final ArrayList<DeviceConfig.OnPropertiesChangedListener> mDeviceConfigListeners =
+ new ArrayList<>();
+
private Description mDescription;
private Context mContext;
private StaticMockitoSession mMockitoSession;
@@ -144,19 +159,27 @@
Log.e("SystemServicesTestRule", "Suppressed: ", throwable);
t.addSuppressed(throwable);
}
- throw t;
+ throwable = t;
}
- if (throwable != null) throw throwable;
}
+ if (throwable != null) throw throwable;
}
};
}
private void setUp() {
+ // Use stubOnly() to reduce memory usage if it doesn't need verification.
+ final MockSettings spyStubOnly = withSettings().stubOnly()
+ .defaultAnswer(CALLS_REAL_METHODS);
+ final MockSettings mockStubOnly = withSettings().stubOnly();
+ // Return mocked services: LocalServices.getService
+ // Avoid leakage: DeviceConfig.addOnPropertiesChangedListener, LockGuard.installLock
+ // Watchdog.getInstance/addMonitor
mMockitoSession = mockitoSession()
- .spyStatic(LocalServices.class)
- .mockStatic(LockGuard.class)
- .mockStatic(Watchdog.class)
+ .mockStatic(LocalServices.class, spyStubOnly)
+ .mockStatic(DeviceConfig.class, spyStubOnly)
+ .mockStatic(LockGuard.class, mockStubOnly)
+ .mockStatic(Watchdog.class, mockStubOnly)
.strictness(Strictness.LENIENT)
.startMocking();
@@ -168,6 +191,16 @@
private void setUpSystemCore() {
doReturn(mock(Watchdog.class)).when(Watchdog::getInstance);
+ doAnswer(invocation -> {
+ // Exclude CONSTRAIN_DISPLAY_APIS because ActivityRecord#sConstrainDisplayApisConfig
+ // only registers once and it doesn't reference to outside.
+ if (!NAMESPACE_CONSTRAIN_DISPLAY_APIS.equals(invocation.getArgument(0))) {
+ mDeviceConfigListeners.add(invocation.getArgument(2));
+ }
+ // SizeCompatTests uses setNeverConstrainDisplayApisFlag, and ActivityRecordTests
+ // uses splash_screen_exception_list. So still execute real registration.
+ return invocation.callRealMethod();
+ }).when(() -> DeviceConfig.addOnPropertiesChangedListener(anyString(), any(), any()));
mContext = getInstrumentation().getTargetContext();
spyOn(mContext);
@@ -346,11 +379,10 @@
// Unregister display listener from root to avoid issues with subsequent tests.
mContext.getSystemService(DisplayManager.class)
.unregisterDisplayListener(mAtmService.mRootWindowContainer);
- // The constructor of WindowManagerService registers WindowManagerConstants and
- // HighRefreshRateBlacklist with DeviceConfig. We need to undo that here to avoid
- // leaking mWmService.
- mWmService.mConstants.dispose();
- mWmService.mHighRefreshRateDenylist.dispose();
+
+ for (int i = mDeviceConfigListeners.size() - 1; i >= 0; i--) {
+ DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListeners.get(i));
+ }
// This makes sure the posted messages without delay are processed, e.g.
// DisplayPolicy#release, WindowManagerService#setAnimationScale.
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java
index 4056c71..2e7cc27 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java
@@ -16,59 +16,64 @@
package com.android.server.wm;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
import android.platform.test.annotations.Presubmit;
-import org.junit.Rule;
+import com.android.internal.util.GcUtils;
+
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import org.junit.runners.model.Statement;
-import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.function.Predicate;
@Presubmit
public class SystemServicesTestRuleTest {
- @Rule
- public ExpectedException mExpectedException = ExpectedException.none();
@Test
- public void testRule_rethrows_unchecked_exceptions() throws Throwable {
- final SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
- Statement statement = new Statement() {
- @Override
- public void evaluate() throws Throwable {
- throw new RuntimeException("A failing test!");
- }
- };
- mExpectedException.expect(RuntimeException.class);
- mWmsRule.apply(statement, null /* Description*/).evaluate();
- }
-
- @Test
- public void testRule_rethrows_checked_exceptions() throws Throwable {
- final SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
- Statement statement = new Statement() {
- @Override
- public void evaluate() throws Throwable {
- throw new IOException("A failing test!");
- }
- };
- mExpectedException.expect(IOException.class);
- mWmsRule.apply(statement, null /* Description*/).evaluate();
+ public void testRule_rethrows_throwable() {
+ assertThrows(Throwable.class, () -> applyRule(rule -> false));
}
@Test
public void testRule_ranSuccessfully() throws Throwable {
- final boolean[] testRan = {false};
- final SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
- Statement statement = new Statement() {
+ final int iterations = 5;
+ final ArrayList<WeakReference<WindowManagerService>> wmsRefs = new ArrayList<>();
+ for (int i = 0; i < iterations; i++) {
+ applyRule(rule -> {
+ final WindowManagerService wms = rule.getWindowManagerService();
+ assertNotNull(wms);
+ wmsRefs.add(new WeakReference<>(wms));
+ return true;
+ });
+ }
+ assertEquals(iterations, wmsRefs.size());
+
+ GcUtils.runGcAndFinalizersSync();
+ // Only ensure that at least one instance is released because some references may be kept
+ // temporally by the message of other thread or single static reference.
+ for (int i = wmsRefs.size() - 1; i >= 0; i--) {
+ if (wmsRefs.get(i).get() == null) {
+ return;
+ }
+ }
+ fail("WMS instance is leaked");
+ }
+
+ private static void applyRule(Predicate<SystemServicesTestRule> action) throws Throwable {
+ final SystemServicesTestRule wmsRule = new SystemServicesTestRule();
+ wmsRule.apply(new Statement() {
@Override
public void evaluate() throws Throwable {
- testRan[0] = true;
+ if (!action.test(wmsRule)) {
+ throw new Throwable("A failing test!");
+ }
}
- };
- mWmsRule.apply(statement, null /* Description*/).evaluate();
- assertTrue(testRan[0]);
+ }, null /* description */).evaluate();
}
}
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
deleted file mode 100644
index 4fdf34c..0000000
--- a/startop/iorap/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2018 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
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
- name: "services.startop.iorap-javasources",
- srcs: ["src/**/*.java"],
- path: "src",
- visibility: ["//visibility:private"],
-}
-
-filegroup {
- name: "services.startop.iorap-sources",
- srcs: [
- ":services.startop.iorap-javasources",
- ":iorap-aidl",
- ],
- visibility: ["//frameworks/base/services:__subpackages__"],
-}
-
-java_library_static {
- name: "services.startop.iorap",
- srcs: [":services.startop.iorap-sources"],
- libs: ["services.core"],
-}
diff --git a/startop/iorap/TEST_MAPPING b/startop/iorap/TEST_MAPPING
deleted file mode 100644
index 8c9d4df..0000000
--- a/startop/iorap/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "libiorap-java-tests"
- }
- ],
- "imports": [
- {
- "path": "system/iorap"
- }
- ]
-}
diff --git a/startop/iorap/functional_tests/Android.bp b/startop/iorap/functional_tests/Android.bp
deleted file mode 100644
index 43c6155..0000000
--- a/startop/iorap/functional_tests/Android.bp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2020 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
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-android_test {
- name: "iorap-functional-tests",
- srcs: ["src/**/*.java"],
- data: [":iorap-functional-test-apps"],
- static_libs: [
- // Non-test dependencies
- // library under test
- "services.startop.iorap",
- // Test Dependencies
- // test android dependencies
- "platform-test-annotations",
- "androidx.test.rules",
- "androidx.test.ext.junit",
- "androidx.test.uiautomator_uiautomator",
- // test framework dependencies
- "truth-prebuilt",
- ],
- dxflags: ["--multi-dex"],
- test_suites: ["device-tests"],
- compile_multilib: "both",
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- certificate: "platform",
- platform_apis: true,
-}
diff --git a/startop/iorap/functional_tests/AndroidManifest.xml b/startop/iorap/functional_tests/AndroidManifest.xml
deleted file mode 100644
index 6bddc4a3..0000000
--- a/startop/iorap/functional_tests/AndroidManifest.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<!--suppress AndroidUnknownAttribute -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.startop.iorap.tests"
- android:sharedUserId="com.google.android.startop.iorap.tests.functional"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <!--suppress AndroidDomInspection -->
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.google.android.startop.iorap.tests" />
-
- <!--
- 'debuggable=true' is required to properly load mockito jvmti dependencies,
- otherwise it gives the following error at runtime:
-
- Openjdkjvmti plugin was loaded on a non-debuggable Runtime.
- Plugin was loaded too late to change runtime state to DEBUGGABLE. -->
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
-</manifest>
diff --git a/startop/iorap/functional_tests/AndroidTest.xml b/startop/iorap/functional_tests/AndroidTest.xml
deleted file mode 100644
index 31d4f6c..0000000
--- a/startop/iorap/functional_tests/AndroidTest.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-
-<configuration description="Runs iorap-functional-tests.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-instrumentation" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="iorap-functional-tests.apk" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
- <target_preparer
- class="com.android.tradefed.targetprep.DeviceSetup">
-
- <!-- iorapd does not pick up the above changes until we restart it -->
- <option name="run-command" value="stop iorapd" />
-
- <!-- Clean up the existing iorap database. -->
- <option name="run-command" value="rm -r /data/misc/iorapd/*" />
- <option name="run-command" value="sleep 1" />
-
- <!-- Set system properties to enable perfetto tracing, readahead and detailed logging. -->
- <option name="run-command" value="setprop iorapd.perfetto.enable true" />
- <option name="run-command" value="setprop iorapd.readahead.enable true" />
- <option name="run-command" value="setprop iorapd.log.verbose true" />
-
- <option name="run-command" value="start iorapd" />
-
- <!-- give it some time to restart the service; otherwise the first unit test might fail -->
- <option name="run-command" value="sleep 1" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="abort-on-push-failure" value="true" />
- <option name="push-file"
- key="iorap_test_app_v1.apk"
- value="/data/misc/iorapd/iorap_test_app_v1.apk" />
- <option name="push-file"
- key="iorap_test_app_v2.apk"
- value="/data/misc/iorapd/iorap_test_app_v2.apk" />
- <option name="push-file"
- key="iorap_test_app_v3.apk"
- value="/data/misc/iorapd/iorap_test_app_v3.apk" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.google.android.startop.iorap.tests" />
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- <!-- test-timeout unit is ms, value = 30 min -->
- <option name="test-timeout" value="1800000" />
- </test>
-
-</configuration>
-
diff --git a/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java b/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
deleted file mode 100644
index 5352be6..0000000
--- a/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.google.android.startop.iorapd;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.Until;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-import java.util.Date;
-import java.util.function.BooleanSupplier;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.List;
-import java.text.SimpleDateFormat;
-
-/**
- * Test for the work flow of iorap.
- *
- * <p> This test tests the function of iorap from:
- * perfetto collection -> compilation -> prefetching -> version update -> perfetto collection.
- */
-@RunWith(AndroidJUnit4.class)
-public class IorapWorkFlowTest {
- private static final String TAG = "IorapWorkFlowTest";
-
- private static final String TEST_APP_VERSION_ONE_PATH = "/data/misc/iorapd/iorap_test_app_v1.apk";
- private static final String TEST_APP_VERSION_TWO_PATH = "/data/misc/iorapd/iorap_test_app_v2.apk";
- private static final String TEST_APP_VERSION_THREE_PATH = "/data/misc/iorapd/iorap_test_app_v3.apk";
-
- private static final String DB_PATH = "/data/misc/iorapd/sqlite.db";
- private static final Duration TIMEOUT = Duration.ofSeconds(300L);
-
- private UiDevice mDevice;
-
- @Before
- public void setUp() throws Exception {
- // Initialize UiDevice instance
- mDevice = UiDevice.getInstance(getInstrumentation());
-
- // Start from the home screen
- mDevice.pressHome();
-
- // Wait for launcher
- final String launcherPackage = mDevice.getLauncherPackageName();
- assertThat(launcherPackage, notNullValue());
- mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), TIMEOUT.getSeconds());
- }
-
- @After
- public void tearDown() throws Exception {
- String packageName = "com.example.ioraptestapp";
- uninstallApk(packageName);
- }
-
- @Test (timeout = 300000)
- public void testNormalWorkFlow() throws Exception {
- assertThat(mDevice, notNullValue());
-
- // Install test app version one
- installApk(TEST_APP_VERSION_ONE_PATH);
- String packageName = "com.example.ioraptestapp";
- String activityName = "com.example.ioraptestapp.MainActivity";
-
- // Perfetto trace collection phase.
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/1L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/1L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/1L));
-
- // Trigger maintenance service for compilation.
- TimeUnit.SECONDS.sleep(5L);
- assertTrue(compile(packageName, activityName, /*version=*/1L));
-
- // Run app with prefetching
- assertTrue(startAppWithCompiledTrace(
- packageName, activityName, /*version=*/1L));
- }
-
- @Test (timeout = 300000)
- public void testUpdateApp() throws Exception {
- assertThat(mDevice, notNullValue());
-
- // Install test app version two,
- String packageName = "com.example.ioraptestapp";
- String activityName = "com.example.ioraptestapp.MainActivity";
- installApk(TEST_APP_VERSION_TWO_PATH);
-
- // Perfetto trace collection phase.
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/2L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/2L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/2L));
-
- // Trigger maintenance service for compilation.
- TimeUnit.SECONDS.sleep(5L);
- assertTrue(compile(packageName, activityName, /*version=*/2L));
-
- // Run app with prefetching
- assertTrue(startAppWithCompiledTrace(
- packageName, activityName, /*version=*/2L));
-
- // Update test app to version 3
- installApk(TEST_APP_VERSION_THREE_PATH);
-
- // Rerun app, should do pefetto tracing.
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/3L));
- }
-
- private static void installApk(String apkPath) throws Exception {
- // Disable the selinux to allow pm install apk in the dir.
- executeShellCommand("setenforce 0");
- executeShellCommand("pm install -r -d " + apkPath);
- executeShellCommand("setenforce 1");
-
- }
-
- private static void uninstallApk(String apkPath) throws Exception {
- executeShellCommand("pm uninstall " + apkPath);
- }
-
- /**
- * Starts the testing app to collect the perfetto trace.
- *
- * @param expectPerfettoTraceCount is the expected count of perfetto traces.
- */
- private boolean startAppForPerfettoTrace(
- String packageName, String activityName, long version)
- throws Exception {
- LogcatTimestamp timestamp = runAppOnce(packageName, activityName);
- return waitForPerfettoTraceSavedFromLogcat(
- packageName, activityName, version, timestamp);
- }
-
- private boolean startAppWithCompiledTrace(
- String packageName, String activityName, long version)
- throws Exception {
- LogcatTimestamp timestamp = runAppOnce(packageName, activityName);
- return waitForPrefetchingFromLogcat(
- packageName, activityName, version, timestamp);
- }
-
- private LogcatTimestamp runAppOnce(String packageName, String activityName) throws Exception {
- // Close the specified app if it's open
- closeApp(packageName);
- LogcatTimestamp timestamp = new LogcatTimestamp();
- // Launch the specified app
- startApp(packageName, activityName);
- // Wait for the app to appear
- mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), TIMEOUT.getSeconds());
- return timestamp;
- }
-
- // Invokes the maintenance to compile the perfetto traces to compiled trace.
- private boolean compile(
- String packageName, String activityName, long version) throws Exception {
- // The job id (283673059) is defined in class IorapForwardingService.
- executeShellCommandViaTmpFile("cmd jobscheduler run -f android 283673059");
- return waitForFileExistence(getCompiledTracePath(packageName, activityName, version));
- }
-
- private String getCompiledTracePath(
- String packageName, String activityName, long version) {
- return String.format(
- "/data/misc/iorapd/%s/%d/%s/compiled_traces/compiled_trace.pb",
- packageName, version, activityName);
- }
-
- /**
- * Starts the testing app.
- */
- private void startApp(String packageName, String activityName) throws Exception {
- executeShellCommandViaTmpFile(
- String.format("am start %s/%s", packageName, activityName));
- }
-
- /**
- * Closes the testing app.
- * <p> Keep trying to kill the process of the app until no process of the app package
- * appears.</p>
- */
- private void closeApp(String packageName) throws Exception {
- while (true) {
- String pid = executeShellCommand("pidof " + packageName);
- if (pid.isEmpty()) {
- Log.i(TAG, "Closed app " + packageName);
- return;
- }
- executeShellCommand("kill -9 " + pid);
- TimeUnit.SECONDS.sleep(1L);
- }
- }
-
- /** Waits for a file to appear. */
- private boolean waitForFileExistence(String fileName) throws Exception {
- return retryWithTimeout(TIMEOUT, () -> {
- try {
- String fileExists = executeShellCommandViaTmpFile(
- String.format("test -f %s; echo $?", fileName));
- Log.i(TAG, fileName + " existence is " + fileExists);
- return fileExists.trim().equals("0");
- } catch (Exception e) {
- Log.i(TAG, e.getMessage());
- return false;
- }
- });
- }
-
- /** Waits for the perfetto trace saved message from logcat. */
- private boolean waitForPerfettoTraceSavedFromLogcat(
- String packageName, String activityName, long version, LogcatTimestamp timestamp)
- throws Exception {
- Pattern p = Pattern.compile(".*"
- + getPerfettoTraceSavedIndicator(packageName, activityName, version)
- + "(.*[.]perfetto_trace[.]pb)\n.*", Pattern.DOTALL);
-
- return retryWithTimeout(TIMEOUT, () -> {
- try {
- String log = timestamp.getLogcatAfter();
- Matcher m = p.matcher(log);
- Log.d(TAG, "Tries to find perfetto trace...");
- if (!m.matches()) {
- Log.i(TAG, "Cannot find perfetto trace saved in log.");
- return false;
- }
- String filePath = m.group(1);
- Log.i(TAG, "Perfetto trace is saved to " + filePath);
- return true;
- } catch(Exception e) {
- Log.e(TAG, e.getMessage());
- return false;
- }
- });
- }
-
- private String getPerfettoTraceSavedIndicator(
- String packageName, String activityName, long version) {
- return String.format(
- "Perfetto TraceBuffer saved to file: /data/misc/iorapd/%s/%d/%s/raw_traces/",
- packageName, version, activityName);
- }
-
- /**
- * Waits for the prefetching log in the logcat.
- *
- * <p> When prefetching works, the perfetto traces should not be collected. </p>
- */
- private boolean waitForPrefetchingFromLogcat(
- String packageName, String activityName, long version, LogcatTimestamp timestamp)
- throws Exception {
- Pattern p = Pattern.compile(
- ".*" + getReadaheadIndicator(packageName, activityName, version) +
- ".*Total File Paths=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
- + ".*Total Entries=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
- + ".*Total Bytes=(\\d+) \\(good: (\\d+[.]?\\d*)%\\).*",
- Pattern.DOTALL);
-
- return retryWithTimeout(TIMEOUT, () -> {
- try {
- String log = timestamp.getLogcatAfter();
- Matcher m = p.matcher(log);
- if (!m.matches()) {
- Log.i(TAG, "Cannot find readahead log.");
- return false;
- }
-
- int totalFilePath = Integer.parseInt(m.group(1));
- float totalFilePathGoodRate = Float.parseFloat(m.group(2)) / 100;
- int totalEntries = Integer.parseInt(m.group(3));
- float totalEntriesGoodRate = Float.parseFloat(m.group(4)) / 100;
- int totalBytes = Integer.parseInt(m.group(5));
- float totalBytesGoodRate = Float.parseFloat(m.group(6)) / 100;
-
- Log.i(TAG, String.format(
- "totalFilePath: %d (good %.2f) totalEntries: %d (good %.2f) totalBytes: %d (good %.2f)",
- totalFilePath, totalFilePathGoodRate, totalEntries, totalEntriesGoodRate, totalBytes,
- totalBytesGoodRate));
-
- return totalFilePath > 0 &&
- totalEntries > 0 &&
- totalBytes > 0 &&
- totalFilePathGoodRate > 0.5 &&
- totalEntriesGoodRate > 0.5 &&
- totalBytesGoodRate > 0.5;
- } catch(Exception e) {
- return false;
- }
- });
- }
-
- private static String getReadaheadIndicator(
- String packageName, String activityName, long version) {
- return String.format(
- "Description = /data/misc/iorapd/%s/%d/%s/compiled_traces/compiled_trace.pb",
- packageName, version, activityName);
- }
-
- /** Retry until timeout. */
- private boolean retryWithTimeout(Duration timeout, BooleanSupplier supplier) throws Exception {
- long totalSleepTimeSeconds = 0L;
- long sleepIntervalSeconds = 2L;
- while (true) {
- if (supplier.getAsBoolean()) {
- return true;
- }
- TimeUnit.SECONDS.sleep(sleepIntervalSeconds);
- totalSleepTimeSeconds += sleepIntervalSeconds;
- if (totalSleepTimeSeconds > timeout.getSeconds()) {
- return false;
- }
- }
- }
-
- /**
- * Executes command in adb shell via a tmp file.
- *
- * <p> This should be run as root.</p>
- */
- private static String executeShellCommandViaTmpFile(String cmd) throws Exception {
- Log.i(TAG, "Execute via tmp file: " + cmd);
- Path tmp = null;
- try {
- tmp = Files.createTempFile(/*prefix=*/null, /*suffix=*/".sh");
- Files.write(tmp, cmd.getBytes(StandardCharsets.UTF_8));
- tmp.toFile().setExecutable(true);
- return UiDevice.getInstance(
- InstrumentationRegistry.getInstrumentation()).
- executeShellCommand(tmp.toString());
- } finally {
- if (tmp != null) {
- Files.delete(tmp);
- }
- }
- }
-
- /**
- * Executes command in adb shell.
- *
- * <p> This should be run as root.</p>
- */
- private static String executeShellCommand(String cmd) throws Exception {
- Log.i(TAG, "Execute: " + cmd);
- return UiDevice.getInstance(
- InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
- }
-
- static class LogcatTimestamp {
- private String epochTime;
-
- public LogcatTimestamp() throws Exception{
- long currentTimeMillis = System.currentTimeMillis();
- epochTime = String.format(
- "%d.%03d", currentTimeMillis/1000, currentTimeMillis%1000);
- Log.i(TAG, "Current logcat timestamp is " + epochTime);
- }
-
- // For example, 1585264100.000
- public String getEpochTime() {
- return epochTime;
- }
-
- // Gets the logcat after this epoch time.
- public String getLogcatAfter() throws Exception {
- return executeShellCommandViaTmpFile(
- "logcat -v epoch -t '" + epochTime + "'");
- }
- }
-}
-
diff --git a/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java b/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java
deleted file mode 100644
index 1d38f4c..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Provide a hint to iorapd that an activity has transitioned state.<br /><br />
- *
- * Knowledge of when an activity starts/stops can be used by iorapd to increase system
- * performance (e.g. by launching perfetto tracing to record an io profile, or by
- * playing back an ioprofile via readahead) over the long run.<br /><br />
- *
- * /@see com.google.android.startop.iorap.IIorap#onActivityHintEvent<br /><br />
- *
- * Once an activity hint is in {@link #TYPE_STARTED} it must transition to another type.
- * All other states could be terminal, see below: <br /><br />
- *
- * <pre>
- *
- * ┌──────────────────────────────────────┐
- * │ ▼
- * ┌─────────┐ ╔════════════════╗ ╔═══════════╗
- * ──▶ │ STARTED │ ──▶ ║ COMPLETED ║ ──▶ ║ CANCELLED ║
- * └─────────┘ ╚════════════════╝ ╚═══════════╝
- * │
- * │
- * ▼
- * ╔════════════════╗
- * ║ POST_COMPLETED ║
- * ╚════════════════╝
- *
- * </pre> <!-- system/iorap/docs/binder/ActivityHint.dot -->
- *
- * @hide
- */
-public class ActivityHintEvent implements Parcelable {
-
- public static final int TYPE_STARTED = 0;
- public static final int TYPE_CANCELLED = 1;
- public static final int TYPE_COMPLETED = 2;
- public static final int TYPE_POST_COMPLETED = 3;
- private static final int TYPE_MAX = TYPE_POST_COMPLETED;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_STARTED,
- TYPE_CANCELLED,
- TYPE_COMPLETED,
- TYPE_POST_COMPLETED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
- public final ActivityInfo activityInfo;
-
- public ActivityHintEvent(@Type int type, ActivityInfo activityInfo) {
- this.type = type;
- this.activityInfo = activityInfo;
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(activityInfo, "activityInfo");
- }
-
- @Override
- public String toString() {
- return String.format("{type: %d, activityInfo: %s}", type, activityInfo);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof ActivityHintEvent) {
- return equals((ActivityHintEvent) other);
- }
- return false;
- }
-
- private boolean equals(ActivityHintEvent other) {
- return type == other.type &&
- Objects.equals(activityInfo, other.activityInfo);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- activityInfo.writeToParcel(out, flags);
- }
-
- private ActivityHintEvent(Parcel in) {
- this.type = in.readInt();
- this.activityInfo = ActivityInfo.CREATOR.createFromParcel(in);
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<ActivityHintEvent> CREATOR
- = new Parcelable.Creator<ActivityHintEvent>() {
- public ActivityHintEvent createFromParcel(Parcel in) {
- return new ActivityHintEvent(in);
- }
-
- public ActivityHintEvent[] newArray(int size) {
- return new ActivityHintEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java b/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java
deleted file mode 100644
index f47a42c..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import java.util.Objects;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/**
- * Provide minimal information for launched activities to iorap.<br /><br />
- *
- * This uniquely identifies a system-wide activity by providing the {@link #packageName} and
- * {@link #activityName}.
- *
- * @see ActivityHintEvent
- * @see AppIntentEvent
- *
- * @hide
- */
-public class ActivityInfo implements Parcelable {
-
- /** The name of the package, for example {@code com.android.calculator}. */
- public final String packageName;
- /** The name of the activity, for example {@code .activities.activity.MainActivity} */
- public final String activityName;
-
- public ActivityInfo(String packageName, String activityName) {
- this.packageName = packageName;
- this.activityName = activityName;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- Objects.requireNonNull(packageName, "packageName");
- Objects.requireNonNull(activityName, "activityName");
- }
-
- @Override
- public String toString() {
- return String.format("{packageName: %s, activityName: %s}", packageName, activityName);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof ActivityInfo) {
- return equals((ActivityInfo) other);
- }
- return false;
- }
-
- private boolean equals(ActivityInfo other) {
- return Objects.equals(packageName, other.packageName) &&
- Objects.equals(activityName, other.activityName);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(packageName);
- out.writeString(activityName);
- }
-
- private ActivityInfo(Parcel in) {
- packageName = in.readString();
- activityName = in.readString();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<ActivityInfo> CREATOR
- = new Parcelable.Creator<ActivityInfo>() {
- public ActivityInfo createFromParcel(Parcel in) {
- return new ActivityInfo(in);
- }
-
- public ActivityInfo[] newArray(int size) {
- return new ActivityInfo[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java
deleted file mode 100644
index 1cd37b5..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Notifications for iorapd specifying when a system-wide intent defaults change.<br /><br />
- *
- * Intent defaults provide a mechanism for an app to register itself as an automatic handler.
- * For example the camera app might be registered as the default handler for
- * {@link android.provider.MediaStore#INTENT_ACTION_STILL_IMAGE_CAMERA} intent. Subsequently,
- * if an arbitrary other app requests for a still image camera photo to be taken, the system
- * will launch the respective default camera app to be launched to handle that request.<br /><br />
- *
- * In some cases iorapd might need to know default intents, e.g. for boot-time pinning of
- * applications that resolve from the default intent. If the application would now be resolved
- * differently, iorapd would unpin the old application and pin the new application.<br /><br />
- *
- * @hide
- */
-public class AppIntentEvent implements Parcelable {
-
- /** @see android.content.Intent#CATEGORY_DEFAULT */
- public static final int TYPE_DEFAULT_INTENT_CHANGED = 0;
- private static final int TYPE_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_DEFAULT_INTENT_CHANGED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- public final ActivityInfo oldActivityInfo;
- public final ActivityInfo newActivityInfo;
-
- // TODO: Probably need the corresponding action here as well.
-
- public static AppIntentEvent createDefaultIntentChanged(ActivityInfo oldActivityInfo,
- ActivityInfo newActivityInfo) {
- return new AppIntentEvent(TYPE_DEFAULT_INTENT_CHANGED, oldActivityInfo,
- newActivityInfo);
- }
-
- private AppIntentEvent(@Type int type, ActivityInfo oldActivityInfo,
- ActivityInfo newActivityInfo) {
- this.type = type;
- this.oldActivityInfo = oldActivityInfo;
- this.newActivityInfo = newActivityInfo;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(oldActivityInfo, "oldActivityInfo");
- Objects.requireNonNull(oldActivityInfo, "newActivityInfo");
- }
-
- @Override
- public String toString() {
- return String.format("{oldActivityInfo: %s, newActivityInfo: %s}", oldActivityInfo,
- newActivityInfo);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof AppIntentEvent) {
- return equals((AppIntentEvent) other);
- }
- return false;
- }
-
- private boolean equals(AppIntentEvent other) {
- return type == other.type &&
- Objects.equals(oldActivityInfo, other.oldActivityInfo) &&
- Objects.equals(newActivityInfo, other.newActivityInfo);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- oldActivityInfo.writeToParcel(out, flags);
- newActivityInfo.writeToParcel(out, flags);
- }
-
- private AppIntentEvent(Parcel in) {
- this.type = in.readInt();
- this.oldActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
- this.newActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<AppIntentEvent> CREATOR
- = new Parcelable.Creator<AppIntentEvent>() {
- public AppIntentEvent createFromParcel(Parcel in) {
- return new AppIntentEvent(in);
- }
-
- public AppIntentEvent[] newArray(int size) {
- return new AppIntentEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
deleted file mode 100644
index 8263e0a..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.annotation.LongDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.server.wm.ActivityMetricsLaunchObserver;
-import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
-import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * Provide a hint to iorapd that an app launch sequence has transitioned state.<br /><br />
- *
- * Knowledge of when an activity starts/stops can be used by iorapd to increase system
- * performance (e.g. by launching perfetto tracing to record an io profile, or by
- * playing back an ioprofile via readahead) over the long run.<br /><br />
- *
- * /@see com.google.android.startop.iorap.IIorap#onAppLaunchEvent <br /><br />
- * @see com.android.server.wm.ActivityMetricsLaunchObserver
- * ActivityMetricsLaunchObserver for the possible event states.
- * @hide
- */
-public abstract class AppLaunchEvent implements Parcelable {
- @LongDef
- @Retention(RetentionPolicy.SOURCE)
- public @interface SequenceId {}
-
- public final @SequenceId
- long sequenceId;
-
- protected AppLaunchEvent(@SequenceId long sequenceId) {
- this.sequenceId = sequenceId;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof AppLaunchEvent) {
- return equals((AppLaunchEvent) other);
- }
- return false;
- }
-
- protected boolean equals(AppLaunchEvent other) {
- return sequenceId == other.sequenceId;
- }
-
-
- @Override
- public String toString() {
- return getClass().getSimpleName() +
- "{" + "sequenceId=" + Long.toString(sequenceId) +
- toStringBody() + "}";
- }
-
- protected String toStringBody() { return ""; };
-
- // List of possible variants:
-
- public static final class IntentStarted extends AppLaunchEvent {
- @NonNull
- public final Intent intent;
- public final long timestampNs;
-
- public IntentStarted(@SequenceId long sequenceId,
- Intent intent,
- long timestampNs) {
- super(sequenceId);
- this.intent = intent;
- this.timestampNs = timestampNs;
-
- Objects.requireNonNull(intent, "intent");
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof IntentStarted) {
- return intent.equals(((IntentStarted)other).intent) &&
- timestampNs == ((IntentStarted)other).timestampNs &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return ", intent=" + intent.toString() +
- " , timestampNs=" + Long.toString(timestampNs);
- }
-
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- IntentProtoParcelable.write(p, intent, flags);
- p.writeLong(timestampNs);
- }
-
- IntentStarted(Parcel p) {
- super(p);
- intent = IntentProtoParcelable.create(p);
- timestampNs = p.readLong();
- }
- }
-
- public static final class IntentFailed extends AppLaunchEvent {
- public IntentFailed(@SequenceId long sequenceId) {
- super(sequenceId);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof IntentFailed) {
- return super.equals(other);
- }
- return false;
- }
-
- IntentFailed(Parcel p) {
- super(p);
- }
- }
-
- public static abstract class BaseWithActivityRecordData extends AppLaunchEvent {
- public final @NonNull
- @ActivityRecordProto byte[] activityRecordSnapshot;
-
- protected BaseWithActivityRecordData(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot) {
- super(sequenceId);
- activityRecordSnapshot = snapshot;
-
- Objects.requireNonNull(snapshot, "snapshot");
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof BaseWithActivityRecordData) {
- return (Arrays.equals(activityRecordSnapshot,
- ((BaseWithActivityRecordData)other).activityRecordSnapshot)) &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return ", " + new String(activityRecordSnapshot);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags);
- }
-
- BaseWithActivityRecordData(Parcel p) {
- super(p);
- activityRecordSnapshot = ActivityRecordProtoParcelable.create(p);
- }
- }
-
- public static final class ActivityLaunched extends BaseWithActivityRecordData {
- public final @ActivityMetricsLaunchObserver.Temperature
- int temperature;
-
- public ActivityLaunched(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot,
- @ActivityMetricsLaunchObserver.Temperature int temperature) {
- super(sequenceId, snapshot);
- this.temperature = temperature;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ActivityLaunched) {
- return temperature == ((ActivityLaunched)other).temperature &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", temperature=" + Integer.toString(temperature);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- p.writeInt(temperature);
- }
-
- ActivityLaunched(Parcel p) {
- super(p);
- temperature = p.readInt();
- }
- }
-
- public static final class ActivityLaunchFinished extends BaseWithActivityRecordData {
- public final long timestampNs;
-
- public ActivityLaunchFinished(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot,
- long timestampNs) {
- super(sequenceId, snapshot);
- this.timestampNs = timestampNs;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ActivityLaunchFinished) {
- return timestampNs == ((ActivityLaunchFinished)other).timestampNs &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- p.writeLong(timestampNs);
- }
-
- ActivityLaunchFinished(Parcel p) {
- super(p);
- timestampNs = p.readLong();
- }
- }
-
- public static class ActivityLaunchCancelled extends AppLaunchEvent {
- public final @Nullable @ActivityRecordProto byte[] activityRecordSnapshot;
-
- public ActivityLaunchCancelled(@SequenceId long sequenceId,
- @Nullable @ActivityRecordProto byte[] snapshot) {
- super(sequenceId);
- activityRecordSnapshot = snapshot;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ActivityLaunchCancelled) {
- return Arrays.equals(activityRecordSnapshot,
- ((ActivityLaunchCancelled)other).activityRecordSnapshot) &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", " + new String(activityRecordSnapshot);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- if (activityRecordSnapshot != null) {
- p.writeBoolean(true);
- ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags);
- } else {
- p.writeBoolean(false);
- }
- }
-
- ActivityLaunchCancelled(Parcel p) {
- super(p);
- if (p.readBoolean()) {
- activityRecordSnapshot = ActivityRecordProtoParcelable.create(p);
- } else {
- activityRecordSnapshot = null;
- }
- }
- }
-
- public static final class ReportFullyDrawn extends BaseWithActivityRecordData {
- public final long timestampNs;
-
- public ReportFullyDrawn(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot,
- long timestampNs) {
- super(sequenceId, snapshot);
- this.timestampNs = timestampNs;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ReportFullyDrawn) {
- return timestampNs == ((ReportFullyDrawn)other).timestampNs &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- p.writeLong(timestampNs);
- }
-
- ReportFullyDrawn(Parcel p) {
- super(p);
- timestampNs = p.readLong();
- }
- }
-
- @Override
- public @ContentsFlags int describeContents() { return 0; }
-
- @Override
- public void writeToParcel(Parcel p, @WriteFlags int flags) {
- p.writeInt(getTypeIndex());
-
- writeToParcelImpl(p, flags);
- }
-
-
- public static Creator<AppLaunchEvent> CREATOR =
- new Creator<AppLaunchEvent>() {
- @Override
- public AppLaunchEvent createFromParcel(Parcel source) {
- int typeIndex = source.readInt();
-
- Class<?> kls = getClassFromTypeIndex(typeIndex);
- if (kls == null) {
- throw new IllegalArgumentException("Invalid type index: " + typeIndex);
- }
-
- try {
- return (AppLaunchEvent) kls.getConstructor(Parcel.class).newInstance(source);
- } catch (InstantiationException e) {
- throw new AssertionError(e);
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
- } catch (InvocationTargetException e) {
- throw new AssertionError(e);
- } catch (NoSuchMethodException e) {
- throw new AssertionError(e);
- }
- }
-
- @Override
- public AppLaunchEvent[] newArray(int size) {
- return new AppLaunchEvent[0];
- }
- };
-
- protected void writeToParcelImpl(Parcel p, int flags) {
- p.writeLong(sequenceId);
- }
-
- protected AppLaunchEvent(Parcel p) {
- sequenceId = p.readLong();
- }
-
- private int getTypeIndex() {
- for (int i = 0; i < sTypes.length; ++i) {
- if (sTypes[i].equals(this.getClass())) {
- return i;
- }
- }
- throw new AssertionError("sTypes did not include this type: " + this.getClass());
- }
-
- private static @Nullable Class<?> getClassFromTypeIndex(int typeIndex) {
- if (typeIndex >= 0 && typeIndex < sTypes.length) {
- return sTypes[typeIndex];
- }
- return null;
- }
-
- // Index position matters: It is used to encode the specific type in parceling.
- // Keep up-to-date with C++ side.
- private static Class<?>[] sTypes = new Class[] {
- IntentStarted.class,
- IntentFailed.class,
- ActivityLaunched.class,
- ActivityLaunchFinished.class,
- ActivityLaunchCancelled.class,
- ReportFullyDrawn.class,
- };
-
- public static class ActivityRecordProtoParcelable {
- public static void write(Parcel p, @ActivityRecordProto byte[] activityRecordSnapshot,
- int flags) {
- p.writeByteArray(activityRecordSnapshot);
- }
-
- public static @ActivityRecordProto byte[] create(Parcel p) {
- byte[] data = p.createByteArray();
-
- return data;
- }
- }
-
- public static class IntentProtoParcelable {
- private static final int INTENT_PROTO_CHUNK_SIZE = 1024;
-
- public static void write(Parcel p, @NonNull Intent intent, int flags) {
- // There does not appear to be a way to 'reset' a ProtoOutputBuffer stream,
- // so create a new one every time.
- final ProtoOutputStream protoOutputStream =
- new ProtoOutputStream(INTENT_PROTO_CHUNK_SIZE);
- // Write this data out as the top-most IntentProto (i.e. it is not a sub-object).
- intent.dumpDebug(protoOutputStream);
- final byte[] bytes = protoOutputStream.getBytes();
-
- p.writeByteArray(bytes);
- }
-
- // TODO: Should be mockable for testing?
- // We cannot deserialize in the platform because we don't have a 'readFromProto'
- // code.
- public static @NonNull Intent create(Parcel p) {
- // This will "read" the correct amount of data, but then we discard it.
- byte[] data = p.createByteArray();
-
- // Never called by real code in a platform, this binder API is implemented only in C++.
- return new Intent("<cannot deserialize IntentProto>");
- }
- }
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java b/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java
deleted file mode 100644
index 34aedd7..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-/**
- * Convenience short-hand to throw {@link IllegalAccessException} when the arguments
- * are out-of-range.
- */
-public class CheckHelpers {
- /** @throws IllegalAccessException if {@param type} is not in {@code [0..maxValue]} */
- public static void checkTypeInRange(int type, int maxValue) {
- if (type < 0) {
- throw new IllegalArgumentException(
- String.format("type must be non-negative (value=%d)", type));
- }
- if (type > maxValue) {
- throw new IllegalArgumentException(
- String.format("type out of range (value=%d, max=%d)", type, maxValue));
- }
- }
-
- /** @throws IllegalAccessException if {@param state} is not in {@code [0..maxValue]} */
- public static void checkStateInRange(int state, int maxValue) {
- if (state < 0) {
- throw new IllegalArgumentException(
- String.format("state must be non-negative (value=%d)", state));
- }
- if (state > maxValue) {
- throw new IllegalArgumentException(
- String.format("state out of range (value=%d, max=%d)", state, maxValue));
- }
- }
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java b/startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java
deleted file mode 100644
index 72c5eaa..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.google.android.startop.iorap;
-
-import android.annotation.NonNull;
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Notifications for iorapd specifying when a package is updated by dexopt service.<br /><br />
- *
- * @hide
- */
-public class DexOptEvent implements Parcelable {
- public static final int TYPE_PACKAGE_UPDATE = 0;
- private static final int TYPE_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_PACKAGE_UPDATE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
- public final String packageName;
-
- @NonNull
- public static DexOptEvent createPackageUpdate(String packageName) {
- return new DexOptEvent(TYPE_PACKAGE_UPDATE, packageName);
- }
-
- private DexOptEvent(@Type int type, String packageName) {
- this.type = type;
- this.packageName = packageName;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(packageName, "packageName");
- }
-
- @Override
- public String toString() {
- return String.format("{DexOptEvent: packageName: %s}", packageName);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof DexOptEvent) {
- return equals((DexOptEvent) other);
- }
- return false;
- }
-
- private boolean equals(DexOptEvent other) {
- return packageName.equals(other.packageName);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- out.writeString(packageName);
- }
-
- private DexOptEvent(Parcel in) {
- this.type = in.readInt();
- this.packageName = in.readString();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<DexOptEvent> CREATOR
- = new Parcelable.Creator<DexOptEvent>() {
- public DexOptEvent createFromParcel(Parcel in) {
- return new DexOptEvent(in);
- }
-
- public DexOptEvent[] newArray(int size) {
- return new DexOptEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
deleted file mode 100644
index dcaff26..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.google.android.startop.iorap;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.util.Log;
-
-import com.android.server.wm.ActivityMetricsLaunchObserver;
-
-import java.io.StringWriter;
-import java.io.PrintWriter;
-
-/**
- * A validator to check the correctness of event sequence during app startup.
- *
- * <p> A valid state transition of event sequence is shown as the following:
- *
- * <pre>
- *
- * +--------------------+
- * | |
- * | INIT |
- * | |
- * +--------------------+
- * |
- * |
- * ↓
- * +--------------------+
- * | |
- * +-------------------| INTENT_STARTED | ←--------------------------------+
- * | | | |
- * | +--------------------+ |
- * | | |
- * | | |
- * ↓ ↓ |
- * +--------------------+ +--------------------+ |
- * | | | | |
- * | INTENT_FAILED | | ACTIVITY_LAUNCHED |------------------+ |
- * | | | | | |
- * +--------------------+ +--------------------+ | |
- * | | | |
- * | ↓ ↓ |
- * | +--------------------+ +--------------------+ |
- * | | | | | |
- * +------------------ | ACTIVITY_FINISHED | | ACTIVITY_CANCELLED | |
- * | | | | | |
- * | +--------------------+ +--------------------+ |
- * | | | |
- * | | | |
- * | ↓ | |
- * | +--------------------+ | |
- * | | | | |
- * | | REPORT_FULLY_DRAWN | | |
- * | | | | |
- * | +--------------------+ | |
- * | | | |
- * | | | |
- * | ↓ | |
- * | +--------------------+ | |
- * | | | | |
- * +-----------------→ | END |←-----------------+ |
- * | | |
- * +--------------------+ |
- * | |
- * | |
- * | |
- * +---------------------------------------------
- *
- * <p> END is not a real state in implementation. All states that points to END directly
- * could transition to INTENT_STARTED.
- *
- * <p> If any bad transition happened, the state becomse UNKNOWN. The UNKNOWN state
- * could be accumulated, because during the UNKNOWN state more IntentStarted may
- * be triggered. To recover from UNKNOWN to INIT, all the accumualted IntentStarted
- * should termniate.
- *
- * <p> During UNKNOWN state, each IntentStarted increases the accumulation, and any of
- * IntentFailed, ActivityLaunchCancelled and ActivityFinished decreases the accumulation.
- * ReportFullyDrawn doesn't impact the accumulation.
- */
-public class EventSequenceValidator implements ActivityMetricsLaunchObserver {
- static final String TAG = "EventSequenceValidator";
- /** $> adb shell 'setprop log.tag.EventSequenceValidator VERBOSE' */
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private State state = State.INIT;
- private long accIntentStartedEvents = 0;
-
- @Override
- public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("IntentStarted during UNKNOWN. " + intent);
- incAccIntentStartedEvents();
- return;
- }
-
- if (state != State.INIT &&
- state != State.INTENT_FAILED &&
- state != State.ACTIVITY_CANCELLED &&
- state != State.ACTIVITY_FINISHED &&
- state != State.REPORT_FULLY_DRAWN) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.INTENT_STARTED));
- incAccIntentStartedEvents();
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.INTENT_STARTED));
- state = State.INTENT_STARTED;
- }
-
- @Override
- public void onIntentFailed() {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onIntentFailed during UNKNOWN.");
- decAccIntentStartedEvents();
- return;
- }
- if (state != State.INTENT_STARTED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.INTENT_FAILED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.INTENT_FAILED));
- state = State.INTENT_FAILED;
- }
-
- @Override
- public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
- @Temperature int temperature) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onActivityLaunched during UNKNOWN.");
- return;
- }
- if (state != State.INTENT_STARTED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
- state = State.ACTIVITY_LAUNCHED;
- }
-
- @Override
- public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onActivityLaunchCancelled during UNKNOWN.");
- decAccIntentStartedEvents();
- return;
- }
- if (state != State.ACTIVITY_LAUNCHED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.ACTIVITY_CANCELLED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_CANCELLED));
- state = State.ACTIVITY_CANCELLED;
- }
-
- @Override
- public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onActivityLaunchFinished during UNKNOWN.");
- decAccIntentStartedEvents();
- return;
- }
-
- if (state != State.ACTIVITY_LAUNCHED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.ACTIVITY_FINISHED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_FINISHED));
- state = State.ACTIVITY_FINISHED;
- }
-
- @Override
- public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onReportFullyDrawn during UNKNOWN.");
- return;
- }
- if (state == State.INIT) {
- return;
- }
-
- if (state != State.ACTIVITY_FINISHED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
- state = State.REPORT_FULLY_DRAWN;
- }
-
- enum State {
- INIT,
- INTENT_STARTED,
- INTENT_FAILED,
- ACTIVITY_LAUNCHED,
- ACTIVITY_CANCELLED,
- ACTIVITY_FINISHED,
- REPORT_FULLY_DRAWN,
- UNKNOWN,
- }
-
- private void incAccIntentStartedEvents() {
- if (accIntentStartedEvents < 0) {
- throw new AssertionError("The number of unknowns cannot be negative");
- }
- if (accIntentStartedEvents == 0) {
- state = State.UNKNOWN;
- }
- ++accIntentStartedEvents;
- Log.i(TAG,
- String.format("inc AccIntentStartedEvents to %d", accIntentStartedEvents));
- }
-
- private void decAccIntentStartedEvents() {
- if (accIntentStartedEvents <= 0) {
- throw new AssertionError("The number of unknowns cannot be negative");
- }
- if(accIntentStartedEvents == 1) {
- state = State.INIT;
- }
- --accIntentStartedEvents;
- Log.i(TAG,
- String.format("dec AccIntentStartedEvents to %d", accIntentStartedEvents));
- }
-
- private void logWarningWithStackTrace(String log) {
- if (DEBUG) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- new Throwable("EventSequenceValidator#getStackTrace").printStackTrace(pw);
- Log.wtf(TAG, String.format("%s\n%s", log, sw));
- }
- }
-}
-
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
deleted file mode 100644
index 1a0e526..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-// TODO: rename to com.android.server.startop.iorap
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobService;
-import android.app.job.JobScheduler;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.os.IBinder;
-import android.os.IBinder.DeathRecipient;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.provider.DeviceConfig;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.IoThread;
-import com.android.server.LocalServices;
-import com.android.server.SystemService;
-import com.android.server.pm.BackgroundDexOptService;
-import com.android.server.pm.PackageManagerService;
-import com.android.server.wm.ActivityMetricsLaunchObserver;
-import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
-import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature;
-import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
-import com.android.server.wm.ActivityTaskManagerInternal;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.BooleanSupplier;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * System-server-local proxy into the {@code IIorap} native service.
- */
-public class IorapForwardingService extends SystemService {
-
- public static final String TAG = "IorapForwardingService";
- /** $> adb shell 'setprop log.tag.IorapForwardingService VERBOSE' */
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- /** $> adb shell 'setprop ro.iorapd.enable true' */
- private static boolean IS_ENABLED = SystemProperties.getBoolean("ro.iorapd.enable", true);
- /** $> adb shell 'setprop iorapd.forwarding_service.wtf_crash true' */
- private static boolean WTF_CRASH = SystemProperties.getBoolean(
- "iorapd.forwarding_service.wtf_crash", false);
- private static final Duration TIMEOUT = Duration.ofSeconds(600L);
-
- // "Unique" job ID from the service name. Also equal to 283673059.
- public static final int JOB_ID_IORAPD = encodeEnglishAlphabetStringIntoInt("iorapd");
- // Run every 24 hours.
- public static final long JOB_INTERVAL_MS = TimeUnit.HOURS.toMillis(24);
-
- private IIorap mIorapRemote;
- private final Object mLock = new Object();
- /** Handle onBinderDeath by periodically trying to reconnect. */
- private final Handler mHandler =
- new BinderConnectionHandler(IoThread.getHandler().getLooper());
-
- private volatile IorapdJobService mJobService; // Write-once (null -> non-null forever).
- private volatile static IorapForwardingService sSelfService; // Write once (null -> non-null).
-
-
- /**
- * Atomics set to true if the JobScheduler requests an abort.
- */
- private final AtomicBoolean mAbortIdleCompilation = new AtomicBoolean(false);
-
- /**
- * Initializes the system service.
- * <p>
- * Subclasses must define a single argument constructor that accepts the context
- * and passes it to super.
- * </p>
- *
- * @param context The system server context.
- */
- public IorapForwardingService(Context context) {
- super(context);
-
- if (DEBUG) {
- Log.v(TAG, "IorapForwardingService (Context=" + context.toString() + ")");
- }
-
- if (sSelfService != null) {
- throw new AssertionError("only one service instance allowed");
- }
- sSelfService = this;
- }
-
- //<editor-fold desc="Providers">
- /*
- * Providers for external dependencies:
- * - These are marked as protected to allow tests to inject different values via mocks.
- */
-
- @VisibleForTesting
- protected ActivityMetricsLaunchObserverRegistry provideLaunchObserverRegistry() {
- ActivityTaskManagerInternal amtInternal =
- LocalServices.getService(ActivityTaskManagerInternal.class);
- ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
- amtInternal.getLaunchObserverRegistry();
- return launchObserverRegistry;
- }
-
- @VisibleForTesting
- protected IIorap provideIorapRemote() {
- IIorap iorap;
- try {
- iorap = IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"));
- } catch (ServiceManager.ServiceNotFoundException e) {
- Log.w(TAG, e.getMessage());
- return null;
- }
-
- try {
- iorap.asBinder().linkToDeath(provideDeathRecipient(), /*flags*/0);
- } catch (RemoteException e) {
- handleRemoteError(e);
- return null;
- }
-
- return iorap;
- }
-
- @VisibleForTesting
- protected DeathRecipient provideDeathRecipient() {
- return new DeathRecipient() {
- @Override
- public void binderDied() {
- Log.w(TAG, "iorapd has died");
- retryConnectToRemoteAndConfigure(/*attempts*/0);
-
- if (mJobService != null) {
- mJobService.onIorapdDisconnected();
- }
- }
- };
- }
-
- @VisibleForTesting
- protected boolean isIorapEnabled() {
- // These two mendel flags should match those in iorapd native process
- // system/iorapd/src/common/property.h
- boolean isTracingEnabled =
- getMendelFlag("iorap_perfetto_enable", "iorapd.perfetto.enable", false);
- boolean isReadAheadEnabled =
- getMendelFlag("iorap_readahead_enable", "iorapd.readahead.enable", false);
- // Same as the property in iorapd.rc -- disabling this will mean the 'iorapd' binder process
- // never comes up, so all binder connections will fail indefinitely.
- return IS_ENABLED && (isTracingEnabled || isReadAheadEnabled);
- }
-
- private boolean getMendelFlag(String mendelFlag, String sysProperty, boolean defaultValue) {
- // TODO(yawanng) use DeviceConfig to get mendel property.
- // DeviceConfig doesn't work and the reason is not clear.
- // Provider service is already up before IORapForwardService.
- String mendelProperty = "persist.device_config."
- + DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT
- + "."
- + mendelFlag;
- return SystemProperties.getBoolean(mendelProperty,
- SystemProperties.getBoolean(sysProperty, defaultValue));
- }
-
- //</editor-fold>
-
- @Override
- public void onStart() {
- if (DEBUG) {
- Log.v(TAG, "onStart");
- }
-
- retryConnectToRemoteAndConfigure(/*attempts*/0);
- }
-
- @Override
- public void onBootPhase(int phase) {
- if (phase == PHASE_BOOT_COMPLETED) {
- if (DEBUG) {
- Log.v(TAG, "onBootPhase(PHASE_BOOT_COMPLETED)");
- }
-
- if (isIorapEnabled()) {
- // Set up a recurring background job. This has to be done in a later phase since it
- // has a dependency the job scheduler.
- //
- // Doing this too early can result in a ServiceNotFoundException for 'jobservice'
- // or a null reference for #getSystemService(JobScheduler.class)
- mJobService = new IorapdJobService(getContext());
- }
- }
- }
-
- private class BinderConnectionHandler extends Handler {
- public BinderConnectionHandler(android.os.Looper looper) {
- super(looper);
- }
-
- public static final int MESSAGE_BINDER_CONNECT = 0;
-
- private int mAttempts = 0;
-
- @Override
- public void handleMessage(android.os.Message message) {
- switch (message.what) {
- case MESSAGE_BINDER_CONNECT:
- if (!retryConnectToRemoteAndConfigure(mAttempts)) {
- mAttempts++;
- } else {
- mAttempts = 0;
- }
- break;
- default:
- throw new AssertionError("Unknown message: " + message.toString());
- }
- }
- }
-
- /**
- * Handle iorapd shutdowns and crashes, by attempting to reconnect
- * until the service is reached again.
- *
- * <p>The first connection attempt is synchronous,
- * subsequent attempts are done by posting delayed tasks to the IoThread.</p>
- *
- * @return true if connection succeeded now, or false if it failed now [and needs to requeue].
- */
- private boolean retryConnectToRemoteAndConfigure(int attempts) {
- final int sleepTime = 1000; // ms
-
- if (DEBUG) {
- Log.v(TAG, "retryConnectToRemoteAndConfigure - attempt #" + attempts);
- }
-
- if (connectToRemoteAndConfigure()) {
- return true;
- }
-
- // Either 'iorapd' is stuck in a crash loop (ouch!!) or we manually
- // called 'adb shell stop iorapd' , which means this would loop until it comes back
- // up.
- //
- // TODO: it would be good to get nodified of 'adb shell stop iorapd' to avoid
- // printing this warning.
- if (DEBUG) {
- Log.v(TAG, "Failed to connect to iorapd, is it down? Delay for " + sleepTime);
- }
-
- // Use a handler instead of Thread#sleep to avoid backing up the binder thread
- // when this is called from the death recipient callback.
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(BinderConnectionHandler.MESSAGE_BINDER_CONNECT),
- sleepTime);
-
- return false;
-
- // Log.e(TAG, "Can't connect to iorapd - giving up after " + attempts + " attempts");
- }
-
- private boolean connectToRemoteAndConfigure() {
- synchronized (mLock) {
- // Synchronize against any concurrent calls to this via the DeathRecipient.
- return connectToRemoteAndConfigureLocked();
- }
- }
-
- private boolean connectToRemoteAndConfigureLocked() {
- if (!isIorapEnabled()) {
- if (DEBUG) {
- Log.v(TAG, "connectToRemoteAndConfigure - iorapd is disabled, skip rest of work");
- }
- // When we see that iorapd is disabled (when system server comes up),
- // it stays disabled permanently until the next system server reset.
-
- // TODO: consider listening to property changes as a callback, then we can
- // be more dynamic about handling enable/disable.
- return true;
- }
-
- // Connect to the native binder service.
- mIorapRemote = provideIorapRemote();
- if (mIorapRemote == null) {
- if (DEBUG) {
- Log.e(TAG, "connectToRemoteAndConfigure - null iorap remote. check for Log.wtf?");
- }
- return false;
- }
- invokeRemote(mIorapRemote,
- (IIorap remote) -> remote.setTaskListener(new RemoteTaskListener()) );
- registerInProcessListenersLocked();
-
- Log.i(TAG, "Connected to iorapd native service.");
-
- return true;
- }
-
- private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
- private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator();
- private final DexOptPackagesUpdated mDexOptPackagesUpdated = new DexOptPackagesUpdated();
- private boolean mRegisteredListeners = false;
-
- private void registerInProcessListenersLocked() {
- if (mRegisteredListeners) {
- // Listeners are registered only once (idempotent operation).
- //
- // Today listeners are tolerant of the remote side going away
- // by handling remote errors.
- //
- // We could try to 'unregister' the listener when we get a binder disconnect,
- // but we'd still have to handle the case of encountering synchronous errors so
- // it really wouldn't be a win (other than having less log spew).
- return;
- }
-
- // Listen to App Launch Sequence events from ActivityTaskManager,
- // and forward them to the native binder service.
- ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
- provideLaunchObserverRegistry();
- launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
- launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
-
- BackgroundDexOptService.addPackagesUpdatedListener(mDexOptPackagesUpdated);
-
-
- mRegisteredListeners = true;
- }
-
- private class DexOptPackagesUpdated implements BackgroundDexOptService.PackagesUpdatedListener {
- @Override
- public void onPackagesUpdated(ArraySet<String> updatedPackages) {
- String[] updated = updatedPackages.toArray(new String[0]);
- for (String packageName : updated) {
- Log.d(TAG, "onPackagesUpdated: " + packageName);
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onDexOptEvent(RequestId.nextValueForSequence(),
- DexOptEvent.createPackageUpdate(packageName))
- );
- }
- }
- }
-
- private class AppLaunchObserver implements ActivityMetricsLaunchObserver {
- // We add a synthetic sequence ID here to make it easier to differentiate new
- // launch sequences on the native side.
- private @AppLaunchEvent.SequenceId long mSequenceId = -1;
-
- // All callbacks occur on the same background thread. Don't synchronize explicitly.
-
- @Override
- public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
- // #onIntentStarted [is the only transition that] initiates a new launch sequence.
- ++mSequenceId;
-
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onIntentStarted(%d, %s, %d)",
- mSequenceId, intent, timestampNs));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.IntentStarted(mSequenceId, intent, timestampNs))
- );
- }
-
- @Override
- public void onIntentFailed() {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onIntentFailed(%d)", mSequenceId));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.IntentFailed(mSequenceId))
- );
- }
-
- @Override
- public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
- @Temperature int temperature) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunched(%d, %s, %d)",
- mSequenceId, activity, temperature));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ActivityLaunched(mSequenceId, activity, temperature))
- );
- }
-
- @Override
- public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunchCancelled(%d, %s)",
- mSequenceId, activity));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ActivityLaunchCancelled(mSequenceId,
- activity)));
- }
-
- @Override
- public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunchFinished(%d, %s, %d)",
- mSequenceId, activity, timestampNs));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ActivityLaunchFinished(mSequenceId,
- activity,
- timestampNs))
- );
- }
-
- @Override
- public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onReportFullyDrawn(%d, %s, %d)",
- mSequenceId, activity, timestampNs));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ReportFullyDrawn(mSequenceId, activity, timestampNs))
- );
- }
- }
-
- /**
- * Debugging:
- *
- * $> adb shell dumpsys jobscheduler
- *
- * Search for 'IorapdJobServiceProxy'.
- *
- * JOB #1000/283673059: 6e54ed android/com.google.android.startop.iorap.IorapForwardingService$IorapdJobServiceProxy
- * ^ ^ ^
- * (uid, job id) ComponentName(package/class)
- *
- * Forcing the job to be run, ignoring constraints:
- *
- * $> adb shell cmd jobscheduler run -f android 283673059
- * ^ ^
- * package job_id
- *
- * ------------------------------------------------------------
- *
- * This class is instantiated newly by the JobService every time
- * it wants to run a new job.
- *
- * We need to forward invocations to the current running instance of
- * IorapForwardingService#IorapdJobService.
- *
- * Visibility: Must be accessible from android.app.AppComponentFactory
- */
- public static class IorapdJobServiceProxy extends JobService {
-
- public IorapdJobServiceProxy() {
- getActualIorapdJobService().bindProxy(this);
- }
-
-
- @NonNull
- private IorapdJobService getActualIorapdJobService() {
- // Can't ever be null, because the guarantee is that the
- // IorapForwardingService is always running.
- // We are in the same process as Job Service.
- return sSelfService.mJobService;
- }
-
- // Called by system to start the job.
- @Override
- public boolean onStartJob(JobParameters params) {
- return getActualIorapdJobService().onStartJob(params);
- }
-
- // Called by system to prematurely stop the job.
- @Override
- public boolean onStopJob(JobParameters params) {
- return getActualIorapdJobService().onStopJob(params);
- }
- }
-
- private class IorapdJobService extends JobService {
- private final ComponentName IORAPD_COMPONENT_NAME;
-
- private final Object mLock = new Object();
- // Jobs currently running remotely on iorapd.
- // They were started by the JobScheduler and need to be finished.
- private final HashMap<RequestId, JobParameters> mRunningJobs = new HashMap<>();
-
- private final JobInfo IORAPD_JOB_INFO;
-
- private volatile IorapdJobServiceProxy mProxy;
-
- public void bindProxy(IorapdJobServiceProxy proxy) {
- mProxy = proxy;
- }
-
- // Create a new job service which immediately schedules a 24-hour idle maintenance mode
- // background job to execute.
- public IorapdJobService(Context context) {
- if (DEBUG) {
- Log.v(TAG, "IorapdJobService (Context=" + context.toString() + ")");
- }
-
- // Schedule the proxy class to be instantiated by the JobScheduler
- // when it is time to invoke background jobs for IorapForwardingService.
-
-
- // This also needs a BIND_JOB_SERVICE permission in
- // frameworks/base/core/res/AndroidManifest.xml
- IORAPD_COMPONENT_NAME = new ComponentName(context, IorapdJobServiceProxy.class);
-
- JobInfo.Builder builder = new JobInfo.Builder(JOB_ID_IORAPD, IORAPD_COMPONENT_NAME);
- builder.setPeriodic(JOB_INTERVAL_MS);
- builder.setPrefetch(true);
-
- builder.setRequiresCharging(true);
- builder.setRequiresDeviceIdle(true);
-
- builder.setRequiresStorageNotLow(true);
-
- IORAPD_JOB_INFO = builder.build();
-
- JobScheduler js = context.getSystemService(JobScheduler.class);
- js.schedule(IORAPD_JOB_INFO);
- Log.d(TAG,
- "BgJob Scheduled (jobId=" + JOB_ID_IORAPD
- + ", interval: " + JOB_INTERVAL_MS + "ms)");
- }
-
- // Called by system to start the job.
- @Override
- public boolean onStartJob(JobParameters params) {
- // Tell iorapd to start a background job.
- Log.d(TAG, "Starting background job: " + params.toString());
-
- mAbortIdleCompilation.set(false);
- // PackageManagerService starts before IORap service.
- PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
- List<String> pkgs = pm.getAllPackages();
- runIdleCompilationAsync(params, pkgs);
- return true;
- }
-
- private void runIdleCompilationAsync(final JobParameters params, final List<String> pkgs) {
- new Thread("IORap_IdleCompilation") {
- @Override
- public void run() {
- for (int i = 0; i < pkgs.size(); i++) {
- String pkg = pkgs.get(i);
- if (mAbortIdleCompilation.get()) {
- Log.i(TAG, "The idle compilation is aborted");
- return;
- }
-
- // We wait until that job's sequence ID returns to us with 'Completed',
- RequestId request;
- synchronized (mLock) {
- // TODO: would be cleaner if we got the request from the
- // 'invokeRemote' function. Better yet, consider
- // a Pair<RequestId, Future<TaskResult>> or similar.
- request = RequestId.nextValueForSequence();
- mRunningJobs.put(request, params);
- }
-
- Log.i(TAG, String.format("IORap compile package: %s, [%d/%d]",
- pkg, i + 1, pkgs.size()));
- boolean shouldUpdateVersions = (i == 0);
- if (!invokeRemote(mIorapRemote, (IIorap remote) ->
- remote.onJobScheduledEvent(request,
- JobScheduledEvent.createIdleMaintenance(
- JobScheduledEvent.TYPE_START_JOB,
- params,
- pkg,
- shouldUpdateVersions)))) {
- synchronized (mLock) {
- mRunningJobs.remove(request); // Avoid memory leaks.
- }
- }
-
- // Wait until the job is complete and removed from the running jobs.
- retryWithTimeout(TIMEOUT, () -> {
- synchronized (mLock) {
- return !mRunningJobs.containsKey(request);
- }
- });
- }
-
- // Finish the job after all packages are compiled.
- if (mProxy != null) {
- mProxy.jobFinished(params, /*reschedule*/false);
- }
- }
- }.start();
- }
-
- /** Retry until timeout. */
- private boolean retryWithTimeout(final Duration timeout, BooleanSupplier supplier) {
- long totalSleepTimeMs = 0L;
- long sleepIntervalMs = 10L;
- while (true) {
- if (supplier.getAsBoolean()) {
- return true;
- }
- try {
- TimeUnit.MILLISECONDS.sleep(sleepIntervalMs);
- } catch (InterruptedException e) {
- Log.e(TAG, e.getMessage());
- return false;
- }
-
- totalSleepTimeMs += sleepIntervalMs;
- if (totalSleepTimeMs > timeout.toMillis()) {
- return false;
- }
- }
- }
-
- // Called by system to prematurely stop the job.
- @Override
- public boolean onStopJob(JobParameters params) {
- // As this is unexpected behavior, print a warning.
- Log.w(TAG, "onStopJob(params=" + params.toString() + ")");
- mAbortIdleCompilation.set(true);
-
- // Yes, retry the job at a later time no matter what.
- return true;
- }
-
- // Listen to *all* task completes for all requests.
- // The majority of these might be unrelated to background jobs.
- public void onIorapdTaskCompleted(RequestId requestId) {
- JobParameters jobParameters;
- synchronized (mLock) {
- jobParameters = mRunningJobs.remove(requestId);
- }
-
- // Typical case: This was a task callback unrelated to our jobs.
- if (jobParameters == null) {
- return;
- }
-
- if (DEBUG) {
- Log.v(TAG,
- String.format("IorapdJobService#onIorapdTaskCompleted(%s), found params=%s",
- requestId, jobParameters));
- }
-
- Log.d(TAG, "Finished background job: " + jobParameters.toString());
- }
-
- public void onIorapdDisconnected() {
- synchronized (mLock) {
- mRunningJobs.clear();
- }
-
- if (DEBUG) {
- Log.v(TAG, String.format("IorapdJobService#onIorapdDisconnected"));
- }
-
- // TODO: should we try to resubmit all incomplete jobs after it's reconnected?
- }
- }
-
- private class RemoteTaskListener extends ITaskListener.Stub {
- @Override
- public void onProgress(RequestId requestId, TaskResult result) throws RemoteException {
- if (DEBUG) {
- Log.v(TAG,
- String.format("RemoteTaskListener#onProgress(%s, %s)", requestId, result));
- }
-
- // TODO: implement rest.
- }
-
- @Override
- public void onComplete(RequestId requestId, TaskResult result) throws RemoteException {
- if (DEBUG) {
- Log.v(TAG,
- String.format("RemoteTaskListener#onComplete(%s, %s)", requestId, result));
- }
-
- if (mJobService != null) {
- mJobService.onIorapdTaskCompleted(requestId);
- }
-
- // TODO: implement rest.
- }
- }
-
- /** Allow passing lambdas to #invokeRemote */
- private interface RemoteRunnable {
- // TODO: run(RequestId) ?
- void run(IIorap iorap) throws RemoteException;
- }
-
- // Always pass in the iorap directly here to avoid data race.
- private static boolean invokeRemote(IIorap iorap, RemoteRunnable r) {
- if (iorap == null) {
- Log.w(TAG, "IIorap went to null in this thread, drop invokeRemote.");
- return false;
- }
- try {
- r.run(iorap);
- return true;
- } catch (RemoteException e) {
- // This could be a logic error (remote side returning error), which we need to fix.
- //
- // This could also be a DeadObjectException in which case its probably just iorapd
- // being manually restarted.
- //
- // Don't make any assumption, since DeadObjectException could also mean iorapd crashed
- // unexpectedly.
- //
- // DeadObjectExceptions are recovered from using DeathRecipient and #linkToDeath.
- handleRemoteError(e);
- return false;
- }
- }
-
- private static void handleRemoteError(Throwable t) {
- if (WTF_CRASH) {
- // In development modes, we just want to crash.
- throw new AssertionError("unexpected remote error", t);
- } else {
- // Log to wtf which gets sent to dropbox, and in system_server this does not crash.
- Log.wtf(TAG, t);
- }
- }
-
- // Encode A-Z bitstring into bits. Every character is bits.
- // Characters outside of the range [a,z] are considered out of range.
- //
- // The least significant bits hold the last character.
- // First 2 bits are left as 0.
- private static int encodeEnglishAlphabetStringIntoInt(String name) {
- int value = 0;
-
- final int CHARS_PER_INT = 6;
- final int BITS_PER_CHAR = 5;
- // Note: 2 top bits are unused, this also means our values are non-negative.
- final char CHAR_LOWER = 'a';
- final char CHAR_UPPER = 'z';
-
- if (name.length() > CHARS_PER_INT) {
- throw new IllegalArgumentException(
- "String too long. Cannot encode more than 6 chars: " + name);
- }
-
- for (int i = 0; i < name.length(); ++i) {
- char c = name.charAt(i);
-
- if (c < CHAR_LOWER || c > CHAR_UPPER) {
- throw new IllegalArgumentException("String has out-of-range [a-z] chars: " + name);
- }
-
- // Avoid sign extension during promotion.
- int cur_value = (c & 0xFFFF) - (CHAR_LOWER & 0xFFFF);
- if (cur_value >= (1 << BITS_PER_CHAR)) {
- throw new AssertionError("wtf? i=" + i + ", name=" + name);
- }
-
- value = value << BITS_PER_CHAR;
- value = value | cur_value;
- }
-
- return value;
- }
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java b/startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java
deleted file mode 100644
index b91dd71..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.app.job.JobParameters;
-import android.annotation.NonNull;
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Forward JobService events to iorapd. <br /><br />
- *
- * iorapd sometimes need to use background jobs. Forwarding these events to iorapd
- * notifies iorapd when it is an opportune time to execute these background jobs.
- *
- * @hide
- */
-public class JobScheduledEvent implements Parcelable {
-
- /** JobService#onJobStarted */
- public static final int TYPE_START_JOB = 0;
- /** JobService#onJobStopped */
- public static final int TYPE_STOP_JOB = 1;
- private static final int TYPE_MAX = 1;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_START_JOB,
- TYPE_STOP_JOB,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- /** @see JobParameters#getJobId() */
- public final int jobId;
-
- public final String packageName;
-
- public final boolean shouldUpdateVersions;
-
- /** Device is 'idle' and it's charging (plugged in). */
- public static final int SORT_IDLE_MAINTENANCE = 0;
- private static final int SORT_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "SORT_" }, value = {
- SORT_IDLE_MAINTENANCE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Sort {}
-
- /**
- * Roughly corresponds to the {@code extras} fields in a JobParameters.
- */
- @Sort public final int sort;
-
- /**
- * Creates a {@link #SORT_IDLE_MAINTENANCE} event from the type and job parameters.
- *
- * Only the job ID is retained from {@code jobParams}, all other param info is dropped.
- */
- @NonNull
- public static JobScheduledEvent createIdleMaintenance(
- @Type int type, JobParameters jobParams, String packageName, boolean shouldUpdateVersions) {
- return new JobScheduledEvent(
- type, jobParams.getJobId(), SORT_IDLE_MAINTENANCE, packageName, shouldUpdateVersions);
- }
-
- private JobScheduledEvent(@Type int type,
- int jobId,
- @Sort int sort,
- String packageName,
- boolean shouldUpdateVersions) {
- this.type = type;
- this.jobId = jobId;
- this.sort = sort;
- this.packageName = packageName;
- this.shouldUpdateVersions = shouldUpdateVersions;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- // No check for 'jobId': any int is valid.
- CheckHelpers.checkTypeInRange(sort, SORT_MAX);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof JobScheduledEvent) {
- return equals((JobScheduledEvent) other);
- }
- return false;
- }
-
- private boolean equals(JobScheduledEvent other) {
- return type == other.type &&
- jobId == other.jobId &&
- sort == other.sort &&
- packageName.equals(other.packageName) &&
- shouldUpdateVersions == other.shouldUpdateVersions;
- }
-
- @Override
- public String toString() {
- return String.format(
- "{type: %d, jobId: %d, sort: %d, packageName: %s, shouldUpdateVersions %b}",
- type, jobId, sort, packageName, shouldUpdateVersions);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- out.writeInt(jobId);
- out.writeInt(sort);
- out.writeString(packageName);
- out.writeBoolean(shouldUpdateVersions);
-
- // We do not parcel the entire JobParameters here because there is no C++ equivalent
- // of that class [which the iorapd side of the binder interface requires].
- }
-
- private JobScheduledEvent(Parcel in) {
- this.type = in.readInt();
- this.jobId = in.readInt();
- this.sort = in.readInt();
- this.packageName = in.readString();
- this.shouldUpdateVersions = in.readBoolean();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<JobScheduledEvent> CREATOR
- = new Parcelable.Creator<JobScheduledEvent>() {
- public JobScheduledEvent createFromParcel(Parcel in) {
- return new JobScheduledEvent(in);
- }
-
- public JobScheduledEvent[] newArray(int size) {
- return new JobScheduledEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java b/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java
deleted file mode 100644
index aa4eea7..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.annotation.NonNull;
-import android.os.Parcelable;
-import android.os.Parcel;
-import android.net.Uri;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Forward package manager events to iorapd. <br /><br />
- *
- * Knowing when packages are modified by the system are a useful tidbit to help with performance:
- * for example when a package is replaced, it could be a hint used to invalidate any collected
- * io profiles used for prefetching or pinning.
- *
- * @hide
- */
-public class PackageEvent implements Parcelable {
-
- /** @see android.content.Intent#ACTION_PACKAGE_REPLACED */
- public static final int TYPE_REPLACED = 0;
- private static final int TYPE_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_REPLACED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- /** The path that a package is installed in, for example {@code /data/app/.../base.apk}. */
- public final Uri packageUri;
- /** The name of the package, for example {@code com.android.calculator}. */
- public final String packageName;
-
- @NonNull
- public static PackageEvent createReplaced(Uri packageUri, String packageName) {
- return new PackageEvent(TYPE_REPLACED, packageUri, packageName);
- }
-
- private PackageEvent(@Type int type, Uri packageUri, String packageName) {
- this.type = type;
- this.packageUri = packageUri;
- this.packageName = packageName;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(packageUri, "packageUri");
- Objects.requireNonNull(packageName, "packageName");
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof PackageEvent) {
- return equals((PackageEvent) other);
- }
- return false;
- }
-
- private boolean equals(PackageEvent other) {
- return type == other.type &&
- Objects.equals(packageUri, other.packageUri) &&
- Objects.equals(packageName, other.packageName);
- }
-
- @Override
- public String toString() {
- return String.format("{packageUri: %s, packageName: %s}", packageUri, packageName);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- packageUri.writeToParcel(out, flags);
- out.writeString(packageName);
- }
-
- private PackageEvent(Parcel in) {
- this.type = in.readInt();
- this.packageUri = Uri.CREATOR.createFromParcel(in);
- this.packageName = in.readString();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<PackageEvent> CREATOR
- = new Parcelable.Creator<PackageEvent>() {
- public PackageEvent createFromParcel(Parcel in) {
- return new PackageEvent(in);
- }
-
- public PackageEvent[] newArray(int size) {
- return new PackageEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/RequestId.java b/startop/iorap/src/com/google/android/startop/iorap/RequestId.java
deleted file mode 100644
index 503e1c6..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/RequestId.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.NonNull;
-
-/**
- * Uniquely identify an {@link com.google.android.startop.iorap.IIorap} method invocation,
- * used for asynchronous callbacks by the server. <br /><br />
- *
- * As all system server binder calls must be {@code oneway}, this means all invocations
- * into {@link com.google.android.startop.iorap.IIorap} are non-blocking. The request ID
- * exists to associate all calls with their respective callbacks in
- * {@link com.google.android.startop.iorap.ITaskListener}.
- *
- * @see com.google.android.startop.iorap.IIorap
- *
- * @hide
- */
-public class RequestId implements Parcelable {
-
- public final long requestId;
-
- private static Object mLock = new Object();
- private static long mNextRequestId = 0;
-
- /**
- * Create a monotonically increasing request ID.<br /><br />
- *
- * It is invalid to re-use the same request ID for multiple method calls on
- * {@link com.google.android.startop.iorap.IIorap}; a new request ID must be created
- * each time.
- */
- @NonNull public static RequestId nextValueForSequence() {
- long currentRequestId;
- synchronized (mLock) {
- currentRequestId = mNextRequestId;
- ++mNextRequestId;
- }
- return new RequestId(currentRequestId);
- }
-
- private RequestId(long requestId) {
- this.requestId = requestId;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- if (requestId < 0) {
- throw new IllegalArgumentException("request id must be non-negative");
- }
- }
-
- @Override
- public String toString() {
- return String.format("{requestId: %d}", requestId);
- }
-
- @Override
- public int hashCode() {
- return Long.hashCode(requestId);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof RequestId) {
- return equals((RequestId) other);
- }
- return false;
- }
-
- private boolean equals(RequestId other) {
- return requestId == other.requestId;
- }
-
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(requestId);
- }
-
- private RequestId(Parcel in) {
- requestId = in.readLong();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<RequestId> CREATOR
- = new Parcelable.Creator<RequestId>() {
- public RequestId createFromParcel(Parcel in) {
- return new RequestId(in);
- }
-
- public RequestId[] newArray(int size) {
- return new RequestId[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java
deleted file mode 100644
index 75d47f9..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Forward system service events to iorapd.
- *
- * @see com.android.server.SystemService
- *
- * @hide
- */
-public class SystemServiceEvent implements Parcelable {
-
- /** @see com.android.server.SystemService#onBootPhase */
- public static final int TYPE_BOOT_PHASE = 0;
- /** @see com.android.server.SystemService#onStart */
- public static final int TYPE_START = 1;
- private static final int TYPE_MAX = TYPE_START;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_BOOT_PHASE,
- TYPE_START,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- // TODO: do we want to pass the exact build phase enum?
-
- public SystemServiceEvent(@Type int type) {
- this.type = type;
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- }
-
- @Override
- public String toString() {
- return String.format("{type: %d}", type);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof SystemServiceEvent) {
- return equals((SystemServiceEvent) other);
- }
- return false;
- }
-
- private boolean equals(SystemServiceEvent other) {
- return type == other.type;
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- }
-
- private SystemServiceEvent(Parcel in) {
- this.type = in.readInt();
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<SystemServiceEvent> CREATOR
- = new Parcelable.Creator<SystemServiceEvent>() {
- public SystemServiceEvent createFromParcel(Parcel in) {
- return new SystemServiceEvent(in);
- }
-
- public SystemServiceEvent[] newArray(int size) {
- return new SystemServiceEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
deleted file mode 100644
index 2e7bafe..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Forward user events to iorapd.<br /><br />
- *
- * Knowledge of the logged-in user is reserved to be used to set-up appropriate policies
- * by iorapd (e.g. to handle user default pinned applications changing).
- *
- * @see com.android.server.SystemService
- *
- * @hide
- */
-public class SystemServiceUserEvent implements Parcelable {
-
- /** @see com.android.server.SystemService#onUserStarting */
- public static final int TYPE_START_USER = 0;
- /** @see com.android.server.SystemService#onUserUnlocking */
- public static final int TYPE_UNLOCK_USER = 1;
- /** @see com.android.server.SystemService#onUserSwitching*/
- public static final int TYPE_SWITCH_USER = 2;
- /** @see com.android.server.SystemService#onUserStopping */
- public static final int TYPE_STOP_USER = 3;
- /** @see com.android.server.SystemService#onUserStopped */
- public static final int TYPE_CLEANUP_USER = 4;
- private static final int TYPE_MAX = TYPE_CLEANUP_USER;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_START_USER,
- TYPE_UNLOCK_USER,
- TYPE_SWITCH_USER,
- TYPE_STOP_USER,
- TYPE_CLEANUP_USER,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
- public final int userHandle;
-
- public SystemServiceUserEvent(@Type int type, int userHandle) {
- this.type = type;
- this.userHandle = userHandle;
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- if (userHandle < 0) {
- throw new IllegalArgumentException("userHandle must be non-negative");
- }
- }
-
- @Override
- public String toString() {
- return String.format("{type: %d, userHandle: %d}", type, userHandle);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof SystemServiceUserEvent) {
- return equals((SystemServiceUserEvent) other);
- }
- return false;
- }
-
- private boolean equals(SystemServiceUserEvent other) {
- return type == other.type &&
- userHandle == other.userHandle;
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- out.writeInt(userHandle);
- }
-
- private SystemServiceUserEvent(Parcel in) {
- this.type = in.readInt();
- this.userHandle = in.readInt();
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<SystemServiceUserEvent> CREATOR
- = new Parcelable.Creator<SystemServiceUserEvent>() {
- public SystemServiceUserEvent createFromParcel(Parcel in) {
- return new SystemServiceUserEvent(in);
- }
-
- public SystemServiceUserEvent[] newArray(int size) {
- return new SystemServiceUserEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java b/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java
deleted file mode 100644
index b5fd6d8..0000000
--- a/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Result data accompanying a request for {@link com.google.android.startop.iorap.ITaskListener}
- * callbacks.<br /><br />
- *
- * Following {@link com.google.android.startop.iorap.IIorap} method invocation,
- * iorapd will issue in-order callbacks for that corresponding {@link RequestId}.<br /><br />
- *
- * State transitions are as follows: <br /><br />
- *
- * <pre>
- * ┌─────────────────────────────┐
- * │ ▼
- * ┌───────┐ ┌─────────┐ ╔═══════════╗
- * ──▶ │ BEGAN │ ──▶ │ ONGOING │ ──▶ ║ COMPLETED ║
- * └───────┘ └─────────┘ ╚═══════════╝
- * │ │
- * │ │
- * ▼ │
- * ╔═══════╗ │
- * ──▶ ║ ERROR ║ ◀─────┘
- * ╚═══════╝
- *
- * </pre> <!-- system/iorap/docs/binder/TaskResult.dot -->
- *
- * @hide
- */
-public class TaskResult implements Parcelable {
-
- public static final int STATE_BEGAN = 0;
- public static final int STATE_ONGOING = 1;
- public static final int STATE_COMPLETED = 2;
- public static final int STATE_ERROR = 3;
- private static final int STATE_MAX = STATE_ERROR;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "STATE_" }, value = {
- STATE_BEGAN,
- STATE_ONGOING,
- STATE_COMPLETED,
- STATE_ERROR,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface State {}
-
- @State public final int state;
-
- @Override
- public String toString() {
- return String.format("{state: %d}", state);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof TaskResult) {
- return equals((TaskResult) other);
- }
- return false;
- }
-
- private boolean equals(TaskResult other) {
- return state == other.state;
- }
-
- public TaskResult(@State int state) {
- this.state = state;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkStateInRange(state, STATE_MAX);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(state);
- }
-
- private TaskResult(Parcel in) {
- state = in.readInt();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<TaskResult> CREATOR
- = new Parcelable.Creator<TaskResult>() {
- public TaskResult createFromParcel(Parcel in) {
- return new TaskResult(in);
- }
-
- public TaskResult[] newArray(int size) {
- return new TaskResult[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/stress/Android.bp b/startop/iorap/stress/Android.bp
deleted file mode 100644
index 6e8725d..0000000
--- a/startop/iorap/stress/Android.bp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (C) 2020 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
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-cc_binary {
- name: "iorap.stress.memory",
- srcs: ["main_memory.cc"],
-
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wno-unused-parameter"
- ],
-
- shared_libs: [
- "libbase"
- ],
-
- host_supported: true,
-}
diff --git a/startop/iorap/stress/main_memory.cc b/startop/iorap/stress/main_memory.cc
deleted file mode 100644
index 1f26861..0000000
--- a/startop/iorap/stress/main_memory.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Copyright (C) 2020 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.
-//
-
-#include <chrono>
-#include <fstream>
-#include <iostream>
-#include <random>
-#include <string>
-
-#include <string.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-
-#include <android-base/parseint.h>
-
-static constexpr size_t kBytesPerMb = 1048576;
-const size_t kMemoryAllocationSize = 2 * 1024 * kBytesPerMb;
-
-#define USE_MLOCKALL 0
-
-std::string GetProcessStatus(const char* key) {
- // Build search pattern of key and separator.
- std::string pattern(key);
- pattern.push_back(':');
-
- // Search for status lines starting with pattern.
- std::ifstream fs("/proc/self/status");
- std::string line;
- while (std::getline(fs, line)) {
- if (strncmp(pattern.c_str(), line.c_str(), pattern.size()) == 0) {
- // Skip whitespace in matching line (if any).
- size_t pos = line.find_first_not_of(" \t", pattern.size());
- if (pos == std::string::npos) {
- break;
- }
- return std::string(line, pos);
- }
- }
- return "<unknown>";
-}
-
-int main(int argc, char** argv) {
- size_t allocationSize = 0;
- if (argc >= 2) {
- if (!android::base::ParseUint(argv[1], /*out*/&allocationSize)) {
- std::cerr << "Failed to parse the allocation size (must be 0,MAX_SIZE_T)" << std::endl;
- return 1;
- }
- } else {
- allocationSize = kMemoryAllocationSize;
- }
-
- void* mem = malloc(allocationSize);
- if (mem == nullptr) {
- std::cerr << "Malloc failed" << std::endl;
- return 1;
- }
-
- volatile int* imem = static_cast<int *>(mem); // don't optimize out memory usage
-
- size_t imemCount = allocationSize / sizeof(int);
-
- std::cout << "Allocated " << allocationSize << " bytes" << std::endl;
-
- auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
- std::mt19937 mt_rand(seed);
-
- size_t randPrintCount = 10;
-
- // Write random numbers:
- // * Ensures each page is resident
- // * Avoids zeroed out pages (zRAM)
- // * Avoids same-page merging
- for (size_t i = 0; i < imemCount; ++i) {
- imem[i] = mt_rand();
-
- if (i < randPrintCount) {
- std::cout << "Generated random value: " << imem[i] << std::endl;
- }
- }
-
-#if USE_MLOCKALL
- /*
- * Lock all pages from the address space of this process.
- */
- if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
- std::cerr << "Mlockall failed" << std::endl;
- return 1;
- }
-#else
- // Use mlock because of the predictable VmLck size.
- // Using mlockall tends to bring in anywhere from 2-2.5GB depending on the device.
- if (mlock(mem, allocationSize) != 0) {
- std::cerr << "Mlock failed" << std::endl;
- return 1;
- }
-#endif
-
- // Validate memory is actually resident and locked with:
- // $> cat /proc/$(pidof iorap.stress.memory)/status | grep VmLck
- std::cout << "Locked memory (VmLck) = " << GetProcessStatus("VmLck") << std::endl;
-
- std::cout << "Press any key to terminate" << std::endl;
- int any_input;
- std::cin >> any_input;
-
- std::cout << "Terminating..." << std::endl;
-
- munlockall();
- free(mem);
-
- return 0;
-}
diff --git a/startop/iorap/tests/Android.bp b/startop/iorap/tests/Android.bp
deleted file mode 100644
index ad3d001..0000000
--- a/startop/iorap/tests/Android.bp
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2018 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.
-
-// TODO: once b/80095087 is fixed, rewrite this back to android_test
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library {
- name: "libiorap-java-test-lib",
- srcs: ["src/**/*.kt"],
- static_libs: [
- // Non-test dependencies
- // library under test
- "services.startop.iorap",
- // need the system_server code to be on the classpath,
- "services.core",
- // Test Dependencies
- // test android dependencies
- "platform-test-annotations",
- "androidx.test.rules",
- // test framework dependencies
- "mockito-target-inline-minus-junit4",
- // "mockito-target-minus-junit4",
- // Mockito also requires JNI (see Android.mk)
- // and android:debuggable=true (see AndroidManifest.xml)
- "truth-prebuilt",
- ],
- // sdk_version: "current",
- // certificate: "platform",
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- // test_suites: ["device-tests"],
-}
-
-android_test {
- name: "libiorap-java-tests",
- dxflags: ["--multi-dex"],
- test_suites: ["device-tests"],
- static_libs: ["libiorap-java-test-lib"],
- compile_multilib: "both",
- jni_libs: [
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- "libmultiplejvmtiagentsinterferenceagent",
- ],
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- // Use private APIs
- certificate: "platform",
- platform_apis: true,
-}
diff --git a/startop/iorap/tests/AndroidManifest.xml b/startop/iorap/tests/AndroidManifest.xml
deleted file mode 100644
index b967e72..0000000
--- a/startop/iorap/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<!--suppress AndroidUnknownAttribute -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.startop.iorap.tests"
- android:sharedUserId="com.google.android.startop.iorap.tests"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <!--suppress AndroidDomInspection -->
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.google.android.startop.iorap.tests" />
-
- <!--
- 'debuggable=true' is required to properly load mockito jvmti dependencies,
- otherwise it gives the following error at runtime:
-
- Openjdkjvmti plugin was loaded on a non-debuggable Runtime.
- Plugin was loaded too late to change runtime state to DEBUGGABLE. -->
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
-</manifest>
diff --git a/startop/iorap/tests/AndroidTest.xml b/startop/iorap/tests/AndroidTest.xml
deleted file mode 100644
index 6102c44..0000000
--- a/startop/iorap/tests/AndroidTest.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<configuration description="Runs libiorap-java-tests.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-instrumentation" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="libiorap-java-tests.apk" />
- </target_preparer>
-
- <!--
- Our IIorapIntegrationTest.kt requires setlinux to be disabled:
- it connects to the iorapd binder service but this requires selinux permissions:
-
- avc: denied { find } for service=iorapd pid=2738 uid=10050
- scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:iorapd_service:s0
- tclass=service_manager permissive=0
- -->
- <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer">
- </target_preparer>
-
- <!-- do not use DeviceSetup#set-property because it reboots the device b/136200738.
- furthermore the changes in /data/local.prop don't actually seem to get picked up.
- -->
- <target_preparer
- class="com.android.tradefed.targetprep.DeviceSetup">
- <!-- we need this magic flag, otherwise it always reboots and breaks the selinux -->
- <option name="force-skip-system-props" value="true" />
-
- <!-- Crash instead of using Log.wtf within the system_server iorap code. -->
- <option name="run-command" value="setprop iorapd.forwarding_service.wtf_crash true" />
- <!-- IIorapd has fake behavior: it doesn't do anything but reply with 'DONE' status -->
- <option name="run-command" value="setprop iorapd.binder.fake true" />
-
- <!-- iorapd does not pick up the above changes until we restart it -->
- <option name="run-command" value="stop iorapd" />
- <option name="run-command" value="start iorapd" />
- <!-- give it some time to restart the service; otherwise the first unit test might fail -->
- <option name="run-command" value="sleep 1" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.google.android.startop.iorap.tests" />
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- </test>
-
- <!-- using DeviceSetup again does not work. we simply leave the device in a semi-bad
- state. there is no way to clean this up as far as I know.
- -->
-
-</configuration>
-
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
deleted file mode 100644
index 51e407d..0000000
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.google.android.startop.iorap
-
-import android.content.Intent;
-import android.net.Uri
-import android.os.Parcel
-import android.os.Parcelable
-import androidx.test.filters.SmallTest
-import com.google.android.startop.iorap.AppLaunchEvent;
-import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunched
-import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchCancelled
-import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchFinished
-import com.google.android.startop.iorap.AppLaunchEvent.IntentStarted;
-import com.google.android.startop.iorap.AppLaunchEvent.IntentFailed;
-import com.google.android.startop.iorap.AppLaunchEvent.ReportFullyDrawn
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-
-/**
- * Basic unit tests to test all of the [AppLaunchEvent]s in [com.google.android.startop.iorap].
- */
-@SmallTest
-class AppLaunchEventTest {
- /**
- * Test for IntentStarted.
- */
- @Test
- fun testIntentStarted() {
- var intent = Intent()
- val valid = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
- val copy = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
- val noneCopy1 = IntentStarted(/* sequenceId= */1L, intent, /* timestampNs= */ 1L)
- val noneCopy2 = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 2L)
- val noneCopy3 = IntentStarted(/* sequenceId= */2L, Intent(), /* timestampNs= */ 1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("IntentStarted{sequenceId=2, intent=Intent { } , timestampNs=1}")
- }
-
- /**
- * Test for IntentFailed.
- */
- @Test
- fun testIntentFailed() {
- val valid = IntentFailed(/* sequenceId= */2L)
- val copy = IntentFailed(/* sequenceId= */2L)
- val noneCopy = IntentFailed(/* sequenceId= */1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("IntentFailed{sequenceId=2}")
- }
-
- /**
- * Test for ActivityLaunched.
- */
- @Test
- fun testActivityLaunched() {
- //var activityRecord =
- val valid = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
- /* temperature= */ 0)
- val copy = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
- /* temperature= */ 0)
- val noneCopy1 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
- /* temperature= */ 0)
- val noneCopy2 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
- /* temperature= */ 1)
- val noneCopy3 = ActivityLaunched(/* sequenceId= */1L, "test1".toByteArray(),
- /* temperature= */ 0)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ActivityLaunched{sequenceId=2, test, temperature=0}")
- }
-
-
- /**
- * Test for ActivityLaunchFinished.
- */
- @Test
- fun testActivityLaunchFinished() {
- val valid = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val copy = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy1 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy2 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 2L)
- val noneCopy3 = ActivityLaunchFinished(/* sequenceId= */2L, "test1".toByteArray(),
- /* timestampNs= */ 1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ActivityLaunchFinished{sequenceId=2, test, timestampNs=1}")
- }
-
- /**
- * Test for ActivityLaunchCancelled.
- */
- @Test
- fun testActivityLaunchCancelled() {
- val valid = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
- val copy = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
- val noneCopy1 = ActivityLaunchCancelled(/* sequenceId= */1L, "test".toByteArray())
- val noneCopy2 = ActivityLaunchCancelled(/* sequenceId= */2L, "test1".toByteArray())
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ActivityLaunchCancelled{sequenceId=2, test}")
- }
-
- /**
- * Test for ReportFullyDrawn.
- */
- @Test
- fun testReportFullyDrawn() {
- val valid = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
- val copy = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
- val noneCopy1 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy2 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy3 = ReportFullyDrawn(/* sequenceId= */2L, "test1".toByteArray(),
- /* timestampNs= */ 1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ReportFullyDrawn{sequenceId=2, test, timestampNs=1}")
- }
-}
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
deleted file mode 100644
index 18c2491..0000000
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap
-
-import android.net.Uri
-import android.os.ServiceManager
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.MediumTest
-import org.junit.Test
-import org.mockito.Mockito.argThat
-import org.mockito.Mockito.eq
-import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.timeout
-
-// @Ignore("Test is disabled until iorapd is added to init and there's selinux policies for it")
-@MediumTest
-@FlakyTest(bugId = 149098310) // Failing on cuttlefish with SecurityException.
-class IIorapIntegrationTest {
- /**
- * @throws ServiceManager.ServiceNotFoundException if iorapd service could not be found
- */
- private val iorapService: IIorap by lazy {
- // TODO: connect to 'iorapd.stub' which doesn't actually do any work other than reply.
- IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"))
-
- // Use 'adb shell setenforce 0' otherwise this whole test fails,
- // because the servicemanager is not allowed to hand out the binder token for iorapd.
-
- // TODO: implement the selinux policies for iorapd.
- }
-
- // A dummy binder stub implementation is required to use with mockito#spy.
- // Mockito overrides the methods at runtime and tracks how methods were invoked.
- open class DummyTaskListener : ITaskListener.Stub() {
- // Note: make parameters nullable to avoid the kotlin IllegalStateExceptions
- // from using the mockito matchers (eq, argThat, etc).
- override fun onProgress(requestId: RequestId?, result: TaskResult?) {
- }
-
- override fun onComplete(requestId: RequestId?, result: TaskResult?) {
- }
- }
-
- private fun testAnyMethod(func: (RequestId) -> Unit) {
- val taskListener = spy(DummyTaskListener())!!
-
- // FIXME: b/149098310
- return
-
- try {
- iorapService.setTaskListener(taskListener)
- // Note: Binder guarantees total order for oneway messages sent to the same binder
- // interface, so we don't need any additional blocking here before sending later calls.
-
- // Every new method call should have a unique request id.
- val requestId = RequestId.nextValueForSequence()!!
-
- // Apply the specific function under test.
- func(requestId)
-
- // Typical mockito behavior is to allow any-order callbacks, but we want to test order.
- val inOrder = inOrder(taskListener)
-
- // The "stub" behavior of iorapd is that every request immediately gets a response of
- // BEGAN,ONGOING,COMPLETED
- inOrder.verify(taskListener, timeout(100))
- .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
- inOrder.verify(taskListener, timeout(100))
- .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
- inOrder.verify(taskListener, timeout(100))
- .onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
- inOrder.verifyNoMoreInteractions()
- } finally {
- // iorapService.setTaskListener(null)
- // FIXME: null is broken, C++ side sees a non-null object.
- }
- }
-
- @Test
- fun testOnPackageEvent() {
- // FIXME (b/137134253): implement PackageEvent parsing on the C++ side.
- // This is currently (silently: b/137135024) failing because IIorap is 'oneway' and the
- // C++ PackageEvent un-parceling fails since its not implemented fully.
- /*
- testAnyMethod { requestId : RequestId ->
- iorapService.onPackageEvent(requestId,
- PackageEvent.createReplaced(
- Uri.parse("https://www.google.com"), "com.fake.package"))
- }
- */
- }
-
- @Test
- fun testOnAppIntentEvent() {
- testAnyMethod { requestId: RequestId ->
- iorapService.onAppIntentEvent(requestId, AppIntentEvent.createDefaultIntentChanged(
- ActivityInfo("dont care", "dont care"),
- ActivityInfo("dont care 2", "dont care 2")))
- }
- }
-
- @Test
- fun testOnAppLaunchEvent() {
- testAnyMethod { requestId : RequestId ->
- iorapService.onAppLaunchEvent(requestId, AppLaunchEvent.IntentFailed(/*sequenceId*/123))
- }
- }
-
- @Test
- fun testOnSystemServiceEvent() {
- testAnyMethod { requestId: RequestId ->
- iorapService.onSystemServiceEvent(requestId,
- SystemServiceEvent(SystemServiceEvent.TYPE_START))
- }
- }
-
- @Test
- fun testOnSystemServiceUserEvent() {
- testAnyMethod { requestId: RequestId ->
- iorapService.onSystemServiceUserEvent(requestId,
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 0))
- }
- }
-}
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
deleted file mode 100644
index 150577a..0000000
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.google.android.startop.iorap
-
-import android.net.Uri
-import android.os.Parcel
-import android.os.Parcelable
-import androidx.test.filters.SmallTest
-import org.junit.Test
-import org.junit.runner.RunWith
-import com.google.common.truth.Truth.assertThat
-import org.junit.runners.Parameterized
-
-/**
- * Basic unit tests to ensure that all of the [Parcelable]s in [com.google.android.startop.iorap]
- * have a valid-conforming interface implementation.
- */
-@SmallTest
-@RunWith(Parameterized::class)
-class ParcelablesTest<T : Parcelable>(private val inputData: InputData<T>) {
- companion object {
- private val initialRequestId = RequestId.nextValueForSequence()!!
-
- @JvmStatic
- @Parameterized.Parameters
- fun data() = listOf(
- InputData(
- newActivityInfo(),
- newActivityInfo(),
- ActivityInfo("some package", "some other activity")),
- InputData(
- ActivityHintEvent(ActivityHintEvent.TYPE_COMPLETED, newActivityInfo()),
- ActivityHintEvent(ActivityHintEvent.TYPE_COMPLETED, newActivityInfo()),
- ActivityHintEvent(ActivityHintEvent.TYPE_POST_COMPLETED,
- newActivityInfo())),
- InputData(
- AppIntentEvent.createDefaultIntentChanged(newActivityInfo(),
- newActivityInfoOther()),
- AppIntentEvent.createDefaultIntentChanged(newActivityInfo(),
- newActivityInfoOther()),
- AppIntentEvent.createDefaultIntentChanged(newActivityInfoOther(),
- newActivityInfo())),
- InputData(
- PackageEvent.createReplaced(newUri(), "some package"),
- PackageEvent.createReplaced(newUri(), "some package"),
- PackageEvent.createReplaced(newUri(), "some other package")
- ),
- InputData(initialRequestId, cloneRequestId(initialRequestId),
- RequestId.nextValueForSequence()),
- InputData(
- SystemServiceEvent(SystemServiceEvent.TYPE_BOOT_PHASE),
- SystemServiceEvent(SystemServiceEvent.TYPE_BOOT_PHASE),
- SystemServiceEvent(SystemServiceEvent.TYPE_START)),
- InputData(
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 12345),
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 12345),
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_CLEANUP_USER, 12345)),
- InputData(
- TaskResult(TaskResult.STATE_COMPLETED),
- TaskResult(TaskResult.STATE_COMPLETED),
- TaskResult(TaskResult.STATE_ONGOING))
- )
-
- private fun newActivityInfo(): ActivityInfo {
- return ActivityInfo("some package", "some activity")
- }
-
- private fun newActivityInfoOther(): ActivityInfo {
- return ActivityInfo("some package 2", "some activity 2")
- }
-
- private fun newUri(): Uri {
- return Uri.parse("https://www.google.com")
- }
-
- private fun cloneRequestId(requestId: RequestId): RequestId {
- val constructor = requestId::class.java.declaredConstructors[0]
- constructor.isAccessible = true
- return constructor.newInstance(requestId.requestId) as RequestId
- }
- }
-
- /**
- * Test for [Object.equals] implementation.
- */
- @Test
- fun testEquality() {
- assertThat(inputData.valid).isEqualTo(inputData.valid)
- assertThat(inputData.valid).isEqualTo(inputData.validCopy)
- assertThat(inputData.valid).isNotEqualTo(inputData.validOther)
- }
-
- /**
- * Test for [Parcelable] implementation.
- */
- @Test
- fun testParcelRoundTrip() {
- // calling writeToParcel and then T::CREATOR.createFromParcel would return the same data.
- val assertParcels = { it: T, data: InputData<T> ->
- val parcel = Parcel.obtain()
- it.writeToParcel(parcel, 0)
- parcel.setDataPosition(0) // future reads will see all previous writes.
- assertThat(it).isEqualTo(data.createFromParcel(parcel))
- parcel.recycle()
- }
-
- assertParcels(inputData.valid, inputData)
- assertParcels(inputData.validCopy, inputData)
- assertParcels(inputData.validOther, inputData)
- }
-
- data class InputData<T : Parcelable>(val valid: T, val validCopy: T, val validOther: T) {
- val kls = valid.javaClass
- init {
- assertThat(valid).isNotSameInstanceAs(validCopy)
- // Don't use isInstanceOf because of phantom warnings in intellij about Class!
- assertThat(validCopy.javaClass).isEqualTo(valid.javaClass)
- assertThat(validOther.javaClass).isEqualTo(valid.javaClass)
- }
-
- fun createFromParcel(parcel: Parcel): T {
- val field = kls.getDeclaredField("CREATOR")
- val creator = field.get(null) as Parcelable.Creator<T>
-
- return creator.createFromParcel(parcel)
- }
- }
-}
diff --git a/startop/scripts/app_startup/analyze_metrics.py b/startop/scripts/app_startup/analyze_metrics.py
deleted file mode 100755
index d74d6f6..0000000
--- a/startop/scripts/app_startup/analyze_metrics.py
+++ /dev/null
@@ -1,457 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-
-"""
-Perform statistical analysis on measurements produced by app_startup_runner.py
-
-Install:
-$> sudo apt-get install python3-scipy
-
-Usage:
-$> ./analyze_metrics.py <filename.csv> [<filename2.csv> ...]
-$> ./analyze_metrics.py --help
-"""
-
-import argparse
-import csv
-import itertools
-import os
-import subprocess
-import sys
-import tempfile
-from typing import Any, List, Dict, Iterable, TextIO, Tuple
-
-from scipy import stats as sc
-import numpy as np
-
-
-# These CSV columns are considered labels. Everything after them in the same row are metrics.
-_LABEL_COLUMNS=['packages', 'readaheads', 'compiler_filters']
-# The metric series with the 'cold' readahead is the baseline.
-# All others (warm, jit, etc) are the potential improvements.
-
-#fixme: this should probably be an option
-_BASELINE=('readaheads', 'cold')
-# ignore this for some statistic calculations
-_IGNORE_PAIR=('readaheads', 'warm')
-_PLOT_SUBKEY='readaheads'
-_PLOT_GROUPKEY='packages'
-_PLOT_DATA_INDEX = 0
-_DELTA=50
-_DELTA2=100
-_PVALUE_THRESHOLD=0.10
-_debug = False # See -d/--debug flag.
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Perform statistical analysis on measurements produced by app_start_runner.py.")
- parser.add_argument('input_files', metavar='file.csv', nargs='+', help='CSV file produced by app_startup_runner.py')
-
- parser.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
- parser.add_argument('-os', '--output-samples', dest='output_samples', default='/dev/null', action='store', help='Store CSV for per-sample data')
- parser.add_argument('-oc', '--output-comparable', dest='output_comparable', default='/dev/null', action='store', help='Output CSV for comparable against baseline')
- parser.add_argument('-ocs', '--output-comparable-significant', dest='output_comparable_significant', default='/dev/null', action='store', help='Output CSV for comparable against baseline (significant only)')
- parser.add_argument('-pt', '--pvalue-threshold', dest='pvalue_threshold', type=float, default=_PVALUE_THRESHOLD, action='store')
- parser.add_argument('-dt', '--delta-threshold', dest='delta_threshold', type=int, default=_DELTA, action='store')
-
- return parser.parse_args(argv)
-
-def _debug_print(*args, **kwargs):
- """Print the args to sys.stderr if the --debug/-d flag was passed in."""
- global _debug
- if _debug:
- print(*args, **kwargs, file=sys.stderr)
-
-def _expand_gen_repr(args):
- new_args_list = []
- for i in args:
- # detect iterable objects that do not have their own override of __str__
- if hasattr(i, '__iter__'):
- to_str = getattr(i, '__str__')
- if to_str.__objclass__ == object:
- # the repr for a generator is just type+address, expand it out instead.
- new_args_list.append([_expand_gen_repr([j])[0] for j in i])
- continue
- # normal case: uses the built-in to-string
- new_args_list.append(i)
- return new_args_list
-
-def _debug_print_gen(*args, **kwargs):
- """Like _debug_print but will turn any iterable args into a list."""
- if not _debug:
- return
-
- new_args_list = _expand_gen_repr(args)
- _debug_print(*new_args_list, **kwargs)
-
-def read_headers(input_file: TextIO) -> Tuple[List[str], List[str]]:
- _debug_print("read_headers for file: ", input_file.name)
- csv_reader = csv.reader(input_file)
-
- label_num_columns = len(_LABEL_COLUMNS)
-
- try:
- header = next(csv_reader)
- except StopIteration:
- header = None
- _debug_print('header', header)
-
- if not header:
- return (None, None)
-
- labels = header[0:label_num_columns]
- data = header[label_num_columns:]
-
- return (labels, data)
-
-def read_labels_and_data(input_file: TextIO) -> Iterable[Tuple[List[str], List[int]]]:
- _debug_print("print_analysis for file: ", input_file.name)
- csv_reader = csv.reader(input_file)
-
- # Skip the header because it doesn't contain any data.
- # To get the header see read_headers function.
- try:
- header = next(csv_reader)
- except StopIteration:
- header = None
-
- label_num_columns = len(_LABEL_COLUMNS)
-
- for row in csv_reader:
- if len(row) > 0 and row[0][0] == ';':
- _debug_print("skip comment line", row)
- continue
-
- labels = row[0:label_num_columns]
- data = [int(i) for i in row[label_num_columns:]]
-
-# _debug_print("labels:", labels)
-# _debug_print("data:", data)
-
- yield (labels, data)
-
-def group_metrics_by_label(it: Iterable[Tuple[List[str], List[int]]]):
- prev_labels = None
- data_2d = []
-
- for label_list, data_list in it:
- if prev_labels != label_list:
- if prev_labels:
-# _debug_print("grouped labels:", prev_labels, "data_2d:", data_2d)
- yield (prev_labels, data_2d)
- data_2d = []
-
- data_2d.append(data_list)
- prev_labels = label_list
-
- if prev_labels:
-# _debug_print("grouped labels:", prev_labels, "data_2d:", data_2d)
- yield (prev_labels, data_2d)
-
-def data_to_numpy(it: Iterable[Tuple[List[str], List[List[int]]]]) -> Iterable[Tuple[List[str], Any]]:
- for label_list, data_2d in it:
- yield (label_list, np.asarray(data_2d, dtype=int))
-
-def iterate_columns(np_data_2d):
- for col in range(np_data_2d.shape[1]):
- col_as_array = np_data_2d[:, col]
- yield col_as_array
-
-def confidence_interval(np_data_2d, percent=0.95):
- """
- Given some data [[a,b,c],[d,e,f,]...]
-
- We assume the same metric is in the column (e.g. [a,d])
- and that data in the rows (e.g. [b,e]) are separate metric values.
-
- We then calculate the CI for each metric individually returning it as a list of tuples.
- """
- arr = []
- for col_2d in iterate_columns(np_data_2d):
- mean = col_2d.mean()
- sigma = col_2d.std()
-
- ci = sc.norm.interval(percent, loc=mean, scale=sigma / np.sqrt(len(col_2d)))
- arr.append(ci)
-
- # TODO: This seems to be returning NaN when all the samples have the same exact value
- # (e.g. stddev=0, which can trivially happen when sample count = 1).
-
- return arr
-
-def print_analysis(it, label_header: List[str], data_header: List[str], output_samples: str):
- print(label_header)
-
- with open(output_samples, "w") as output_file:
-
- csv_writer = csv.writer(output_file)
- csv_writer.writerow(label_header + ['mean', 'std', 'confidence_interval_a', 'confidence_interval_b'])
-
- for label_list, np_data_2d in it:
- print("**********************")
- print(label_list)
- print()
- print(" ", data_header)
- # aggregate computation column-wise
- print("Mean: ", np_data_2d.mean(axis=0))
- print("Std: ", np_data_2d.std(axis=0))
- print("CI95%:", confidence_interval(np_data_2d))
- print("SEM: ", stats_standard_error_one(np_data_2d, axis=0))
-
- #ci = confidence_interval(np_data_2d)[_PLOT_DATA_INDEX]
- sem = stats_standard_error_one(np_data_2d, axis=0)[_PLOT_DATA_INDEX]
- mean = np_data_2d.mean(axis=0)[_PLOT_DATA_INDEX]
-
- ci = (mean - sem, mean + sem)
-
- csv_writer.writerow(label_list + [mean, np_data_2d.std(axis=0)[_PLOT_DATA_INDEX], ci[0], ci[1]])
-
-def from_file_group_by_labels(input_file):
- (label_header, data_header) = read_headers(input_file)
- label_data_iter = read_labels_and_data(input_file)
- grouped_iter = group_metrics_by_label(label_data_iter)
- grouped_numpy_iter = data_to_numpy(grouped_iter)
-
- return grouped_numpy_iter, label_header, data_header
-
-def list_without_index(list, index):
- return list[:index] + list[index+1:]
-
-def group_by_without_baseline_key(grouped_numpy_iter, label_header):
- """
- Data is considered comparable if the only difference is the baseline key
- (i.e. the readahead is different but the package, compilation filter, etc, are the same).
-
- Returns iterator that's grouped by the non-baseline labels to an iterator of
- (label_list, data_2d).
- """
- baseline_index = label_header.index(_BASELINE[0])
-
- def get_label_without_baseline(tpl):
- label_list, _ = tpl
- return list_without_index(label_list, baseline_index)
- # [['pkgname', 'compfilter', 'warm'], [data]]
- # [['pkgname', 'compfilter', 'cold'], [data2]]
- # [['pkgname2', 'compfilter', 'warm'], [data3]]
- #
- # ->
- # ( [['pkgname', 'compfilter', 'warm'], [data]] # ignore baseline label change.
- # [['pkgname', 'compfilter', 'cold'], [data2]] ), # split here because the pkgname changed.
- # ( [['pkgname2', 'compfilter', 'warm'], [data3]] )
- for group_info, it in itertools.groupby(grouped_numpy_iter, key = get_label_without_baseline):
- yield it
-
- # TODO: replace this messy manual iteration/grouping with pandas
-
-def iterate_comparable_metrics(without_baseline_iter, label_header):
- baseline_index = label_header.index(_BASELINE[0])
- baseline_value = _BASELINE[1]
-
- _debug_print("iterate comparables")
-
- def is_baseline_fun(tp):
- ll, dat = tp
- return ll[baseline_index] == baseline_value
-
- # iterating here when everything but the baseline key is the same.
- for it in without_baseline_iter:
- it1, it2 = itertools.tee(it)
-
- # find all the baseline data.
- baseline_filter_it = filter(is_baseline_fun, it1)
-
- # find non-baseline data.
- nonbaseline_filter_it = itertools.filterfalse(is_baseline_fun, it2)
-
- yield itertools.product(baseline_filter_it, nonbaseline_filter_it)
-
-def stats_standard_error_one(a, axis):
- a_std = a.std(axis=axis, ddof=0)
- a_len = a.shape[axis]
-
- return a_std / np.sqrt(a_len)
-
-def stats_standard_error(a, b, axis):
- a_std = a.std(axis=axis, ddof=0)
- b_std = b.std(axis=axis, ddof=0)
-
- a_len = a.shape[axis]
- b_len = b.shape[axis]
-
- temp1 = a_std*a_std/a_len
- temp2 = b_std*b_std/b_len
-
- return np.sqrt(temp1 + temp2)
-
-def stats_tvalue(a, b, axis, delta = 0):
- a_mean = a.mean(axis=axis)
- b_mean = b.mean(axis=axis)
-
- return (a_mean - b_mean - delta) / stats_standard_error(a, b, axis)
-
-def stats_pvalue(a, b, axis, delta, left:bool = False):
- """
- Single-tailed 2-sample t-test.
-
- Returns p-value for the null hypothesis: mean(a) - mean(b) >= delta.
- :param a: numpy 2d array
- :param b: numpy 2d array
- :param axis: which axis to do the calculations across
- :param delta: test value of mean differences
- :param left: if true then use <= delta instead of >= delta
- :return: p-value
- """
- # implement our own pvalue calculation because the built-in t-test (t,p values)
- # only offer delta=0 , e.g. m1-m1 ? 0
- # we are however interested in m1-m2 ? delta
- t_value = stats_tvalue(a, b, axis, delta)
-
- # 2-sample degrees of freedom is using the array sizes - 2.
- dof = a.shape[axis] + b.shape[axis] - 2
-
- if left:
- # left tailed test. e.g. m1-m2 <= delta
- return sc.t.cdf(t_value, dof)
- else:
- # right tailed test. e.g. m1-m2 >= delta
- return sc.t.sf(t_value, dof)
- # a left+right tailed test is a 2-tail t-test and can be done using ttest_ind for delta=0
-
-def print_comparable_analysis(comparable_metrics_iter, label_header, data_header, output_comparable: str, output_comparable_significant: str):
- baseline_value = _BASELINE[1]
- baseline_index = label_header.index(_BASELINE[0])
-
- old_baseline_label_list = None
- delta = _DELTA
- filter_value = _IGNORE_PAIR[1]
- filter_index = label_header.index(_IGNORE_PAIR[0])
-
- pvalue_threshold = _PVALUE_THRESHOLD
- ci_threshold = (1 - _PVALUE_THRESHOLD) * 100.0
-
- with open(output_comparable, "w") as output_file:
-
- csv_writer = csv.writer(output_file)
- csv_writer.writerow(label_header + ['mean', 'mean_diff', 'sem', 'pvalue_2tailed', 'pvalue_gt%d' %(_DELTA), 'pvalue_gt%d' %(_DELTA2)])
-
- print("------------------------------------------------------------------")
- print("Comparison against the baseline %s = %s" %(_BASELINE, baseline_value))
- print("--- Right-tailed t-test checks if the baseline >= current %s by at least %d" %(_BASELINE[0], delta))
- print()
-
- global_stats = {'better_than_delta': [], 'better_than_delta_p95': []}
-
- for nested_it in comparable_metrics_iter:
- print("************************")
-
- better_than_delta = []
- better_than_delta_p95 = []
-
- saw_baseline_once = False
-
- for ((baseline_label_list, baseline_np_data_2d), (rest_label_list, rest_np_data_2d)) in nested_it:
- _debug_print("baseline_label_list:", baseline_label_list)
- _debug_print("baseline_np_data_2d:", baseline_np_data_2d)
- _debug_print("rest_label_list:", rest_label_list)
- _debug_print("rest_np_data_2d:", rest_np_data_2d)
-
- mean_diff = baseline_np_data_2d.mean(axis=0) - rest_np_data_2d.mean(axis=0)
- # 2-sample 2-tailed t-test with delta=0
- # e.g. "Is it true that usually the two sample means are different?"
- t_statistic, t_pvalue = sc.ttest_ind(baseline_np_data_2d, rest_np_data_2d, axis=0)
-
- # 2-sample 1-tailed t-test with delta=50
- # e.g. "Is it true that usually the sample means better than 50ms?"
- t2 = stats_tvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=delta)
- p2 = stats_pvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=delta)
-
- t2_b = stats_tvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=_DELTA2)
- p2_b = stats_pvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=_DELTA2)
-
- print("%s vs %s" %(rest_label_list, baseline_value))
- print(" ", data_header)
- print("Mean Difference: ", mean_diff)
- print("T-test (2-tailed) != 0: t=%s, p=%s" %(t_statistic, t_pvalue))
- print("T-test (right-tailed) >= %d: t=%s, p=%s" %(_DELTA, t2, p2))
- print("T-test (right-tailed) >= %d: t=%s, p=%s" %(_DELTA2, t2_b, p2_b))
-
- def write_out_values(label_list, *args):
- csv_writer.writerow(label_list + [i[_PLOT_DATA_INDEX] for i in args])
-
- sem = stats_standard_error(baseline_np_data_2d, rest_np_data_2d, axis=0)
- if saw_baseline_once == False:
- saw_baseline_once = True
- base_sem = stats_standard_error_one(baseline_np_data_2d, axis=0)
- write_out_values(baseline_label_list, baseline_np_data_2d.mean(axis=0), [0], base_sem, [None], [None], [None])
- write_out_values(rest_label_list, rest_np_data_2d.mean(axis=0), mean_diff, sem, t_pvalue, p2, p2_b)
-
- # now do the global statistics aggregation
-
- if rest_label_list[filter_index] == filter_value:
- continue
-
- if mean_diff > delta:
- better_than_delta.append((mean_diff, p2, rest_label_list))
-
- if p2 <= pvalue_threshold:
- better_than_delta_p95.append((mean_diff, rest_label_list))
-
- if better_than_delta:
- global_stats['better_than_delta'].append(better_than_delta)
- if better_than_delta_p95:
- global_stats['better_than_delta_p95'].append(better_than_delta_p95)
-
- print("------------------------")
- print("Global statistics:")
- print("//// Rows with %s=%s are ignored here." %_IGNORE_PAIR)
- print("- # of results with mean diff better than delta(%d) = %d" %(delta, len(global_stats['better_than_delta'])))
- print(" > (meandiff, pvalue, labels)")
- for i in global_stats['better_than_delta']:
- print(" > %s" %i)
- print("- # of results with mean diff better than delta(%d) CI%d%% = %d" %(delta, ci_threshold, len(global_stats['better_than_delta_p95'])))
- print(" > (meandiff, labels)")
- for i in global_stats['better_than_delta_p95']:
- print(" > %s" %i)
-
-def main():
- global _debug
- global _DELTA
- global _PVALUE_THRESHOLD
-
- opts = parse_options()
- _debug = opts.debug
- _debug_print("parsed options: ", opts)
-
- _PVALUE_THRESHOLD = opts.pvalue_threshold or _PVALUE_THRESHOLD
-
- for file_name in opts.input_files:
- with open(file_name, 'r') as input_file:
- (grouped_numpy_iter, label_header, data_header) = from_file_group_by_labels(input_file)
- print_analysis(grouped_numpy_iter, label_header, data_header, opts.output_samples)
-
- with open(file_name, 'r') as input_file:
- (grouped_numpy_iter, label_header, data_header) = from_file_group_by_labels(input_file)
- without_baseline_iter = group_by_without_baseline_key(grouped_numpy_iter, label_header)
- #_debug_print_gen(without_baseline_iter)
-
- comparable_metrics_iter = iterate_comparable_metrics(without_baseline_iter, label_header)
- print_comparable_analysis(comparable_metrics_iter, label_header, data_header, opts.output_comparable, opts.output_comparable_significant)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
deleted file mode 100755
index 25ee6f7..0000000
--- a/startop/scripts/app_startup/app_startup_runner.py
+++ /dev/null
@@ -1,393 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-
-#
-#
-# Measure application start-up time by launching applications under various combinations.
-# See --help for more details.
-#
-#
-# Sample usage:
-# $> ./app_startup_runner.py -p com.google.android.calculator -r warm -r cold -lc 10 -o out.csv
-# $> ./analyze_metrics.py out.csv
-#
-#
-
-import argparse
-import csv
-import itertools
-import os
-import sys
-import tempfile
-from datetime import timedelta
-from typing import Any, Callable, Iterable, List, NamedTuple, TextIO, Tuple, \
- TypeVar, Union, Optional
-
-# local import
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
-from app_startup.run_app_with_prefetch import PrefetchAppRunner
-import app_startup.lib.args_utils as args_utils
-from app_startup.lib.data_frame import DataFrame
-from app_startup.lib.perfetto_trace_collector import PerfettoTraceCollector
-from iorap.compiler import CompilerType
-import iorap.compiler as compiler
-
-# The following command line options participate in the combinatorial generation.
-# All other arguments have a global effect.
-_COMBINATORIAL_OPTIONS = ['package', 'readahead', 'compiler_filter',
- 'activity', 'trace_duration']
-_TRACING_READAHEADS = ['mlock', 'fadvise']
-_FORWARD_OPTIONS = {'loop_count': '--count'}
-_RUN_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)),
- 'run_app_with_prefetch.py')
-
-CollectorPackageInfo = NamedTuple('CollectorPackageInfo',
- [('package', str), ('compiler_filter', str)])
-# by 2; systrace starts up slowly.
-
-_UNLOCK_SCREEN_SCRIPT = os.path.join(
- os.path.dirname(os.path.realpath(__file__)), 'unlock_screen')
-
-RunCommandArgs = NamedTuple('RunCommandArgs',
- [('package', str),
- ('readahead', str),
- ('activity', Optional[str]),
- ('compiler_filter', Optional[str]),
- ('timeout', Optional[int]),
- ('debug', bool),
- ('simulate', bool),
- ('input', Optional[str]),
- ('trace_duration', Optional[timedelta])])
-
-# This must be the only mutable global variable. All other global variables are constants to avoid magic literals.
-_debug = False # See -d/--debug flag.
-_DEBUG_FORCE = None # Ignore -d/--debug if this is not none.
-_PERFETTO_TRACE_DURATION_MS = 5000 # milliseconds
-_PERFETTO_TRACE_DURATION = timedelta(milliseconds=_PERFETTO_TRACE_DURATION_MS)
-
-# Type hinting names.
-T = TypeVar('T')
-NamedTupleMeta = Callable[
- ..., T] # approximation of a (S : NamedTuple<T> where S() == T) metatype.
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Run one or more Android "
- "applications under various "
- "settings in order to measure "
- "startup time.")
- # argparse considers args starting with - and -- optional in --help, even though required=True.
- # by using a named argument group --help will clearly say that it's required instead of optional.
- required_named = parser.add_argument_group('required named arguments')
- required_named.add_argument('-p', '--package', action='append',
- dest='packages',
- help='package of the application', required=True)
- required_named.add_argument('-r', '--readahead', action='append',
- dest='readaheads',
- help='which readahead mode to use',
- choices=('warm', 'cold', 'mlock', 'fadvise'),
- required=True)
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-c', '--compiler-filter', action='append',
- dest='compiler_filters',
- help='which compiler filter to use. if omitted it does not enforce the app\'s compiler filter',
- choices=('speed', 'speed-profile', 'quicken'))
- optional_named.add_argument('-s', '--simulate', dest='simulate',
- action='store_true',
- help='Print which commands will run, but don\'t run the apps')
- optional_named.add_argument('-d', '--debug', dest='debug',
- action='store_true',
- help='Add extra debugging output')
- optional_named.add_argument('-o', '--output', dest='output', action='store',
- help='Write CSV output to file.')
- optional_named.add_argument('-t', '--timeout', dest='timeout', action='store',
- type=int, default=10,
- help='Timeout after this many seconds when executing a single run.')
- optional_named.add_argument('-lc', '--loop-count', dest='loop_count',
- default=1, type=int, action='store',
- help='How many times to loop a single run.')
- optional_named.add_argument('-in', '--inodes', dest='inodes', type=str,
- action='store',
- help='Path to inodes file (system/extras/pagecache/pagecache.py -d inodes)')
- optional_named.add_argument('--compiler-trace-duration-ms',
- dest='trace_duration',
- type=lambda ms_str: timedelta(milliseconds=int(ms_str)),
- action='append',
- help='The trace duration (milliseconds) in '
- 'compilation')
- optional_named.add_argument('--compiler-type', dest='compiler_type',
- type=CompilerType, choices=list(CompilerType),
- default=CompilerType.DEVICE,
- help='The type of compiler.')
-
- return parser.parse_args(argv)
-
-def key_to_cmdline_flag(key: str) -> str:
- """Convert key into a command line flag, e.g. 'foo-bars' -> '--foo-bar' """
- if key.endswith("s"):
- key = key[:-1]
- return "--" + key.replace("_", "-")
-
-def as_run_command(tpl: NamedTuple) -> List[Union[str, Any]]:
- """
- Convert a named tuple into a command-line compatible arguments list.
-
- Example: ABC(1, 2, 3) -> ['--a', 1, '--b', 2, '--c', 3]
- """
- args = []
- for key, value in tpl._asdict().items():
- if value is None:
- continue
- args.append(key_to_cmdline_flag(key))
- args.append(value)
- return args
-
-def run_perfetto_collector(collector_info: CollectorPackageInfo,
- timeout: int,
- simulate: bool) -> Tuple[bool, TextIO]:
- """Run collector to collect prefetching trace.
-
- Returns:
- A tuple of whether the collection succeeds and the generated trace file.
- """
- tmp_output_file = tempfile.NamedTemporaryFile()
-
- collector = PerfettoTraceCollector(package=collector_info.package,
- activity=None,
- compiler_filter=collector_info.compiler_filter,
- timeout=timeout,
- simulate=simulate,
- trace_duration=_PERFETTO_TRACE_DURATION,
- save_destination_file_path=tmp_output_file.name)
- result = collector.run()
-
- return result is not None, tmp_output_file
-
-def parse_run_script_csv_file(csv_file: TextIO) -> DataFrame:
- """Parse a CSV file full of integers into a DataFrame."""
- csv_reader = csv.reader(csv_file)
-
- try:
- header_list = next(csv_reader)
- except StopIteration:
- header_list = []
-
- if not header_list:
- return None
-
- headers = [i for i in header_list]
-
- d = {}
- for row in csv_reader:
- header_idx = 0
-
- for i in row:
- v = i
- if i:
- v = int(i)
-
- header_key = headers[header_idx]
- l = d.get(header_key, [])
- l.append(v)
- d[header_key] = l
-
- header_idx = header_idx + 1
-
- return DataFrame(d)
-
-def build_ri_compiler_argv(inodes_path: str,
- perfetto_trace_file: str,
- trace_duration: Optional[timedelta]
- ) -> str:
- argv = ['-i', inodes_path, '--perfetto-trace',
- perfetto_trace_file]
-
- if trace_duration is not None:
- argv += ['--duration', str(int(trace_duration.total_seconds()
- * PerfettoTraceCollector.MS_PER_SEC))]
-
- print_utils.debug_print(argv)
- return argv
-
-def execute_run_using_perfetto_trace(collector_info,
- run_combos: Iterable[RunCommandArgs],
- simulate: bool,
- inodes_path: str,
- timeout: int,
- compiler_type: CompilerType,
- requires_trace_collection: bool) -> DataFrame:
- """ Executes run based on perfetto trace. """
- if requires_trace_collection:
- passed, perfetto_trace_file = run_perfetto_collector(collector_info,
- timeout,
- simulate)
- if not passed:
- raise RuntimeError('Cannot run perfetto collector!')
- else:
- perfetto_trace_file = tempfile.NamedTemporaryFile()
-
- with perfetto_trace_file:
- for combos in run_combos:
- if combos.readahead in _TRACING_READAHEADS:
- if simulate:
- compiler_trace_file = tempfile.NamedTemporaryFile()
- else:
- ri_compiler_argv = build_ri_compiler_argv(inodes_path,
- perfetto_trace_file.name,
- combos.trace_duration)
- compiler_trace_file = compiler.compile(compiler_type,
- inodes_path,
- ri_compiler_argv,
- combos.package,
- combos.activity)
-
- with compiler_trace_file:
- combos = combos._replace(input=compiler_trace_file.name)
- print_utils.debug_print(combos)
- output = PrefetchAppRunner(**combos._asdict()).run()
- else:
- print_utils.debug_print(combos)
- output = PrefetchAppRunner(**combos._asdict()).run()
-
- yield DataFrame(dict((x, [y]) for x, y in output)) if output else None
-
-def execute_run_combos(
- grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[RunCommandArgs]]],
- simulate: bool,
- inodes_path: str,
- timeout: int,
- compiler_type: CompilerType,
- requires_trace_collection: bool):
- # nothing will work if the screen isn't unlocked first.
- cmd_utils.execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT],
- timeout,
- simulate=simulate,
- shell=False)
-
- for collector_info, run_combos in grouped_run_combos:
- yield from execute_run_using_perfetto_trace(collector_info,
- run_combos,
- simulate,
- inodes_path,
- timeout,
- compiler_type,
- requires_trace_collection)
-
-def gather_results(commands: Iterable[Tuple[DataFrame]],
- key_list: List[str], value_list: List[Tuple[str, ...]]):
- print_utils.debug_print("gather_results: key_list = ", key_list)
- stringify_none = lambda s: s is None and "<none>" or s
- # yield key_list + ["time(ms)"]
- for (run_result_list, values) in itertools.zip_longest(commands, value_list):
- print_utils.debug_print("run_result_list = ", run_result_list)
- print_utils.debug_print("values = ", values)
-
- if not run_result_list:
- continue
-
- # RunCommandArgs(package='com.whatever', readahead='warm', compiler_filter=None)
- # -> {'package':['com.whatever'], 'readahead':['warm'], 'compiler_filter':[None]}
- values_dict = {}
- for k, v in values._asdict().items():
- if not k in key_list:
- continue
- values_dict[k] = [stringify_none(v)]
-
- values_df = DataFrame(values_dict)
- # project 'values_df' to be same number of rows as run_result_list.
- values_df = values_df.repeat(run_result_list.data_row_len)
-
- # the results are added as right-hand-side columns onto the existing labels for the table.
- values_df.merge_data_columns(run_result_list)
-
- yield values_df
-
-def eval_and_save_to_csv(output, annotated_result_values):
- printed_header = False
-
- csv_writer = csv.writer(output)
- for row in annotated_result_values:
- if not printed_header:
- headers = row.headers
- csv_writer.writerow(headers)
- printed_header = True
- # TODO: what about when headers change?
-
- for data_row in row.data_table:
- data_row = [d for d in data_row]
- csv_writer.writerow(data_row)
-
- output.flush() # see the output live.
-
-def coerce_to_list(opts: dict):
- """Tranform values of the dictionary to list.
- For example:
- 1 -> [1], None -> [None], [1,2,3] -> [1,2,3]
- [[1],[2]] -> [[1],[2]], {1:1, 2:2} -> [{1:1, 2:2}]
- """
- result = {}
- for key in opts:
- val = opts[key]
- result[key] = val if issubclass(type(val), list) else [val]
- return result
-
-def main():
- global _debug
-
- opts = parse_options()
- _debug = opts.debug
- if _DEBUG_FORCE is not None:
- _debug = _DEBUG_FORCE
-
- print_utils.DEBUG = _debug
- cmd_utils.SIMULATE = opts.simulate
-
- print_utils.debug_print("parsed options: ", opts)
-
- output_file = opts.output and open(opts.output, 'w') or sys.stdout
-
- combos = lambda: args_utils.generate_run_combinations(
- RunCommandArgs,
- coerce_to_list(vars(opts)),
- opts.loop_count)
- print_utils.debug_print_gen("run combinations: ", combos())
-
- grouped_combos = lambda: args_utils.generate_group_run_combinations(combos(),
- CollectorPackageInfo)
-
- print_utils.debug_print_gen("grouped run combinations: ", grouped_combos())
- requires_trace_collection = any(i in _TRACING_READAHEADS for i in opts.readaheads)
- exec = execute_run_combos(grouped_combos(),
- opts.simulate,
- opts.inodes,
- opts.timeout,
- opts.compiler_type,
- requires_trace_collection)
-
- results = gather_results(exec, _COMBINATORIAL_OPTIONS, combos())
-
- eval_and_save_to_csv(output_file, results)
-
- return 1
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
deleted file mode 100755
index 0c2bbea..0000000
--- a/startop/scripts/app_startup/app_startup_runner_test.py
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-#
-
-"""
-Unit tests for the app_startup_runner.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./app_startup_runner_test.py
- $> pytest app_startup_runner_test.py
- $> python -m pytest app_startup_runner_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-import io
-import shlex
-import sys
-import typing
-# global imports
-from contextlib import contextmanager
-
-# local imports
-import app_startup_runner as asr
-# pip imports
-import pytest
-
-#
-# Argument Parsing Helpers
-#
-
-@contextmanager
-def ignore_stdout_stderr():
- """Ignore stdout/stderr output for duration of this context."""
- old_stdout = sys.stdout
- old_stderr = sys.stderr
- sys.stdout = io.StringIO()
- sys.stderr = io.StringIO()
- try:
- yield
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
-
-@contextmanager
-def argparse_bad_argument(msg):
- """
- Assert that a SystemExit is raised when executing this context.
- If the assertion fails, print the message 'msg'.
- """
- with pytest.raises(SystemExit, message=msg):
- with ignore_stdout_stderr():
- yield
-
-def assert_bad_argument(args, msg):
- """
- Assert that the command line arguments in 'args' are malformed.
- Prints 'msg' if the assertion fails.
- """
- with argparse_bad_argument(msg):
- parse_args(args)
-
-def parse_args(args):
- """
- :param args: command-line like arguments as a single string
- :return: dictionary of parsed key/values
- """
- # "-a b -c d" => ['-a', 'b', '-c', 'd']
- return vars(asr.parse_options(shlex.split(args)))
-
-def default_dict_for_parsed_args(**kwargs):
- """
- # Combine it with all of the "optional" parameters' default values.
- """
- d = {'compiler_filters': None, 'simulate': False, 'debug': False,
- 'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None,
- 'trace_duration': None, 'compiler_type': asr.CompilerType.DEVICE}
- d.update(kwargs)
- return d
-
-def default_mock_dict_for_parsed_args(include_optional=True, **kwargs):
- """
- Combine default dict with all optional parameters with some mock required parameters.
- """
- d = {'packages': ['com.fake.package'], 'readaheads': ['warm']}
- if include_optional:
- d.update(default_dict_for_parsed_args())
- d.update(kwargs)
- return d
-
-def parse_optional_args(str):
- """
- Parse an argument string which already includes all the required arguments
- in default_mock_dict_for_parsed_args.
- """
- req = "--package com.fake.package --readahead warm"
- return parse_args("%s %s" % (req, str))
-
-def test_argparse():
- # missing arguments
- assert_bad_argument("", "-p and -r are required")
- assert_bad_argument("-r warm", "-p is required")
- assert_bad_argument("--readahead warm", "-p is required")
- assert_bad_argument("-p com.fake.package", "-r is required")
- assert_bad_argument("--package com.fake.package", "-r is required")
-
- # required arguments are parsed correctly
- ad = default_dict_for_parsed_args # assert dict
-
- assert parse_args("--package xyz --readahead warm") == ad(packages=['xyz'],
- readaheads=['warm'])
- assert parse_args("-p xyz -r warm") == ad(packages=['xyz'],
- readaheads=['warm'])
-
- assert parse_args("-p xyz -r warm -s") == ad(packages=['xyz'],
- readaheads=['warm'],
- simulate=True)
- assert parse_args("-p xyz -r warm --simulate") == ad(packages=['xyz'],
- readaheads=['warm'],
- simulate=True)
-
- # optional arguments are parsed correctly.
- mad = default_mock_dict_for_parsed_args # mock assert dict
- assert parse_optional_args("--output filename.csv") == mad(
- output='filename.csv')
- assert parse_optional_args("-o filename.csv") == mad(output='filename.csv')
-
- assert parse_optional_args("--timeout 123") == mad(timeout=123)
- assert parse_optional_args("-t 456") == mad(timeout=456)
-
- assert parse_optional_args("--loop-count 123") == mad(loop_count=123)
- assert parse_optional_args("-lc 456") == mad(loop_count=456)
-
- assert parse_optional_args("--inodes bar") == mad(inodes="bar")
- assert parse_optional_args("-in baz") == mad(inodes="baz")
-
-
-
-def test_key_to_cmdline_flag():
- assert asr.key_to_cmdline_flag("abc") == "--abc"
- assert asr.key_to_cmdline_flag("foos") == "--foo"
- assert asr.key_to_cmdline_flag("ba_r") == "--ba-r"
- assert asr.key_to_cmdline_flag("ba_zs") == "--ba-z"
-
-def test_parse_run_script_csv_file():
- # empty file -> empty list
- f = io.StringIO("")
- assert asr.parse_run_script_csv_file(f) == None
-
- # common case
- f = io.StringIO("TotalTime_ms,Displayed_ms\n1,2")
- df = asr.DataFrame({'TotalTime_ms': [1], 'Displayed_ms': [2]})
-
- pf = asr.parse_run_script_csv_file(f)
- assert pf == df
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/force_compiler_filter b/startop/scripts/app_startup/force_compiler_filter
deleted file mode 100755
index 08f983d..0000000
--- a/startop/scripts/app_startup/force_compiler_filter
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018, 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.
-
-#
-# Forces an application APK to be compiled (by ART's dex2oat)
-# with a specific compiler filter.
-#
-# Example usage:
-# $> ./force_compiler_filter -p com.google.android.apps.maps -c speed-profile
-#
-# (The application may be started/stopped as a side effect)
-#
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/lib/common"
-
-usage() {
- cat <<EOF
-Usage: $(basename $0) [OPTION]...
-
- Required:
- -p, --package package of the app to recompile
- -c, --compiler-filter override the compiler filter if set (default none)
- valid options are listed by: adb shell cmd package, under compile -m
-
- Optional:
- -a, --activity activity of the app to recompile
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -w, --wait_time how long to wait for app startup (default 10) in seconds
-EOF
-}
-
-wait_time="10" # seconds
-
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -a|--activity)
- activity="$2"
- shift
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -w|--wait_time)
- wait_time="$2"
- shift
- ;;
- -c|--compiler-filter)
- compiler_filter="$2"
- shift
- ;;
- -v|--verbose)
- verbose="y"
- ;;
- esac
- shift
- done
-
- if [[ -z "$compiler_filter" ]]; then
- echo "Missing required --compiler-filter" >&2
- echo ""
- usage
- exit 1
- fi
- if [[ -z "$package" ]]; then
- echo "Missing required --package" >&2
- echo ""
- usage
- exit 1
- fi
-
- if [[ "$activity" == "" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 1
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-}
-
-force_package_compilation() {
- local arg_compiler_filter="$1"
- local arg_package="$2"
-
- if [[ $arg_compiler_filter == speed-profile ]]; then
- # Force the running app to dump its profiles to disk.
- remote_pkill "$arg_package" -SIGUSR1
- sleep 1 # give some time for above to complete.
- fi
-
- adb shell cmd package compile -m "$arg_compiler_filter" -f "$arg_package"
-}
-
-main() {
- parse_arguments "$@"
-
- if [[ $compiler_filter == speed-profile ]]; then
- # screen needs to be unlocked in order to run an app
- "$DIR"/unlock_screen
-
- local output=$("$DIR"/launch_application "$package" "$activity")
- if [[ $? -ne 0 ]]; then
- echo "launching application failed" >&2
- exit 1
- fi
-
- verbose_print "$output"
- # give some time for app startup to complete.
- # this is supposed to be an upper bound for measuring startup time.
- sleep "$wait_time"
- fi
-
- force_package_compilation "$compiler_filter" "$package"
-
- # kill the application to ensure next time it's started,
- # it picks up the correct compilation filter.
- adb shell am force-stop "$package"
- remote_pkill "$package"
-}
-
-main "$@"
diff --git a/startop/scripts/app_startup/launch_application b/startop/scripts/app_startup/launch_application
deleted file mode 100755
index 6704a5a..0000000
--- a/startop/scripts/app_startup/launch_application
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018, 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/lib/common"
-
-launch_application_usage() {
- cat <<EOF
-Usage: $(basename $0) <package> <activity>
-
- Positional Arguments:
- <package> package of the app to test
- <activity> activity to use
-
- Named Arguments:
- -h, --help usage information (this)
-EOF
-}
-
-launch_application() {
- local package="$1"
- local activity="$2"
-
- # if there's any $s inside of the activity name, it needs to be escaped to \$.
- # example '.app.honeycomb.Shell$HomeActivity'
- # if the $ is not escaped, adb shell will try to evaluate $HomeActivity to a variable.
- activity=${activity//\$/\\$}
-
- adb shell am start -S -W "$package"/"$activity"
-
- # pipe this into 'parse_metrics' to parse the output.
-}
-
-if [[ $# -lt 2 ]]; then
- launch_application_usage
- exit 1
-fi
-
-launch_application "$@"
diff --git a/startop/scripts/app_startup/lib/adb_utils.py b/startop/scripts/app_startup/lib/adb_utils.py
deleted file mode 100644
index 3cebc9a..0000000
--- a/startop/scripts/app_startup/lib/adb_utils.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-"""Helper util libraries for calling adb command line."""
-
-import datetime
-import os
-import re
-import sys
-import time
-from typing import Optional
-
-sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))))
-import lib.cmd_utils as cmd_utils
-import lib.logcat_utils as logcat_utils
-
-
-def logcat_save_timestamp() -> str:
- """Gets the current logcat timestamp.
-
- Returns:
- A string of timestamp.
- """
- _, output = cmd_utils.run_adb_shell_command(
- "date -u +\'%Y-%m-%d %H:%M:%S.%N\'")
- return output
-
-def vm_drop_cache():
- """Free pagecache and slab object."""
- cmd_utils.run_adb_shell_command('echo 3 > /proc/sys/vm/drop_caches')
- # Sleep a little bit to provide enough time for cache cleanup.
- time.sleep(1)
-
-def root():
- """Roots adb and successive adb commands will run under root."""
- cmd_utils.run_shell_command('adb root')
-
-def disable_selinux():
- """Disables selinux setting."""
- _, output = cmd_utils.run_adb_shell_command('getenforce')
- if output == 'Permissive':
- return
-
- print('Disable selinux permissions and restart framework.')
- cmd_utils.run_adb_shell_command('setenforce 0')
- cmd_utils.run_adb_shell_command('stop')
- cmd_utils.run_adb_shell_command('start')
- cmd_utils.run_shell_command('adb wait-for-device')
-
-def pkill(procname: str):
- """Kills a process on device specified by the substring pattern in procname"""
- _, pids = cmd_utils.run_shell_command('adb shell ps | grep "{}" | '
- 'awk \'{{print $2;}}\''.
- format(procname))
-
- for pid in pids.split('\n'):
- pid = pid.strip()
- if pid:
- passed,_ = cmd_utils.run_adb_shell_command('kill {}'.format(pid))
- time.sleep(1)
-
-def parse_time_to_milliseconds(time: str) -> int:
- """Parses the time string to milliseconds."""
- # Example: +1s56ms, +56ms
- regex = r'\+((?P<second>\d+?)s)?(?P<millisecond>\d+?)ms'
- result = re.search(regex, time)
- second = 0
- if result.group('second'):
- second = int(result.group('second'))
- ms = int(result.group('millisecond'))
- return second * 1000 + ms
-
-def blocking_wait_for_logcat_displayed_time(timestamp: datetime.datetime,
- package: str,
- timeout: int) -> Optional[int]:
- """Parses the displayed time in the logcat.
-
- Returns:
- the displayed time.
- """
- pattern = re.compile('.*ActivityTaskManager: Displayed {}.*'.format(package))
- # 2019-07-02 22:28:34.469453349 -> 2019-07-02 22:28:34.469453
- timestamp = datetime.datetime.strptime(timestamp[:-3],
- '%Y-%m-%d %H:%M:%S.%f')
- timeout_dt = timestamp + datetime.timedelta(0, timeout)
- # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager:
- # Displayed com.android.settings/.Settings: +927ms
- result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_dt)
- if not result or not '+' in result:
- return None
- displayed_time = result[result.rfind('+'):]
-
- return parse_time_to_milliseconds(displayed_time)
-
-def delete_file_on_device(file_path: str) -> None:
- """ Deletes a file on the device. """
- cmd_utils.run_adb_shell_command(
- "[[ -f '{file_path}' ]] && rm -f '{file_path}' || "
- "exit 0".format(file_path=file_path))
-
-def set_prop(property: str, value: str) -> None:
- """ Sets property using adb shell. """
- cmd_utils.run_adb_shell_command('setprop "{property}" "{value}"'.format(
- property=property, value=value))
-
-def pull_file(device_file_path: str, output_file_path: str) -> None:
- """ Pulls file from device to output """
- cmd_utils.run_shell_command('adb pull "{device_file_path}" "{output_file_path}"'.
- format(device_file_path=device_file_path,
- output_file_path=output_file_path))
diff --git a/startop/scripts/app_startup/lib/adb_utils_test.py b/startop/scripts/app_startup/lib/adb_utils_test.py
deleted file mode 100644
index e590fed..0000000
--- a/startop/scripts/app_startup/lib/adb_utils_test.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import adb_utils
-
-# pip imports
-import pytest
-
-def test_parse_time_to_milliseconds():
- # Act
- result1 = adb_utils.parse_time_to_milliseconds('+1s7ms')
- result2 = adb_utils.parse_time_to_milliseconds('+523ms')
-
- # Assert
- assert result1 == 1007
- assert result2 == 523
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/lib/app_runner.py b/startop/scripts/app_startup/lib/app_runner.py
deleted file mode 100644
index 78873fa..0000000
--- a/startop/scripts/app_startup/lib/app_runner.py
+++ /dev/null
@@ -1,266 +0,0 @@
-# Copyright 2019, 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.
-
-"""Class to run an app."""
-import os
-import sys
-from typing import Optional, List, Tuple
-
-# local import
-sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))))
-
-import app_startup.lib.adb_utils as adb_utils
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
-
-class AppRunnerListener(object):
- """Interface for lisenter of AppRunner. """
-
- def preprocess(self) -> None:
- """Preprocess callback to initialized before the app is running. """
- pass
-
- def postprocess(self, pre_launch_timestamp: str) -> None:
- """Postprocess callback to cleanup after the app is running.
-
- param:
- 'pre_launch_timestamp': indicates the timestamp when the app is
- launching.. """
- pass
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> None:
- """A metrics selection callback that waits for the desired metrics to
- show up in logcat.
- params:
- 'am_start_output': indicates the output of app startup.
- 'pre_launch_timestamp': indicates the timestamp when the app is
- launching.
- returns:
- a string in the format of "<metric>=<value>\n<metric>=<value>\n..."
- for further parsing. For example "TotalTime=123\nDisplayedTime=121".
- Return an empty string if no metrics need to be parsed further.
- """
- pass
-
-class AppRunner(object):
- """ Class to run an app. """
- # static variables
- DIR = os.path.abspath(os.path.dirname(__file__))
- APP_STARTUP_DIR = os.path.dirname(DIR)
- IORAP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(DIR,
- '../../iorap/common'))
- DEFAULT_TIMEOUT = 30 # seconds
-
- def __init__(self,
- package: str,
- activity: Optional[str],
- compiler_filter: Optional[str],
- timeout: Optional[int],
- simulate: bool):
- self.package = package
- self.simulate = simulate
-
- # If the argument activity is None, try to set it.
- self.activity = activity
- if self.simulate:
- self.activity = 'act'
- if self.activity is None:
- self.activity = AppRunner.get_activity(self.package)
-
- self.compiler_filter = compiler_filter
- self.timeout = timeout if timeout else AppRunner.DEFAULT_TIMEOUT
-
- self.listeners = []
-
- def add_callbacks(self, listener: AppRunnerListener):
- self.listeners.append(listener)
-
- def remove_callbacks(self, listener: AppRunnerListener):
- self.listeners.remove(listener)
-
- @staticmethod
- def get_activity(package: str) -> str:
- """ Tries to set the activity based on the package. """
- passed, activity = cmd_utils.run_shell_func(
- AppRunner.IORAP_COMMON_BASH_SCRIPT,
- 'get_activity_name',
- [package])
-
- if not passed or not activity:
- raise ValueError(
- 'Activity name could not be found, invalid package name?!')
-
- return activity
-
- def configure_compiler_filter(self) -> bool:
- """Configures compiler filter (e.g. speed).
-
- Returns:
- A bool indicates whether configure of compiler filer succeeds or not.
- """
- if not self.compiler_filter:
- print_utils.debug_print('No --compiler-filter specified, don\'t'
- ' need to force it.')
- return True
-
- passed, current_compiler_filter_info = \
- cmd_utils.run_shell_command(
- '{} --package {}'.format(os.path.join(AppRunner.APP_STARTUP_DIR,
- 'query_compiler_filter.py'),
- self.package))
-
- if passed != 0:
- return passed
-
- # TODO: call query_compiler_filter directly as a python function instead of
- # these shell calls.
- current_compiler_filter, current_reason, current_isa = \
- current_compiler_filter_info.split(' ')
- print_utils.debug_print('Compiler Filter={} Reason={} Isa={}'.format(
- current_compiler_filter, current_reason, current_isa))
-
- # Don't trust reasons that aren't 'unknown' because that means
- # we didn't manually force the compilation filter.
- # (e.g. if any automatic system-triggered compilations are not unknown).
- if current_reason != 'unknown' or \
- current_compiler_filter != self.compiler_filter:
- passed, _ = adb_utils.run_shell_command('{}/force_compiler_filter '
- '--compiler-filter "{}" '
- '--package "{}"'
- ' --activity "{}'.
- format(AppRunner.APP_STARTUP_DIR,
- self.compiler_filter,
- self.package,
- self.activity))
- else:
- adb_utils.debug_print('Queried compiler-filter matched requested '
- 'compiler-filter, skip forcing.')
- passed = False
- return passed
-
- def run(self) -> Optional[List[Tuple[str]]]:
- """Runs an app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- print_utils.debug_print('==========================================')
- print_utils.debug_print('===== START =====')
- print_utils.debug_print('==========================================')
- # Run the preprocess.
- for listener in self.listeners:
- listener.preprocess()
-
- # Ensure the APK is currently compiled with whatever we passed in
- # via --compiler-filter.
- # No-op if this option was not passed in.
- if not self.configure_compiler_filter():
- print_utils.error_print('Compiler filter configuration failed!')
- return None
-
- pre_launch_timestamp = adb_utils.logcat_save_timestamp()
- # Launch the app.
- results = self.launch_app(pre_launch_timestamp)
-
- # Run the postprocess.
- for listener in self.listeners:
- listener.postprocess(pre_launch_timestamp)
-
- return results
-
- def launch_app(self, pre_launch_timestamp: str) -> Optional[List[Tuple[str]]]:
- """ Launches the app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- print_utils.debug_print('Running with timeout {}'.format(self.timeout))
-
- passed, am_start_output = cmd_utils.run_shell_command('timeout {timeout} '
- '"{DIR}/launch_application" '
- '"{package}" '
- '"{activity}"'.
- format(timeout=self.timeout,
- DIR=AppRunner.APP_STARTUP_DIR,
- package=self.package,
- activity=self.activity))
- if not passed and not self.simulate:
- return None
-
- return self.wait_for_app_finish(pre_launch_timestamp, am_start_output)
-
- def wait_for_app_finish(self,
- pre_launch_timestamp: str,
- am_start_output: str) -> Optional[List[Tuple[str]]]:
- """ Wait for app finish and all metrics are shown in logcat.
-
- Returns:
- A list of (metric, value) tuples.
- """
- if self.simulate:
- return [('TotalTime', '123')]
-
- ret = []
- for listener in self.listeners:
- output = listener.metrics_selector(am_start_output,
- pre_launch_timestamp)
- ret = ret + AppRunner.parse_metrics_output(output)
-
- return ret
-
- @staticmethod
- def parse_metrics_output(input: str) -> List[
- Tuple[str, str, str]]:
- """Parses output of app startup to metrics and corresponding values.
-
- It converts 'a=b\nc=d\ne=f\n...' into '[(a,b,''),(c,d,''),(e,f,'')]'
-
- Returns:
- A list of tuples that including metric name, metric value and rest info.
- """
- all_metrics = []
- for line in input.split('\n'):
- if not line:
- continue
- splits = line.split('=')
- if len(splits) < 2:
- print_utils.error_print('Bad line "{}"'.format(line))
- continue
- metric_name = splits[0]
- metric_value = splits[1]
- rest = splits[2] if len(splits) > 2 else ''
- if rest:
- print_utils.error_print('Corrupt line "{}"'.format(line))
- print_utils.debug_print('metric: "{metric_name}", '
- 'value: "{metric_value}" '.
- format(metric_name=metric_name,
- metric_value=metric_value))
-
- all_metrics.append((metric_name, metric_value))
- return all_metrics
-
- @staticmethod
- def parse_total_time( am_start_output: str) -> Optional[str]:
- """Parses the total time from 'adb shell am start pkg' output.
-
- Returns:
- the total time of app startup.
- """
- for line in am_start_output.split('\n'):
- if 'TotalTime:' in line:
- return line[len('TotalTime:'):].strip()
- return None
-
diff --git a/startop/scripts/app_startup/lib/app_runner_test.py b/startop/scripts/app_startup/lib/app_runner_test.py
deleted file mode 100644
index 33d233b..0000000
--- a/startop/scripts/app_startup/lib/app_runner_test.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright 2019, 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.
-#
-
-"""Unit tests for the AppRunner."""
-import os
-import sys
-from pathlib import Path
-
-from app_runner import AppRunner, AppRunnerListener
-from mock import Mock, call, patch
-
-# The path is "frameworks/base/startop/scripts/"
-sys.path.append(Path(os.path.realpath(__file__)).parents[2])
-import lib.cmd_utils as cmd_utils
-
-class AppRunnerTestListener(AppRunnerListener):
- def preprocess(self) -> None:
- cmd_utils.run_shell_command('pre'),
-
- def postprocess(self, pre_launch_timestamp: str) -> None:
- cmd_utils.run_shell_command('post'),
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> None:
- return 'TotalTime=123\n'
-
-RUNNER = AppRunner(package='music',
- activity='MainActivity',
- compiler_filter='speed',
- timeout=None,
- simulate=False)
-
-
-
-def test_configure_compiler_filter():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.return_value = (True, 'speed arm64 kUpToDate')
-
- RUNNER.configure_compiler_filter()
-
- calls = [call(os.path.realpath(
- os.path.join(RUNNER.DIR,
- '../query_compiler_filter.py')) + ' --package music')]
- mock_run_shell_command.assert_has_calls(calls)
-
-def test_parse_metrics_output():
- input = 'a1=b1\nc1=d1\ne1=f1'
- ret = RUNNER.parse_metrics_output(input)
-
- assert ret == [('a1', 'b1'), ('c1', 'd1'), ('e1', 'f1')]
-
-def _mocked_run_shell_command(*args, **kwargs):
- if args[0] == 'adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"':
- return (True, "2019-07-02 23:20:06.972674825")
- elif args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
- return (True, '9999')
- else:
- return (True, 'a1=b1\nc1=d1=d2\ne1=f1')
-
-@patch('app_startup.lib.adb_utils.blocking_wait_for_logcat_displayed_time')
-@patch('lib.cmd_utils.run_shell_command')
-def test_run(mock_run_shell_command,
- mock_blocking_wait_for_logcat_displayed_time):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_displayed_time.return_value = 123
-
- test_listener = AppRunnerTestListener()
- RUNNER.add_callbacks(test_listener)
-
- result = RUNNER.run()
-
- RUNNER.remove_callbacks(test_listener)
-
- calls = [call('pre'),
- call(os.path.realpath(
- os.path.join(RUNNER.DIR,
- '../query_compiler_filter.py')) +
- ' --package music'),
- call('adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"'),
- call(
- 'timeout {timeout} "{DIR}/launch_application" "{package}" "{activity}"'
- .format(timeout=30,
- DIR=os.path.realpath(os.path.dirname(RUNNER.DIR)),
- package='music',
- activity='MainActivity',
- timestamp='2019-07-02 23:20:06.972674825')),
- call('post')
- ]
- mock_run_shell_command.assert_has_calls(calls)
- assert result == [('TotalTime', '123')]
- assert len(RUNNER.listeners) == 0
\ No newline at end of file
diff --git a/startop/scripts/app_startup/lib/args_utils.py b/startop/scripts/app_startup/lib/args_utils.py
deleted file mode 100644
index 080f3b5..0000000
--- a/startop/scripts/app_startup/lib/args_utils.py
+++ /dev/null
@@ -1,77 +0,0 @@
-import itertools
-import os
-import sys
-from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Tuple, \
- TypeVar, Optional
-
-# local import
-sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))))
-import lib.print_utils as print_utils
-
-T = TypeVar('T')
-NamedTupleMeta = Callable[
- ..., T] # approximation of a (S : NamedTuple<T> where S() == T) metatype.
-FilterFuncType = Callable[[NamedTuple], bool]
-
-def dict_lookup_any_key(dictionary: dict, *keys: List[Any]):
- for k in keys:
- if k in dictionary:
- return dictionary[k]
-
-
- print_utils.debug_print("None of the keys {} were in the dictionary".format(
- keys))
- return [None]
-
-def generate_run_combinations(named_tuple: NamedTupleMeta[T],
- opts_dict: Dict[str, List[Optional[object]]],
- loop_count: int = 1) -> Iterable[T]:
- """
- Create all possible combinations given the values in opts_dict[named_tuple._fields].
-
- :type T: type annotation for the named_tuple type.
- :param named_tuple: named tuple type, whose fields are used to make combinations for
- :param opts_dict: dictionary of keys to value list. keys correspond to the named_tuple fields.
- :param loop_count: number of repetitions.
- :return: an iterable over named_tuple instances.
- """
- combinations_list = []
- for k in named_tuple._fields:
- # the key can be either singular or plural , e.g. 'package' or 'packages'
- val = dict_lookup_any_key(opts_dict, k, k + "s")
-
- # treat {'x': None} key value pairs as if it was [None]
- # otherwise itertools.product throws an exception about not being able to iterate None.
- combinations_list.append(val or [None])
-
- print_utils.debug_print("opts_dict: ", opts_dict)
- print_utils.debug_print_nd("named_tuple: ", named_tuple)
- print_utils.debug_print("combinations_list: ", combinations_list)
-
- for i in range(loop_count):
- for combo in itertools.product(*combinations_list):
- yield named_tuple(*combo)
-
-def filter_run_combinations(named_tuple: NamedTuple,
- filters: List[FilterFuncType]) -> bool:
- for filter in filters:
- if filter(named_tuple):
- return False
- return True
-
-def generate_group_run_combinations(run_combinations: Iterable[NamedTuple],
- dst_nt: NamedTupleMeta[T]) \
- -> Iterable[Tuple[T, Iterable[NamedTuple]]]:
- def group_by_keys(src_nt):
- src_d = src_nt._asdict()
- # now remove the keys that aren't legal in dst.
- for illegal_key in set(src_d.keys()) - set(dst_nt._fields):
- if illegal_key in src_d:
- del src_d[illegal_key]
-
- return dst_nt(**src_d)
-
- for args_list_it in itertools.groupby(run_combinations, group_by_keys):
- (group_key_value, args_it) = args_list_it
- yield (group_key_value, args_it)
diff --git a/startop/scripts/app_startup/lib/args_utils_test.py b/startop/scripts/app_startup/lib/args_utils_test.py
deleted file mode 100644
index 4b7e0fa..0000000
--- a/startop/scripts/app_startup/lib/args_utils_test.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-#
-
-"""Unit tests for the args_utils.py script."""
-
-import typing
-
-import args_utils
-
-def generate_run_combinations(*args):
- # expand out the generator values so that assert x == y works properly.
- return [i for i in args_utils.generate_run_combinations(*args)]
-
-def test_generate_run_combinations():
- blank_nd = typing.NamedTuple('Blank')
- assert generate_run_combinations(blank_nd, {}, 1) == [()], "empty"
- assert generate_run_combinations(blank_nd, {'a': ['a1', 'a2']}) == [
- ()], "empty filter"
- a_nd = typing.NamedTuple('A', [('a', str)])
- assert generate_run_combinations(a_nd, {'a': None}) == [(None,)], "None"
- assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}) == [('a1',), (
- 'a2',)], "one item"
- assert generate_run_combinations(a_nd,
- {'a': ['a1', 'a2'], 'b': ['b1', 'b2']}) == [
- ('a1',), ('a2',)], \
- "one item filter"
- assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}, 2) == [('a1',), (
- 'a2',), ('a1',), ('a2',)], "one item"
- ab_nd = typing.NamedTuple('AB', [('a', str), ('b', str)])
- assert generate_run_combinations(ab_nd,
- {'a': ['a1', 'a2'],
- 'b': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
- ab_nd('a1', 'b2'),
- ab_nd('a2', 'b1'),
- ab_nd('a2', 'b2')], \
- "two items"
-
- assert generate_run_combinations(ab_nd,
- {'as': ['a1', 'a2'],
- 'bs': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
- ab_nd('a1', 'b2'),
- ab_nd('a2', 'b1'),
- ab_nd('a2', 'b2')], \
- "two items plural"
diff --git a/startop/scripts/app_startup/lib/common b/startop/scripts/app_startup/lib/common
deleted file mode 100755
index bedaa1e..0000000
--- a/startop/scripts/app_startup/lib/common
+++ /dev/null
@@ -1,198 +0,0 @@
-#!/bin/bash
-# Copyright 2018, 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.
-
-if [[ -z $ANDROID_BUILD_TOP ]]; then
- echo "Please run source build/envsetup.sh first" >&2
- exit 1
-fi
-
-source $ANDROID_BUILD_TOP/build/envsetup.sh
-
-verbose_print() {
- if [[ "$verbose" == "y" ]]; then
- echo "$@" >&2
- fi
-}
-
-remote_pidof() {
- local procname="$1"
- adb shell ps | grep "$procname" | awk '{print $2;}'
-}
-
-remote_pkill() {
- local procname="$1"
- shift
-
- local the_pids=$(remote_pidof "$procname")
- local pid
-
- for pid in $the_pids; do
- verbose_print adb shell kill "$@" "$pid"
- adb shell kill "$@" "$pid"
- done
-}
-
-get_activity_name() {
- local package="$1"
- local action_key="android.intent.action.MAIN:"
-
- # Example query-activities output being parsed:
- #
- # Activity #14:
- # priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true
- # com.google.android.videos/com.google.android.youtube.videos.EntryPoint
- # Activity #15:
- # priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true
- # com.google.android.youtube/.app.honeycomb.Shell$HomeActivity
-
- # Given package 'com.google.android.youtube' return '.app.honeycomb.Shell$HomeActivity'
-
- local activity_line="$(adb shell cmd package query-activities --brief -a android.intent.action.MAIN -c android.intent.category.LAUNCHER | grep "$package/")"
- IFS="/" read -a array <<< "$activity_line"
- local activity_name="${array[1]}"
-
- # Activities starting with '.' are shorthand for having their package name prefixed.
- if [[ $activity_name == .* ]]; then
- activity_name="${package}${activity_name}"
- fi
- echo "$activity_name"
-}
-
-# Use with logcat_from_timestamp to skip all past log-lines.
-logcat_save_timestamp() {
- adb shell 'date -u +"%Y-%m-%d %H:%M:%S.%N"'
-}
-
-# Roll forward logcat to only show events
-# since the specified timestamp.
-#
-# i.e. don't look at historical logcat,
-# only look at FUTURE logcat.
-#
-# First use 'logcat_save_timestamp'
-# Then do whatever action you want.
-# Then use 'logcat_from_timestamp_bg $timestamp'
-logcat_from_timestamp_bg() {
- local timestamp="$1"
- shift # drop timestamp from args.
- verbose_print adb logcat -T \"$timestamp\" \"$@\"
- adb logcat -v UTC -T "$timestamp" "$@" &
- logcat_from_timestamp_pid=$!
-}
-
-# Starting at timestamp $2, wait until we seen pattern $3
-# or until a timeout happens in $1 seconds.
-# If successful, also echo the line that matched the pattern.
-#
-# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
-logcat_select_pattern() {
- local timeout="$1"
- local timestamp="$2"
- local pattern="$3"
-
- local logcat_fd
-
- coproc logcat_fd {
- kill_children_quietly() {
- kill "$logcat_pidd"
- wait "$logcat_pidd" 2>/dev/null
- }
-
- trap 'kill_children_quietly' EXIT # kill logcat when this coproc is killed.
-
- # run logcat in the background so it can be killed.
- logcat_from_timestamp_bg "$timestamp"
- logcat_pidd=$logcat_from_timestamp_pid
- wait "$logcat_pidd"
- }
- local logcat_pid="$!"
- verbose_print "[LOGCAT] Spawn pid $logcat_pid"
-
- local timeout_ts="$(date -d "now + ${timeout} seconds" '+%s')"
- local now_ts="0"
-
- local return_code=1
-
- verbose_print "logcat_wait_for_pattern begin"
-
- while read -t "$timeout" -r -u "${logcat_fd[0]}" logcat_output; do
- if (( $VERBOSE_LOGCAT )); then
- verbose_print "LOGCAT: $logcat_output"
- fi
- if [[ "$logcat_output:" == *"$pattern"* ]]; then
- verbose_print "LOGCAT: " "$logcat_output"
- verbose_print "WE DID SEE PATTERN" '<<' "$pattern" '>>.'
- echo "$logcat_output"
- return_code=0
- break
- fi
- now_ts="$(date -d "now" '+%s')"
- if (( now_ts >= timeout_ts )); then
- verbose_print "DID TIMEOUT BEFORE SEEING ANYTHING (timeout=$timeout seconds) " '<<' "$pattern" '>>.'
- break
- fi
- done
-
- # Don't leave logcat lying around since it will keep going.
- kill "$logcat_pid"
- # Suppress annoying 'Terminated...' message.
- wait "$logcat_pid" 2>/dev/null
-
- verbose_print "[LOGCAT] $logcat_pid should be killed"
-
- return $return_code
-}
-
-# Starting at timestamp $2, wait until we seen pattern $3
-# or until a timeout happens in $1 seconds.
-#
-# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
-logcat_wait_for_pattern() {
- logcat_select_pattern "$@" > /dev/null
-}
-
-# Starting at timestamp $2, wait until we seen pattern $3
-# or until a timeout happens in $1 seconds.
-# If successful, extract with the regular expression pattern in #4
-# and return the first capture group.
-#
-# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
-logcat_extract_pattern() {
- local timeout="$1"
- local timestamp="$2"
- local pattern="$3"
- local re_pattern="$4"
-
- local result
- local exit_code
-
- result="$(logcat_select_pattern "$@")"
- exit_code=$?
-
- if [[ $exit_code -ne 0 ]]; then
- return $exit_code
- fi
-
- echo "$result" | sed 's/'"$re_pattern"'/\1/g'
-}
-
-# Join array
-# FOO=(a b c)
-# join_by , "${FOO[@]}" #a,b,c
-join_by() {
- local IFS="$1"
- shift
- echo "$*"
-}
diff --git a/startop/scripts/app_startup/lib/data_frame.py b/startop/scripts/app_startup/lib/data_frame.py
deleted file mode 100644
index 20a2308..0000000
--- a/startop/scripts/app_startup/lib/data_frame.py
+++ /dev/null
@@ -1,201 +0,0 @@
-import itertools
-from typing import Dict, List
-
-class DataFrame:
- """Table-like class for storing a 2D cells table with named columns."""
- def __init__(self, data: Dict[str, List[object]] = {}):
- """
- Create a new DataFrame from a dictionary (keys = headers,
- values = columns).
- """
- self._headers = [i for i in data.keys()]
- self._rows = []
-
- row_num = 0
-
- def get_data_row(idx):
- r = {}
- for header, header_data in data.items():
-
- if not len(header_data) > idx:
- continue
-
- r[header] = header_data[idx]
-
- return r
-
- while True:
- row_dict = get_data_row(row_num)
- if len(row_dict) == 0:
- break
-
- self._append_row(row_dict.keys(), row_dict.values())
- row_num = row_num + 1
-
- def concat_rows(self, other: 'DataFrame') -> None:
- """
- In-place concatenate rows of other into the rows of the
- current DataFrame.
-
- None is added in pre-existing cells if new headers
- are introduced.
- """
- other_datas = other._data_only()
-
- other_headers = other.headers
-
- for d in other_datas:
- self._append_row(other_headers, d)
-
- def _append_row(self, headers: List[str], data: List[object]):
- new_row = {k:v for k,v in zip(headers, data)}
- self._rows.append(new_row)
-
- for header in headers:
- if not header in self._headers:
- self._headers.append(header)
-
- def __repr__(self):
-# return repr(self._rows)
- repr = ""
-
- header_list = self._headers_only()
-
- row_format = u""
- for header in header_list:
- row_format = row_format + u"{:>%d}" %(len(header) + 1)
-
- repr = row_format.format(*header_list) + "\n"
-
- for v in self._data_only():
- repr = repr + row_format.format(*v) + "\n"
-
- return repr
-
- def __eq__(self, other):
- if isinstance(other, self.__class__):
- return self.headers == other.headers and self.data_table == other.data_table
- else:
- print("wrong instance", other.__class__)
- return False
-
- @property
- def headers(self) -> List[str]:
- return [i for i in self._headers_only()]
-
- @property
- def data_table(self) -> List[List[object]]:
- return list(self._data_only())
-
- @property
- def data_table_transposed(self) -> List[List[object]]:
- return list(self._transposed_data())
-
- @property
- def data_row_len(self) -> int:
- return len(self._rows)
-
- def data_row_at(self, idx) -> List[object]:
- """
- Return a single data row at the specified index (0th based).
-
- Accepts negative indices, e.g. -1 is last row.
- """
- row_dict = self._rows[idx]
- l = []
-
- for h in self._headers_only():
- l.append(row_dict.get(h)) # Adds None in blank spots.
-
- return l
-
- def copy(self) -> 'DataFrame':
- """
- Shallow copy of this DataFrame.
- """
- return self.repeat(count=0)
-
- def repeat(self, count: int) -> 'DataFrame':
- """
- Returns a new DataFrame where each row of this dataframe is repeated count times.
- A repeat of a row is adjacent to other repeats of that same row.
- """
- df = DataFrame()
- df._headers = self._headers.copy()
-
- rows = []
- for row in self._rows:
- for i in range(count):
- rows.append(row.copy())
-
- df._rows = rows
-
- return df
-
- def merge_data_columns(self, other: 'DataFrame'):
- """
- Merge self and another DataFrame by adding the data from other column-wise.
- For any headers that are the same, data from 'other' is preferred.
- """
- for h in other._headers:
- if not h in self._headers:
- self._headers.append(h)
-
- append_rows = []
-
- for self_dict, other_dict in itertools.zip_longest(self._rows, other._rows):
- if not self_dict:
- d = {}
- append_rows.append(d)
- else:
- d = self_dict
-
- d_other = other_dict
- if d_other:
- for k,v in d_other.items():
- d[k] = v
-
- for r in append_rows:
- self._rows.append(r)
-
- def data_row_reduce(self, fnc) -> 'DataFrame':
- """
- Reduces the data row-wise by applying the fnc to each row (column-wise).
- Empty cells are skipped.
-
- fnc(Iterable[object]) -> object
- fnc is applied over every non-empty cell in that column (descending row-wise).
-
- Example:
- DataFrame({'a':[1,2,3]}).data_row_reduce(sum) == DataFrame({'a':[6]})
-
- Returns a new single-row DataFrame.
- """
- df = DataFrame()
- df._headers = self._headers.copy()
-
- def yield_by_column(header_key):
- for row_dict in self._rows:
- val = row_dict.get(header_key)
- if val:
- yield val
-
- new_row_dict = {}
- for h in df._headers:
- cell_value = fnc(yield_by_column(h))
- new_row_dict[h] = cell_value
-
- df._rows = [new_row_dict]
- return df
-
- def _headers_only(self):
- return self._headers
-
- def _data_only(self):
- row_len = len(self._rows)
-
- for i in range(row_len):
- yield self.data_row_at(i)
-
- def _transposed_data(self):
- return zip(*self._data_only())
\ No newline at end of file
diff --git a/startop/scripts/app_startup/lib/data_frame_test.py b/startop/scripts/app_startup/lib/data_frame_test.py
deleted file mode 100644
index 1cbc1cb..0000000
--- a/startop/scripts/app_startup/lib/data_frame_test.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-#
-
-"""Unit tests for the data_frame.py script."""
-
-from data_frame import DataFrame
-
-def test_data_frame():
- # trivial empty data frame
- df = DataFrame()
- assert df.headers == []
- assert df.data_table == []
- assert df.data_table_transposed == []
-
- # common case, same number of values in each place.
- df = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, 4], [2, 5], [3, 6]]
- assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
-
- # varying num values.
- df = DataFrame({'many': [1, 2], 'none': []})
- assert df.headers == ['many', 'none']
- assert df.data_table == [[1, None], [2, None]]
- assert df.data_table_transposed == [(1, 2), (None, None)]
-
- df = DataFrame({'many': [], 'none': [1, 2]})
- assert df.headers == ['many', 'none']
- assert df.data_table == [[None, 1], [None, 2]]
- assert df.data_table_transposed == [(None, None), (1, 2)]
-
- # merge multiple data frames
- df = DataFrame()
- df.concat_rows(DataFrame())
- assert df.headers == []
- assert df.data_table == []
- assert df.data_table_transposed == []
-
- df = DataFrame()
- df2 = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
-
- df.concat_rows(df2)
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, 4], [2, 5], [3, 6]]
- assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
-
- df = DataFrame({'TotalTime_ms': [1, 2]})
- df2 = DataFrame({'Displayed_ms': [4, 5]})
-
- df.concat_rows(df2)
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, None], [2, None], [None, 4], [None, 5]]
-
- df = DataFrame({'TotalTime_ms': [1, 2]})
- df2 = DataFrame({'TotalTime_ms': [3, 4], 'Displayed_ms': [5, 6]})
-
- df.concat_rows(df2)
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, None], [2, None], [3, 5], [4, 6]]
-
- # data_row_at
- df = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
- assert df.data_row_at(-1) == [3, 6]
- assert df.data_row_at(2) == [3, 6]
- assert df.data_row_at(1) == [2, 5]
-
- # repeat
- df = DataFrame({'TotalTime_ms': [1], 'Displayed_ms': [4]})
- df2 = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- assert df.repeat(3) == df2
-
- # repeat
- df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- assert df.data_row_len == 3
- df = DataFrame({'TotalTime_ms': [1, 1]})
- assert df.data_row_len == 2
-
- # repeat
- df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- assert df.data_row_len == 3
- df = DataFrame({'TotalTime_ms': [1, 1]})
- assert df.data_row_len == 2
-
- # data_row_reduce
- df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- df_sum = DataFrame({'TotalTime_ms': [3], 'Displayed_ms': [12]})
- assert df.data_row_reduce(sum) == df_sum
-
- # merge_data_columns
- df = DataFrame({'TotalTime_ms': [1, 2, 3]})
- df2 = DataFrame({'Displayed_ms': [3, 4, 5, 6]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame(
- {'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [3, 4, 5, 6]})
-
- df = DataFrame({'TotalTime_ms': [1, 2, 3]})
- df2 = DataFrame({'Displayed_ms': [3, 4]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame(
- {'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [3, 4]})
-
- df = DataFrame({'TotalTime_ms': [1, 2, 3]})
- df2 = DataFrame({'TotalTime_ms': [10, 11]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame({'TotalTime_ms': [10, 11, 3]})
-
- df = DataFrame({'TotalTime_ms': []})
- df2 = DataFrame({'TotalTime_ms': [10, 11]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame({'TotalTime_ms': [10, 11]})
diff --git a/startop/scripts/app_startup/lib/perfetto_trace_collector.py b/startop/scripts/app_startup/lib/perfetto_trace_collector.py
deleted file mode 100644
index 9ffb349..0000000
--- a/startop/scripts/app_startup/lib/perfetto_trace_collector.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Copyright 2019, 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.
-
-"""Class to collector perfetto trace."""
-import datetime
-import os
-import re
-import sys
-import time
-from datetime import timedelta
-from typing import Optional, List, Tuple
-
-# global variables
-DIR = os.path.abspath(os.path.dirname(__file__))
-
-sys.path.append(os.path.dirname(os.path.dirname(DIR)))
-
-import app_startup.lib.adb_utils as adb_utils
-from app_startup.lib.app_runner import AppRunner, AppRunnerListener
-import lib.print_utils as print_utils
-import lib.logcat_utils as logcat_utils
-import iorap.lib.iorapd_utils as iorapd_utils
-
-class PerfettoTraceCollector(AppRunnerListener):
- """ Class to collect perfetto trace.
-
- To set trace duration of perfetto, change the 'trace_duration_ms'.
- To pull the generated perfetto trace on device, set the 'output'.
- """
- TRACE_FILE_SUFFIX = 'perfetto_trace.pb'
- TRACE_DURATION_PROP = 'iorapd.perfetto.trace_duration_ms'
- MS_PER_SEC = 1000
- DEFAULT_TRACE_DURATION = timedelta(milliseconds=5000) # 5 seconds
- _COLLECTOR_TIMEOUT_MULTIPLIER = 10 # take the regular timeout and multiply
-
- def __init__(self,
- package: str,
- activity: Optional[str],
- compiler_filter: Optional[str],
- timeout: Optional[int],
- simulate: bool,
- trace_duration: timedelta = DEFAULT_TRACE_DURATION,
- save_destination_file_path: Optional[str] = None):
- """ Initialize the perfetto trace collector. """
- self.app_runner = AppRunner(package,
- activity,
- compiler_filter,
- timeout,
- simulate)
- self.app_runner.add_callbacks(self)
-
- self.trace_duration = trace_duration
- self.save_destination_file_path = save_destination_file_path
-
- def purge_file(self, suffix: str) -> None:
- print_utils.debug_print('iorapd-perfetto: purge file in ' +
- self._get_remote_path())
- adb_utils.delete_file_on_device(self._get_remote_path())
-
- def run(self) -> Optional[List[Tuple[str]]]:
- """Runs an app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- return self.app_runner.run()
-
- def preprocess(self):
- # Sets up adb environment.
- adb_utils.root()
- adb_utils.disable_selinux()
- time.sleep(1)
-
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- # Remove existing trace and compiler files
- self.purge_file(PerfettoTraceCollector.TRACE_FILE_SUFFIX)
-
- # Set perfetto trace duration prop to milliseconds.
- adb_utils.set_prop(PerfettoTraceCollector.TRACE_DURATION_PROP,
- int(self.trace_duration.total_seconds()*
- PerfettoTraceCollector.MS_PER_SEC))
-
- if not iorapd_utils.stop_iorapd():
- raise RuntimeError('Cannot stop iorapd!')
-
- if not iorapd_utils.enable_iorapd_perfetto():
- raise RuntimeError('Cannot enable perfetto!')
-
- if not iorapd_utils.disable_iorapd_readahead():
- raise RuntimeError('Cannot disable readahead!')
-
- if not iorapd_utils.start_iorapd():
- raise RuntimeError('Cannot start iorapd!')
-
- # Drop all caches to get cold starts.
- adb_utils.vm_drop_cache()
-
- def postprocess(self, pre_launch_timestamp: str):
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- iorapd_utils.disable_iorapd_perfetto()
-
- if self.save_destination_file_path is not None:
- adb_utils.pull_file(self._get_remote_path(),
- self.save_destination_file_path)
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> str:
- """Parses the metric after app startup by reading from logcat in a blocking
- manner until all metrics have been found".
-
- Returns:
- An empty string because the metric needs no further parsing.
- """
- if not self._wait_for_perfetto_trace(pre_launch_timestamp):
- raise RuntimeError('Could not save perfetto app trace file!')
-
- return ''
-
- def _wait_for_perfetto_trace(self, pre_launch_timestamp) -> Optional[str]:
- """ Waits for the perfetto trace being saved to file.
-
- The string is in the format of r".*Perfetto TraceBuffer saved to file:
- <file path>.*"
-
- Returns:
- the string what the program waits for. If the string doesn't show up,
- return None.
- """
- pattern = re.compile(r'.*Perfetto TraceBuffer saved to file: {}.*'.
- format(self._get_remote_path()))
-
- # The pre_launch_timestamp is longer than what the datetime can parse. Trim
- # last three digits to make them align. For example:
- # 2019-07-02 23:20:06.972674825999 -> 2019-07-02 23:20:06.972674825
- assert len(pre_launch_timestamp) == len('2019-07-02 23:20:06.972674825')
- timestamp = datetime.datetime.strptime(pre_launch_timestamp[:-3],
- '%Y-%m-%d %H:%M:%S.%f')
-
- # The timeout of perfetto trace is longer than the normal app run timeout.
- timeout_dt = self.app_runner.timeout * PerfettoTraceCollector._COLLECTOR_TIMEOUT_MULTIPLIER
- timeout_end = timestamp + datetime.timedelta(seconds=timeout_dt)
-
- return logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_end)
-
- def _get_remote_path(self):
- # For example: android.music%2Fmusic.TopLevelActivity.perfetto_trace.pb
- return iorapd_utils._iorapd_path_to_data_file(self.app_runner.package,
- self.app_runner.activity,
- PerfettoTraceCollector.TRACE_FILE_SUFFIX)
diff --git a/startop/scripts/app_startup/lib/perfetto_trace_collector_test.py b/startop/scripts/app_startup/lib/perfetto_trace_collector_test.py
deleted file mode 100644
index 8d94fc5..0000000
--- a/startop/scripts/app_startup/lib/perfetto_trace_collector_test.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-
-"""Unit tests for the data_frame.py script."""
-import os
-import sys
-from pathlib import Path
-from datetime import timedelta
-
-from mock import call, patch
-from perfetto_trace_collector import PerfettoTraceCollector
-
-sys.path.append(Path(os.path.realpath(__file__)).parents[2])
-from app_startup.lib.app_runner import AppRunner
-
-RUNNER = PerfettoTraceCollector(package='music',
- activity='MainActivity',
- compiler_filter=None,
- timeout=10,
- simulate=False,
- trace_duration = timedelta(milliseconds=1000),
- # No actual file will be created. Just to
- # check the command.
- save_destination_file_path='/tmp/trace.pb')
-
-def _mocked_run_shell_command(*args, **kwargs):
- if args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
- return (True, '9999')
- else:
- return (True, '')
-
-@patch('lib.logcat_utils.blocking_wait_for_logcat_pattern')
-@patch('lib.cmd_utils.run_shell_command')
-def test_perfetto_trace_collector_preprocess(mock_run_shell_command,
- mock_blocking_wait_for_logcat_pattern):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_pattern.return_value = "Succeed!"
-
- RUNNER.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call(
- 'adb shell "[[ -f \'/data/misc/iorapd/music%2FMainActivity.perfetto_trace.pb\' ]] '
- '&& rm -f \'/data/misc/iorapd/music%2FMainActivity.perfetto_trace.pb\' || exit 0"'),
- call('adb shell "setprop "iorapd.perfetto.trace_duration_ms" "1000""'),
- call(
- 'bash -c "source {}; iorapd_stop"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call(
- 'bash -c "source {}; iorapd_perfetto_enable"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call(
- 'bash -c "source {}; iorapd_readahead_disable"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call(
- 'bash -c "source {}; iorapd_start"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('adb shell "echo 3 > /proc/sys/vm/drop_caches"')]
-
- mock_run_shell_command.assert_has_calls(calls)
-
-@patch('lib.logcat_utils.blocking_wait_for_logcat_pattern')
-@patch('lib.cmd_utils.run_shell_command')
-def test_perfetto_trace_collector_postprocess(mock_run_shell_command,
- mock_blocking_wait_for_logcat_pattern):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_pattern.return_value = "Succeed!"
-
- RUNNER.postprocess('2019-07-02 23:20:06.972674825')
-
- calls = [call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call(
- 'bash -c "source {}; iorapd_perfetto_disable"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('adb pull '
- '"/data/misc/iorapd/music%2FMainActivity.perfetto_trace.pb" '
- '"/tmp/trace.pb"')]
-
- mock_run_shell_command.assert_has_calls(calls)
diff --git a/startop/scripts/app_startup/parse_metrics b/startop/scripts/app_startup/parse_metrics
deleted file mode 100755
index 3fa1462..0000000
--- a/startop/scripts/app_startup/parse_metrics
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, 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.
-
-usage() {
- cat <<EOF
-Usage: launch_application package activity | parse_metrics --package <name> --timestamp <timestamp> [OPTIONS]...
-
- Reads from stdin the result of 'am start' metrics. May also parse logcat
- for additional metrics.
-
- Output form:
-
- MetricName_unit=numeric_value
- MetricName2_unit=numeric_value2
-
- This may block until all desired metrics are parsed from logcat.
- To get a list of metrics without doing real parsing, use --simulate.
-
- To add package-specific metrics, add a script called 'metrics/\$full_package_name'
- that exposes additional metrics in same way as above.
-
- (required)
- -p, --package <name> package of the app that is being used
- -ts, --timestamp <name> logcat timestamp [only looks at logcat entries after this timestamp].
-
- (optional)
- -s, --simulate prints dummy values instead of real metrics
- -a, --activity <name> activity to use (default: inferred)
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -t, --timeout <sec> how many seconds to timeout when trying to wait for logcat to change
- -rfd, --reportfullydrawn wait for report fully drawn (default: off)
-EOF
-}
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/lib/common"
-
-report_fully_drawn="n"
-package=""
-activity=""
-timeout=5
-simulate="n"
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -a|--activity)
- activity="$2"
- shift
- ;;
- -v|--verbose)
- export verbose="y"
- ;;
- -t|--timeout)
- timeout="$2"
- shift
- ;;
- -ts|--timestamp)
- timestamp="$2"
- shift
- ;;
- -s|--simulate)
- simulate="y"
- ;;
- -rfd|--reportfullydrawn)
- report_fully_drawn="y"
- ;;
-
-
- *)
- echo "Invalid argument: $1" >&2
- exit 1
- esac
- shift
- done
-}
-
-# Main entry point
-if [[ $# -eq 0 ]]; then
- usage
- exit 1
-else
- parse_arguments "$@"
-
- # if we do not have have package exit early with an error
- [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 64
-
- # ignore timestamp for --simulate. it's optional.
- if [[ $simulate == y ]]; then
- timestamp=0
- fi
-
- # if we do not have timestamp, exit early with an error
- [[ "$timestamp" == "" ]] && echo "--timestamp not specified" 1>&2 && exit 64
-
- if [[ "$activity" == "" ]] && [[ "$simulate" != "y" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 64
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-fi
-
-parse_metric_from_logcat() {
- local metric_name="$1"
- local pattern="$2"
- local re_pattern="$3"
- local retcode
- local result
- local sec
- local ms
-
- # parse logcat for 'Displayed...' and that other one...
-
- # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
- verbose_print "parse_metric_from_logcat: $re_pattern"
-
-
- echo -ne "$metric_name="
-
- if [[ $simulate == y ]]; then
- echo "-1"
- return 0
- fi
-
- result="$(logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern")"
- retcode=$?
-
- if [[ $retcode -ne 0 ]]; then
- # Timed out before finding the pattern. Could also mean the pattern is wrong.
- echo "Parse $re_pattern from logcat TIMED OUT after $timeout seconds." >&2
- echo "-$?"
- return $retcode
- fi
-
- # "10s123ms" -> "10s123"
- result=${result/ms/}
- if [[ $result =~ s ]]; then
- ms=${result/*s/}
- sec=${result/s*/}
- else
- sec=0
- ms=$result
- fi
- ((result=sec*1000+ms))
-
- echo "$result"
- return $retcode
-}
-
-
-total_time="-1"
-if [[ $simulate != y ]]; then
- verbose_print 'logcat timestamp NOW: ' $(logcat_save_timestamp)
-
- # parse stdin for 'am start' result
- while read -t "$timeout" -r input_line; do
- verbose_print 'stdin:' "$input_line"
- if [[ $input_line == *TotalTime:* ]]; then
- total_time="$(echo "$input_line" | sed 's/TotalTime: \([[:digit:]]\+\)/\1/g')"
- # but keep reading the rest from stdin until <EOF>
- fi
- done
-fi
-
-echo "TotalTime_ms=$total_time"
-
-# parse logcat for 'Displayed...' and that other one...
-
-# 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
-pattern="ActivityTaskManager: Displayed ${package}"
-re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'
-
-parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern"
-
-# Only track ReportFullyDrawn with --reportfullydrawn/-rfd flags
-if [[ $report_fully_drawn == y ]]; then
- # 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms
- pattern="ActivityTaskManager: Fully drawn ${package}"
- #re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*'
- re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'
-
- parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern"
-fi
-
-# also call into package-specific scripts if there are additional metrics
-if [[ -x "$DIR/metrics/$package" ]]; then
- source "$DIR/metrics/$package" "$timestamp"
-else
- verbose_print parse_metrics: no per-package metrics script found at "$DIR/metrics/$package"
-fi
diff --git a/startop/scripts/app_startup/query_compiler_filter.py b/startop/scripts/app_startup/query_compiler_filter.py
deleted file mode 100755
index ea14264..0000000
--- a/startop/scripts/app_startup/query_compiler_filter.py
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-
-#
-#
-# Query the current compiler filter for an application by its package name.
-# (By parsing the results of the 'adb shell dumpsys package $package' command).
-# The output is a string "$compilation_filter $compilation_reason $isa".
-#
-# See --help for more details.
-#
-# -----------------------------------
-#
-# Sample usage:
-#
-# $> ./query_compiler_filter.py --package com.google.android.calculator
-# speed-profile unknown arm64
-#
-
-import argparse
-import os
-import re
-import sys
-
-# TODO: refactor this with a common library file with analyze_metrics.py
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
-
-from typing import List, NamedTuple, Iterable
-
-_DEBUG_FORCE = None # Ignore -d/--debug if this is not none.
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Query the compiler filter for a package.")
- # argparse considers args starting with - and -- optional in --help, even though required=True.
- # by using a named argument group --help will clearly say that it's required instead of optional.
- required_named = parser.add_argument_group('required named arguments')
- required_named.add_argument('-p', '--package', action='store', dest='package', help='package of the application', required=True)
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-i', '--isa', '--instruction-set', action='store', dest='instruction_set', help='which instruction set to select. defaults to the first one available if not specified.', choices=('arm64', 'arm', 'x86_64', 'x86'))
- optional_named.add_argument('-s', '--simulate', dest='simulate', action='store_true', help='Print which commands will run, but don\'t run the apps')
- optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
-
- return parser.parse_args(argv)
-
-def remote_dumpsys_package(package: str, simulate: bool) -> str:
- # --simulate is used for interactive debugging/development, but also for the unit test.
- if simulate:
- return """
-Dexopt state:
- [%s]
- path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
- arm64: [status=speed-profile] [reason=unknown]
- path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
- arm: [status=speed] [reason=first-boot]
- path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
- x86: [status=quicken] [reason=install]
-""" %(package, package, package, package)
-
- code, res = cmd_utils.execute_arbitrary_command(['adb', 'shell', 'dumpsys',
- 'package', package],
- simulate=False,
- timeout=5,
- shell=False)
- if code:
- return res
- else:
- raise AssertionError("Failed to dumpsys package, errors = %s", res)
-
-ParseTree = NamedTuple('ParseTree', [('label', str), ('children', List['ParseTree'])])
-DexoptState = ParseTree # With the Dexopt state: label
-ParseResult = NamedTuple('ParseResult', [('remainder', List[str]), ('tree', ParseTree)])
-
-def find_parse_subtree(parse_tree: ParseTree, match_regex: str) -> ParseTree:
- if re.match(match_regex, parse_tree.label):
- return parse_tree
-
- for node in parse_tree.children:
- res = find_parse_subtree(node, match_regex)
- if res:
- return res
-
- return None
-
-def find_parse_children(parse_tree: ParseTree, match_regex: str) -> Iterable[ParseTree]:
- for node in parse_tree.children:
- if re.match(match_regex, node.label):
- yield node
-
-def parse_tab_subtree(label: str, str_lines: List[str], separator=' ', indent=-1) -> ParseResult:
- children = []
-
- get_indent_level = lambda line: len(line) - len(line.lstrip())
-
- line_num = 0
-
- keep_going = True
- while keep_going:
- keep_going = False
-
- for line_num in range(len(str_lines)):
- line = str_lines[line_num]
- current_indent = get_indent_level(line)
-
- print_utils.debug_print("INDENT=%d, LINE=%s" %(current_indent, line))
-
- current_label = line.lstrip()
-
- # skip empty lines
- if line.lstrip() == "":
- continue
-
- if current_indent > indent:
- parse_result = parse_tab_subtree(current_label, str_lines[line_num+1::], separator, current_indent)
- str_lines = parse_result.remainder
- children.append(parse_result.tree)
- keep_going = True
- else:
- # current_indent <= indent
- keep_going = False
-
- break
-
- new_remainder = str_lines[line_num::]
- print_utils.debug_print("NEW REMAINDER: ", new_remainder)
-
- parse_tree = ParseTree(label, children)
- return ParseResult(new_remainder, parse_tree)
-
-def parse_tab_tree(str_tree: str, separator=' ', indentation_level=-1) -> ParseTree:
-
- label = None
- lst = []
-
- line_num = 0
- line_lst = str_tree.split("\n")
-
- return parse_tab_subtree("", line_lst, separator, indentation_level).tree
-
-def parse_dexopt_state(dumpsys_tree: ParseTree) -> DexoptState:
- res = find_parse_subtree(dumpsys_tree, "Dexopt(\s+)state[:]?")
- if not res:
- raise AssertionError("Could not find the Dexopt state")
- return res
-
-def find_first_compiler_filter(dexopt_state: DexoptState, package: str, instruction_set: str) -> str:
- lst = find_all_compiler_filters(dexopt_state, package)
-
- print_utils.debug_print("all compiler filters: ", lst)
-
- for compiler_filter_info in lst:
- if not instruction_set:
- return compiler_filter_info
-
- if compiler_filter_info.isa == instruction_set:
- return compiler_filter_info
-
- return None
-
-CompilerFilterInfo = NamedTuple('CompilerFilterInfo', [('isa', str), ('status', str), ('reason', str)])
-
-def find_all_compiler_filters(dexopt_state: DexoptState, package: str) -> List[CompilerFilterInfo]:
-
- lst = []
- package_tree = find_parse_subtree(dexopt_state, re.escape("[%s]" %package))
-
- if not package_tree:
- raise AssertionError("Could not find any package subtree for package %s" %(package))
-
- print_utils.debug_print("package tree: ", package_tree)
-
- for path_tree in find_parse_children(package_tree, "path: "):
- print_utils.debug_print("path tree: ", path_tree)
-
- matchre = re.compile("([^:]+):\s+\[status=([^\]]+)\]\s+\[reason=([^\]]+)\]")
-
- for isa_node in find_parse_children(path_tree, matchre):
-
- matches = re.match(matchre, isa_node.label).groups()
-
- info = CompilerFilterInfo(*matches)
- lst.append(info)
-
- return lst
-
-def main() -> int:
- opts = parse_options()
- cmd_utils._debug = opts.debug
- if _DEBUG_FORCE is not None:
- cmd_utils._debug = _DEBUG_FORCE
- print_utils.debug_print("parsed options: ", opts)
-
- # Note: This can often 'fail' if the package isn't actually installed.
- package_dumpsys = remote_dumpsys_package(opts.package, opts.simulate)
- print_utils.debug_print("package dumpsys: ", package_dumpsys)
- dumpsys_parse_tree = parse_tab_tree(package_dumpsys, package_dumpsys)
- print_utils.debug_print("parse tree: ", dumpsys_parse_tree)
- dexopt_state = parse_dexopt_state(dumpsys_parse_tree)
-
- filter = find_first_compiler_filter(dexopt_state, opts.package, opts.instruction_set)
-
- if filter:
- print(filter.status, end=' ')
- print(filter.reason, end=' ')
- print(filter.isa)
- else:
- print("ERROR: Could not find any compiler-filter for package %s, isa %s" %(opts.package, opts.instruction_set), file=sys.stderr)
- return 1
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/query_compiler_filter_test.py b/startop/scripts/app_startup/query_compiler_filter_test.py
deleted file mode 100755
index a751a43..0000000
--- a/startop/scripts/app_startup/query_compiler_filter_test.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018, 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.
-#
-
-"""
-Unit tests for the query_compiler_filter.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./query_compiler_filter.py
- $> pytest query_compiler_filter.py
- $> python -m pytest query_compiler_filter.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-from contextlib import contextmanager
-import io
-import shlex
-import sys
-import typing
-
-# pip imports
-import pytest
-
-# local imports
-import query_compiler_filter as qcf
-
-@contextmanager
-def redirect_stdout_stderr():
- """Redirect stdout/stderr to a new StringIO for duration of context."""
- old_stdout = sys.stdout
- old_stderr = sys.stderr
- new_stdout = io.StringIO()
- sys.stdout = new_stdout
- new_stderr = io.StringIO()
- sys.stderr = new_stderr
- try:
- yield (new_stdout, new_stderr)
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
- # Seek back to the beginning so we can read whatever was written into it.
- new_stdout.seek(0)
- new_stderr.seek(0)
-
-@contextmanager
-def replace_argv(argv):
- """ Temporarily replace argv for duration of this context."""
- old_argv = sys.argv
- sys.argv = [sys.argv[0]] + argv
- try:
- yield
- finally:
- sys.argv = old_argv
-
-def exec_main(argv):
- """Run the query_compiler_filter main function with the provided arguments.
-
- Returns the stdout result when successful, assertion failure otherwise.
- """
- try:
- with redirect_stdout_stderr() as (the_stdout, the_stderr):
- with replace_argv(argv):
- code = qcf.main()
- assert 0 == code, the_stderr.readlines()
-
- all_lines = the_stdout.readlines()
- return "".join(all_lines)
- finally:
- the_stdout.close()
- the_stderr.close()
-
-def test_query_compiler_filter():
- # no --instruction-set specified: provide whatever was the 'first' filter.
- assert exec_main(['--simulate',
- '--package', 'com.google.android.apps.maps']) == \
- "speed-profile unknown arm64\n"
-
- # specifying an instruction set finds the exact compiler filter match.
- assert exec_main(['--simulate',
- '--package', 'com.google.android.apps.maps',
- '--instruction-set', 'arm64']) == \
- "speed-profile unknown arm64\n"
-
- assert exec_main(['--simulate',
- '--package', 'com.google.android.apps.maps',
- '--instruction-set', 'arm']) == \
- "speed first-boot arm\n"
-
- assert exec_main(['--simulate',
- '--debug',
- '--package', 'com.google.android.apps.maps',
- '--instruction-set', 'x86']) == \
- "quicken install x86\n"
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/run_app_with_prefetch b/startop/scripts/app_startup/run_app_with_prefetch
deleted file mode 100755
index 31f6253..0000000
--- a/startop/scripts/app_startup/run_app_with_prefetch
+++ /dev/null
@@ -1,487 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018, 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.
-
-usage() {
- cat <<EOF
-Usage: run_app_with_prefetch --package <name> [OPTIONS]...
-
- -p, --package <name> package of the app to test
- -a, --activity <name> activity to use
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -i, --input <file> trace file protobuf (default 'TraceFile.pb')
- -r, --readahead <mode> cold, warm, fadvise, mlock (default 'warm')
- -w, --when <when> aot or jit (default 'jit')
- -c, --count <count> how many times to run (default 1)
- -s, --sleep <sec> how long to sleep after readahead
- -t, --timeout <sec> how many seconds to timeout in between each app run (default 10)
- -o, --output <file.csv> what file to write the performance results into as csv (default stdout)
-EOF
-}
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/../iorap/common"
-
-report_fully_drawn="n"
-needs_trace_file="n"
-input_file=""
-package=""
-mode='warm'
-count=2
-sleep_time=2
-timeout=10
-output="" # stdout by default
-when="jit"
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -a|--activity)
- activity="$2"
- shift
- ;;
- -i|--input)
- input_file="$2"
- shift
- ;;
- -v|--verbose)
- export verbose="y"
- ;;
- -r|--readahead)
- mode="$2"
- shift
- ;;
- -rfd|--reportfullydrawn)
- report_fully_drawn="y"
- shift
- ;;
- -c|--count)
- count="$2"
- ((count+=1))
- shift
- ;;
- -s|--sleep)
- sleep_time="$2"
- shift
- ;;
- -t|--timeout)
- timeout="$2"
- shift
- ;;
- -o|--output)
- output="$2"
- shift
- ;;
- -w|--when)
- when="$2"
- shift
- ;;
- --compiler-filter)
- compiler_filter="$2"
- shift
- ;;
- *)
- echo "Invalid argument: $1" >&2
- exit 1
- esac
- shift
- done
-
- if [[ $when == "aot" ]]; then
- # TODO: re-implement aot later for experimenting.
- echo "Error: --when $when is unsupported" >&2
- exit 1
- elif [[ $when != "jit" ]]; then
- echo "Error: --when must be one of (aot jit)." >&2
- exit 1
- fi
-}
-
-echo_to_output_file() {
- if [[ "x$output" != x ]]; then
- echo "$@" >> $output
- fi
- # Always echo to stdout as well.
- echo "$@"
-}
-
-find_package_path() {
- local pkg="$1"
-
- res="$(adb shell find "/data/app/$pkg"-'*' -maxdepth 0 2> /dev/null)"
- if [[ -z $res ]]; then
- res="$(adb shell find "/system/app/$pkg"-'*' -maxdepth 0 2> /dev/null)"
- fi
- echo "$res"
-}
-
-# Main entry point
-if [[ $# -eq 0 ]]; then
- usage
- exit 1
-else
- parse_arguments "$@"
-
- # if we do not have have package exit early with an error
- [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 1
-
- if [[ $mode != "cold" && $mode != "warm" ]]; then
- needs_trace_file="y"
- if [[ -z "$input_file" ]] || ! [[ -f $input_file ]]; then
- echo "--input not specified" 1>&2
- exit 1
- fi
- fi
-
- if [[ "$activity" == "" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 1
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-fi
-
-adb root > /dev/null
-
-if [[ ($when == jit) || ($when == aot) ]] && [[ "$(adb shell getenforce)" != "Permissive" ]]; then
- echo "Disable selinux permissions and restart framework."
- adb shell setenforce 0
- adb shell stop
- adb shell start
- adb wait-for-device
-fi
-
-# TODO: set performance governor etc, preferrably only once
-# before every single app run.
-
-# Kill everything before running.
-remote_pkill "$package"
-sleep 1
-
-timings_array=()
-
-package_path="$(find_package_path "$package")"
-if [[ $? -ne 0 ]]; then
- echo "Failed to detect package path for '$package'" >&2
- exit 1
-fi
-verbose_print "Package was in path '$package_path'"
-
-application_trace_file_path="$package_path/TraceFile.pb"
-trace_file_directory="$package_path"
-if [[ $needs_trace_file == y ]]; then
- # system server always passes down the package path in a hardcoded spot.
- if [[ $when == "jit" ]]; then
- if ! iorapd_compiler_install_trace_file "$package" "$activity" "$input_file"; then
- echo "Error: Failed to install compiled TraceFile.pb for '$package/$activity'" >&2
- exit 1
- fi
- keep_application_trace_file="y"
- else
- echo "TODO: --readahead=aot is non-functional and needs to be fixed." >&2
- exit 1
- # otherwise use a temporary directory to get normal non-jit behavior.
- trace_file_directory="/data/local/tmp/prefetch/$package"
- adb shell mkdir -p "$trace_file_directory"
- verbose_print adb push "$input_file" "$trace_file_directory/TraceFile.pb"
- adb push "$input_file" "$trace_file_directory/TraceFile.pb"
- fi
-fi
-
-# Everything other than JIT: remove the trace file,
-# otherwise system server activity hints will kick in
-# and the new just-in-time app pre-warmup will happen.
-if [[ $keep_application_trace_file == "n" ]]; then
- iorapd_compiler_purge_trace_file "$package" "$activity"
-fi
-
-# Perform AOT readahead/pinning/etc when an application is about to be launched.
-# For JIT readahead, we allow the system to handle it itself (this is a no-op).
-#
-# For warm, cold, etc modes which don't need readahead this is always a no-op.
-perform_aot() {
- local the_when="$1" # user: aot, jit
- local the_mode="$2" # warm, cold, fadvise, mlock, etc.
-
- # iorapd readahead for jit+(mlock/fadvise)
- if [[ $the_when == "jit" && $the_mode != 'warm' && $the_mode != 'cold' ]]; then
- iorapd_readahead_enable
- return 0
- fi
-
- if [[ $the_when != "aot" ]]; then
- # TODO: just in time implementation.. should probably use system server.
- return 0
- fi
-
- # any non-warm/non-cold modes should use the iorap-activity-hint wrapper script.
- if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
-
- # TODO: add activity_hint_sender.exp
- verbose_print "starting with package=$package package_path=$trace_file_directory"
- coproc hint_sender_fd { $ANDROID_BUILD_TOP/system/iorap/src/sh/activity_hint_sender.exp "$package" "$trace_file_directory" "$the_mode"; }
- hint_sender_pid=$!
- verbose_print "Activity hint sender began"
-
- notification_success="n"
- while read -r -u "${hint_sender_fd[0]}" hint_sender_output; do
- verbose_print "$hint_sender_output"
- if [[ "$hint_sender_output" == "Press any key to send completed event..."* ]]; then
- verbose_print "WE DID SEE NOTIFICATION SUCCESS."
- notification_success='y'
- # Give it some time to actually perform the readaheads.
- sleep $sleep_time
- break
- fi
- done
-
- if [[ $notification_success == 'n' ]]; then
- echo "[FATAL] Activity hint notification failed." 1>&2
- exit 1
- fi
- fi
-}
-
-# Perform cleanup at the end of each loop iteration.
-perform_post_launch_cleanup() {
- local the_when="$1" # user: aot, jit
- local the_mode="$2" # warm, cold, fadvise, mlock, etc.
- local logcat_timestamp="$3" # timestamp from before am start.
- local res
-
- if [[ $the_when != "aot" ]]; then
- if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
- # Validate that readahead completes.
- # If this fails for some reason, then this will also discard the timing of the run.
- iorapd_readahead_wait_until_finished "$package" "$activity" "$logcat_timestamp" "$timeout"
- res=$?
-
- iorapd_readahead_disable
-
- return $res
- fi
- # Don't need to do anything for warm or cold.
- return 0
- fi
-
- # any non-warm/non-cold modes should use the iorap-activity-hint wrapper script.
- if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
- # Clean up the hint sender by telling it that the launch was completed,
- # and to shutdown the watcher.
- echo "Done\n" >&"${hint_sender_fd[1]}"
-
- while read -r -u "${hint_sender_fd[0]}" hint_sender_output; do
- verbose_print "$hint_sender_output"
- done
-
- wait $hint_sender_pid
- fi
-}
-
-configure_compiler_filter() {
- local the_compiler_filter="$1"
- local the_package="$2"
- local the_activity="$3"
-
- if [[ -z $the_compiler_filter ]]; then
- verbose_print "No --compiler-filter specified, don't need to force it."
- return 0
- fi
-
- local current_compiler_filter_info="$("$DIR"/query_compiler_filter.py --package "$the_package")"
- local res=$?
- if [[ $res -ne 0 ]]; then
- return $res
- fi
-
- local current_compiler_filter
- local current_reason
- local current_isa
- read current_compiler_filter current_reason current_isa <<< "$current_compiler_filter_info"
-
- verbose_print "Compiler Filter="$current_compiler_filter "Reason="$current_reason "Isa="$current_isa
-
- # Don't trust reasons that aren't 'unknown' because that means we didn't manually force the compilation filter.
- # (e.g. if any automatic system-triggered compilations are not unknown).
- if [[ $current_reason != "unknown" ]] || [[ $current_compiler_filter != $the_compiler_filter ]]; then
- verbose_print "$DIR"/force_compiler_filter --compiler-filter "$the_compiler_filter" --package "$the_package" --activity "$the_activity"
- "$DIR"/force_compiler_filter --compiler-filter "$the_compiler_filter" --package "$the_package" --activity "$the_activity"
- res=$?
- else
- verbose_print "Queried compiler-filter matched requested compiler-filter, skip forcing."
- res=0
- fi
-
- return $res
-}
-
-# Ensure the APK is currently compiled with whatever we passed in via --compiler-filter.
-# No-op if this option was not passed in.
-configure_compiler_filter "$compiler_filter" "$package" "$activity" || exit 1
-
-# convert 'a=b\nc=d\ne=f\n...' into 'b,d,f,...'
-parse_metrics_output_string() {
- # single string with newlines in it.
- local input="$1"
-
- local metric_name
- local metric_value
- local rest
-
- local all_metrics=()
-
- # (n1=v1 n2=v2 n3=v3 ...)
- readarray -t all_metrics <<< "$input"
-
- local kv_pair=()
- local i
-
- for i in "${all_metrics[@]}"
- do
- verbose_print "parse_metrics_output: element '$i'"
- # name=value
-
- IFS='=' read -r metric_name metric_value rest <<< "$i"
-
- verbose_print "parse_metrics_output: metric_value '$metric_value'"
-
- # (value1 value2 value3 ...)
- all_metrics+=(${metric_value})
- done
-
- # "value1,value2,value3,..."
- join_by ',' "${all_metrics[@]}"
-}
-
-# convert 'a=b\nc=d\ne=f\n... into b,d,f,...'
-parse_metrics_output() {
- local metric_name
- local metric_value
- local rest
-
- local all_metrics=()
-
- while IFS='=' read -r metric_name metric_value rest; do
- verbose_print "metric: $metric_name, value: $metric_value; rest: $rest"
- all_metrics+=($metric_value)
- done
-
- join_by ',' "${all_metrics[@]}"
-}
-
-# convert 'a=b\nc=d\ne=f\n... into b,d,f,...'
-parse_metrics_header() {
- local metric_name
- local metric_value
- local rest
-
- local all_metrics=()
-
- while IFS='=' read -r metric_name metric_value rest; do
- verbose_print "metric: $metric_name, value: $metric_value; rest: $rest"
- all_metrics+=($metric_name)
- done
-
- join_by ',' "${all_metrics[@]}"
-}
-
-if [[ $report_fully_drawn == y ]]; then
- metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate --reportfullydrawn | parse_metrics_header)"
-else
- metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate | parse_metrics_header)"
-fi
-
-# TODO: This loop logic could probably be moved into app_startup_runner.py
-for ((i=0;i<count;++i)) do
- verbose_print "=========================================="
- verbose_print "==== ITERATION $i ===="
- verbose_print "=========================================="
- if [[ $mode != "warm" ]]; then
- # The package must be killed **before** we drop caches, otherwise pages will stay resident.
- verbose_print "Kill package for non-warm start."
- remote_pkill "$package"
- verbose_print "Drop caches for non-warm start."
- # Drop all caches to get cold starts.
- adb shell "echo 3 > /proc/sys/vm/drop_caches"
- fi
-
- perform_aot "$when" "$mode"
-
- verbose_print "Running with timeout $timeout"
-
- pre_launch_timestamp="$(logcat_save_timestamp)"
-
- # TODO: multiple metrics output.
-
-if [[ $report_fully_drawn == y ]]; then
- total_time="$(timeout $timeout "$DIR/launch_application" "$package" "$activity" | "$DIR/parse_metrics" --package "$package" --activity "$activity" --timestamp "$pre_launch_timestamp" --reportfullydrawn | parse_metrics_output)"
-else
- total_time="$(timeout $timeout "$DIR/launch_application" "$package" "$activity" | "$DIR/parse_metrics" --package "$package" --activity "$activity" --timestamp "$pre_launch_timestamp" | parse_metrics_output)"
-fi
-
- if [[ $? -ne 0 ]]; then
- echo "WARNING: Skip bad result, try iteration again." >&2
- ((i=i-1))
- continue
- fi
-
- perform_post_launch_cleanup "$when" "$mode" "$pre_launch_timestamp"
-
- if [[ $? -ne 0 ]]; then
- echo "WARNING: Skip bad cleanup, try iteration again." >&2
- ((i=i-1))
- continue
- fi
-
- echo "Iteration $i. Total time was: $total_time"
-
- timings_array+=("$total_time")
-done
-
-# drop the first result which is usually garbage.
-timings_array=("${timings_array[@]:1}")
-
-# Print the CSV header first.
-echo_to_output_file "$metrics_header"
-
-# Print out interactive/debugging timings and averages.
-# Other scripts should use the --output flag and parse the CSV.
-for tim in "${timings_array[@]}"; do
- echo_to_output_file "$tim"
-done
-
-if [[ x$output != x ]]; then
- echo " Saved results to '$output'"
-fi
-
-if [[ $needs_trace_file == y ]] ; then
- iorapd_compiler_purge_trace_file "$package" "$activity"
-fi
-
-# Kill the process to ensure AM isn't keeping it around.
-remote_pkill "$package"
-
-exit 0
diff --git a/startop/scripts/app_startup/run_app_with_prefetch.py b/startop/scripts/app_startup/run_app_with_prefetch.py
deleted file mode 100755
index 2f1eff2..0000000
--- a/startop/scripts/app_startup/run_app_with_prefetch.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-"""Runner of one test given a setting.
-
-Run app and gather the measurement in a certain configuration.
-Print the result to stdout.
-See --help for more details.
-
-Sample usage:
- $> ./python run_app_with_prefetch.py -p com.android.settings -a
- com.android.settings.Settings -r fadvise -i input
-
-"""
-
-import argparse
-import os
-import sys
-import time
-from typing import List, Tuple, Optional
-
-# local imports
-import lib.adb_utils as adb_utils
-from lib.app_runner import AppRunner, AppRunnerListener
-
-# global variables
-DIR = os.path.abspath(os.path.dirname(__file__))
-
-sys.path.append(os.path.dirname(DIR))
-import lib.print_utils as print_utils
-import lib.cmd_utils as cmd_utils
-import iorap.lib.iorapd_utils as iorapd_utils
-
-class PrefetchAppRunner(AppRunnerListener):
- def __init__(self,
- package: str,
- activity: Optional[str],
- readahead: str,
- compiler_filter: Optional[str],
- timeout: Optional[int],
- simulate: bool,
- debug: bool,
- input:Optional[str],
- **kwargs):
- self.app_runner = AppRunner(package,
- activity,
- compiler_filter,
- timeout,
- simulate)
- self.app_runner.add_callbacks(self)
-
- self.simulate = simulate
- self.readahead = readahead
- self.debug = debug
- self.input = input
- print_utils.DEBUG = self.debug
- cmd_utils.SIMULATE = self.simulate
-
-
- def run(self) -> Optional[List[Tuple[str]]]:
- """Runs an app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- return self.app_runner.run()
-
- def preprocess(self):
- passed = self.validate_options()
- if not passed:
- return
-
- # Sets up adb environment.
- adb_utils.root()
- adb_utils.disable_selinux()
- time.sleep(1)
-
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- if self.readahead != 'warm':
- print_utils.debug_print('Drop caches for non-warm start.')
- # Drop all caches to get cold starts.
- adb_utils.vm_drop_cache()
-
- if self.readahead != 'warm' and self.readahead != 'cold':
- iorapd_utils.enable_iorapd_readahead()
-
- def postprocess(self, pre_launch_timestamp: str):
- passed = self._perform_post_launch_cleanup(pre_launch_timestamp)
- if not passed and not self.app_runner.simulate:
- print_utils.error_print('Cannot perform post launch cleanup!')
- return None
-
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- def _perform_post_launch_cleanup(self, logcat_timestamp: str) -> bool:
- """Performs cleanup at the end of each loop iteration.
-
- Returns:
- A bool indicates whether the cleanup succeeds or not.
- """
- if self.readahead != 'warm' and self.readahead != 'cold':
- passed = iorapd_utils.wait_for_iorapd_finish(self.app_runner.package,
- self.app_runner.activity,
- self.app_runner.timeout,
- self.debug,
- logcat_timestamp)
-
- if not passed:
- return passed
-
- return iorapd_utils.disable_iorapd_readahead()
-
- # Don't need to do anything for warm or cold.
- return True
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> str:
- """Parses the metric after app startup by reading from logcat in a blocking
- manner until all metrics have been found".
-
- Returns:
- the total time and displayed time of app startup.
- For example: "TotalTime=123\nDisplayedTime=121
- """
- total_time = AppRunner.parse_total_time(am_start_output)
- displayed_time = adb_utils.blocking_wait_for_logcat_displayed_time(
- pre_launch_timestamp, self.app_runner.package, self.app_runner.timeout)
-
- return 'TotalTime={}\nDisplayedTime={}'.format(total_time, displayed_time)
-
- def validate_options(self) -> bool:
- """Validates the activity and trace file if needed.
-
- Returns:
- A bool indicates whether the activity is valid.
- """
- needs_trace_file = self.readahead != 'cold' and self.readahead != 'warm'
- if needs_trace_file and (self.input is None or
- not os.path.exists(self.input)):
- print_utils.error_print('--input not specified!')
- return False
-
- # Install necessary trace file. This must be after the activity checking.
- if needs_trace_file:
- passed = iorapd_utils.iorapd_compiler_install_trace_file(
- self.app_runner.package, self.app_runner.activity, self.input)
- if not cmd_utils.SIMULATE and not passed:
- print_utils.error_print('Failed to install compiled TraceFile.pb for '
- '"{}/{}"'.
- format(self.app_runner.package,
- self.app_runner.activity))
- return False
-
- return True
-
-
-
-def parse_options(argv: List[str] = None):
- """Parses command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(
- description='Run an Android application once and measure startup time.'
- )
-
- required_named = parser.add_argument_group('required named arguments')
- required_named.add_argument('-p', '--package', action='store', dest='package',
- help='package of the application', required=True)
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the
- # optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-a', '--activity', action='store',
- dest='activity',
- help='launch activity of the application')
- optional_named.add_argument('-s', '--simulate', dest='simulate',
- action='store_true',
- help='simulate the process without executing '
- 'any shell commands')
- optional_named.add_argument('-d', '--debug', dest='debug',
- action='store_true',
- help='Add extra debugging output')
- optional_named.add_argument('-i', '--input', action='store', dest='input',
- help='perfetto trace file protobuf',
- default='TraceFile.pb')
- optional_named.add_argument('-r', '--readahead', action='store',
- dest='readahead',
- help='which readahead mode to use',
- default='cold',
- choices=('warm', 'cold', 'mlock', 'fadvise'))
- optional_named.add_argument('-t', '--timeout', dest='timeout', action='store',
- type=int,
- help='Timeout after this many seconds when '
- 'executing a single run.',
- default=10)
- optional_named.add_argument('--compiler-filter', dest='compiler_filter',
- action='store',
- help='Which compiler filter to use.',
- default=None)
-
- return parser.parse_args(argv)
-
-def main():
- opts = parse_options()
- runner = PrefetchAppRunner(**vars(opts))
- result = runner.run()
-
- if result is None:
- return 1
-
- print(result)
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/run_app_with_prefetch_test.py b/startop/scripts/app_startup/run_app_with_prefetch_test.py
deleted file mode 100644
index 8a588e4..0000000
--- a/startop/scripts/app_startup/run_app_with_prefetch_test.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-"""Unit tests for the run_app_with_prefetch_test.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./run_app_with_prefetch_test.py
- $> pytest run_app_with_prefetch_test.py
- $> python -m pytest run_app_with_prefetch_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-import io
-import os
-import shlex
-import sys
-import tempfile
-# global imports
-from contextlib import contextmanager
-
-# pip imports
-import pytest
-# local imports
-import run_app_with_prefetch as runner
-from mock import call, patch, Mock
-
-sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-from app_startup.lib.app_runner import AppRunner
-#
-# Argument Parsing Helpers
-#
-
-@contextmanager
-def ignore_stdout_stderr():
- """Ignore stdout/stderr output for duration of this context."""
- old_stdout = sys.stdout
- old_stderr = sys.stderr
- sys.stdout = io.StringIO()
- sys.stderr = io.StringIO()
- try:
- yield
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
-
-@contextmanager
-def argparse_bad_argument(msg):
- """Asserts that a SystemExit is raised when executing this context.
-
- If the assertion fails, print the message 'msg'.
- """
- with pytest.raises(SystemExit, message=msg):
- with ignore_stdout_stderr():
- yield
-
-def assert_bad_argument(args, msg):
- """Asserts that the command line arguments in 'args' are malformed.
-
- Prints 'msg' if the assertion fails.
- """
- with argparse_bad_argument(msg):
- parse_args(args)
-
-def parse_args(args):
- """
- :param args: command-line like arguments as a single string
- :return: dictionary of parsed key/values
- """
- # "-a b -c d" => ['-a', 'b', '-c', 'd']
- return vars(runner.parse_options(shlex.split(args)))
-
-def default_dict_for_parsed_args(**kwargs):
- """Combines it with all of the "optional" parameters' default values."""
- d = {
- 'readahead': 'cold',
- 'simulate': None,
- 'simulate': False,
- 'debug': False,
- 'input': 'TraceFile.pb',
- 'timeout': 10,
- 'compiler_filter': None,
- 'activity': None
- }
- d.update(kwargs)
- return d
-
-def default_mock_dict_for_parsed_args(include_optional=True, **kwargs):
- """Combines default dict with all optional parameters with some mock required
- parameters.
- """
- d = {'package': 'com.fake.package'}
- if include_optional:
- d.update(default_dict_for_parsed_args())
- d.update(kwargs)
- return d
-
-def parse_optional_args(str):
- """
- Parses an argument string which already includes all the required arguments
- in default_mock_dict_for_parsed_args.
- """
- req = '--package com.fake.package'
- return parse_args('%s %s' % (req, str))
-
-def test_argparse():
- # missing arguments
- assert_bad_argument('', '-p are required')
-
- # required arguments are parsed correctly
- ad = default_dict_for_parsed_args # assert dict
- assert parse_args('--package xyz') == ad(package='xyz')
-
- assert parse_args('-p xyz') == ad(package='xyz')
-
- assert parse_args('-p xyz -s') == ad(package='xyz', simulate=True)
- assert parse_args('-p xyz --simulate') == ad(package='xyz', simulate=True)
-
- # optional arguments are parsed correctly.
- mad = default_mock_dict_for_parsed_args # mock assert dict
- assert parse_optional_args('--input trace.pb') == mad(input='trace.pb')
-
- assert parse_optional_args('--compiler-filter speed') == \
- mad(compiler_filter='speed')
-
- assert parse_optional_args('-d') == mad(debug=True)
- assert parse_optional_args('--debug') == mad(debug=True)
-
- assert parse_optional_args('--timeout 123') == mad(timeout=123)
- assert parse_optional_args('-t 456') == mad(timeout=456)
-
- assert parse_optional_args('-r warm') == mad(readahead='warm')
- assert parse_optional_args('--readahead warm') == mad(readahead='warm')
-
- assert parse_optional_args('-a act') == mad(activity='act')
- assert parse_optional_args('--activity act') == mad(activity='act')
-
-def test_main():
- args = '--package com.fake.package --activity act -s'
- opts = runner.parse_options(shlex.split(args))
- result = runner.PrefetchAppRunner(**vars(opts)).run()
- assert result == [('TotalTime', '123')]
-
-def _mocked_run_shell_command(*args, **kwargs):
- if args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
- return (True, '9999')
- else:
- return (True, '')
-
-def test_preprocess_no_cache_drop():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='warm',
- compiler_filter=None,
- timeout=None,
- simulate=False,
- debug=False,
- input=None)
-
- prefetch_app_runner.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"')]
- mock_run_shell_command.assert_has_calls(calls)
-
-def test_preprocess_with_cache_drop():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='cold',
- compiler_filter=None,
- timeout=None,
- simulate=False,
- debug=False,
- input=None)
-
- prefetch_app_runner.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call('adb shell "echo 3 > /proc/sys/vm/drop_caches"')]
- mock_run_shell_command.assert_has_calls(calls)
-
-def test_preprocess_with_cache_drop_and_iorapd_enabled():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.side_effect = _mocked_run_shell_command
-
- with tempfile.NamedTemporaryFile() as input:
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='fadvise',
- compiler_filter=None,
- timeout=None,
- simulate=False,
- debug=False,
- input=input.name)
-
- prefetch_app_runner.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call(
- 'adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call('adb shell "echo 3 > /proc/sys/vm/drop_caches"'),
- call('bash -c "source {}; iorapd_readahead_enable"'.
- format(AppRunner.IORAP_COMMON_BASH_SCRIPT))]
- mock_run_shell_command.assert_has_calls(calls)
-
-@patch('lib.adb_utils.blocking_wait_for_logcat_displayed_time')
-@patch('lib.cmd_utils.run_shell_command')
-def test_postprocess_with_launch_cleanup(
- mock_run_shell_command,
- mock_blocking_wait_for_logcat_displayed_time):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_displayed_time.return_value = 123
-
- with tempfile.NamedTemporaryFile() as input:
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='fadvise',
- compiler_filter=None,
- timeout=10,
- simulate=False,
- debug=False,
- input=input.name)
-
- prefetch_app_runner.postprocess('2019-07-02 23:20:06.972674825')
-
- calls = [
- call('bash -c "source {script_path}; '
- 'iorapd_readahead_wait_until_finished '
- '\'{package}\' \'{activity}\' \'{timestamp}\' \'{timeout}\'"'.
- format(timeout=10,
- package='music',
- activity='MainActivity',
- timestamp='2019-07-02 23:20:06.972674825',
- script_path=AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('bash -c "source {}; iorapd_readahead_disable"'.
- format(AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"')]
- mock_run_shell_command.assert_has_calls(calls)
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/unlock_screen b/startop/scripts/app_startup/unlock_screen
deleted file mode 100755
index 478294c..0000000
--- a/startop/scripts/app_startup/unlock_screen
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018, 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.
-
-# This turns the screen on if it's off.
-# If it's on it does nothing unless its on the home screen, in which case it opens up some background
-# menu.
-#
-# However, this menu is ignored because "am start" commands still work as expected.
-adb shell input keyevent MENU
diff --git a/startop/scripts/iorap/analyze_prefetch_file.py b/startop/scripts/iorap/analyze_prefetch_file.py
deleted file mode 100755
index 343cd54..0000000
--- a/startop/scripts/iorap/analyze_prefetch_file.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2020, 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.
-
-import argparse
-import os
-import sys
-from typing import Dict, List, NamedTuple, Tuple
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR)) # framework/base/startop/script
-import lib.print_utils as print_utils
-
-# Include generated protos.
-dir_name = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(dir_name + "/generated")
-
-from TraceFile_pb2 import *
-
-def parse_options(argv: List[str] = None):
- """Parses command line arguments and returns an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Analyze compiled_trace iorap protos.")
- required_named = parser.add_argument_group('required named arguments')
-
- required_named.add_argument('-i', dest='input', metavar='FILE',
- help='Read protobuf file as input')
-
- optional_named = parser.add_argument_group('optional named arguments')
-
- optional_named.add_argument('-up', dest='upper_percent', type=float,
- default=95.0,
- help='Only show the top-most entries up to this value.')
-
- optional_named.add_argument('-r', dest='raw', action='store_true',
- help='Output entire raw file.')
- optional_named.add_argument('-o', dest='output',
- help='The results are stored into the output file')
- optional_named.add_argument('-d', dest='debug', action='store_true'
- , help='Activity of the app to be compiled')
-
- return parser.parse_args(argv)
-
-def open_iorap_prefetch_file(file_path: str) -> TraceFile:
- with open(file_path, "rb") as f:
- tf = TraceFile()
- tf.ParseFromString(f.read())
- return tf
-
-def print_stats_summary(trace_file: TraceFile, upper_percent):
- tf_dict = convert_to_dict(trace_file)
- print_utils.debug_print(tf_dict)
-
- total_length = 0
- summaries = []
- for name, entries_list in tf_dict.items():
- summary = entries_sum(entries_list)
- summaries.append(summary)
-
- total_length += summary.length
-
- # Sort by length
- summaries.sort(reverse=True, key=lambda s: s.length)
-
- percent_sum = 0.0
- skipped_entries = 0
-
- print("===========================================")
- print("Total length: {:,} bytes".format(total_length))
- print("Displayed upper percent: {:0.2f}%".format(upper_percent))
- print("===========================================")
- print("")
- print("name,length,percent_of_total,upper_percent")
- for sum in summaries:
- percent_of_total = (sum.length * 1.0) / (total_length * 1.0) * 100.0
-
- percent_sum += percent_of_total
-
- if percent_sum > upper_percent:
- skipped_entries = skipped_entries + 1
- continue
-
- #print("%s,%d,%.2f%%" %(sum.name, sum.length, percent_of_total))
- print("{:s},{:d},{:0.2f}%,{:0.2f}%".format(sum.name, sum.length, percent_of_total, percent_sum))
-
- if skipped_entries > 0:
- print("[WARNING] Skipped {:d} entries, use -up=100 to show everything".format(skipped_entries))
-
- pass
-
-class FileEntry(NamedTuple):
- id: int
- name: str
- offset: int
- length: int
-
-class FileEntrySummary(NamedTuple):
- name: str
- length: int
-
-def entries_sum(entries: List[FileEntry]) -> FileEntrySummary:
- if not entries:
- return None
-
- summary = FileEntrySummary(name=entries[0].name, length=0)
- for entry in entries:
- summary = FileEntrySummary(summary.name, summary.length + entry.length)
-
- return summary
-
-def convert_to_dict(trace_file: TraceFile) -> Dict[str, FileEntry]:
- trace_file_index = trace_file.index
-
- # entries.id -> entry.file_name
- entries_map = {}
-
- index_entries = trace_file_index.entries
- for entry in index_entries:
- entries_map[entry.id] = entry.file_name
-
- final_map = {}
-
- file_entries_map = {}
- file_entries = trace_file.list.entries
- for entry in file_entries:
- print_utils.debug_print(entry)
-
- lst = file_entries_map.get(entry.index_id, [])
- file_entries_map[entry.index_id] = lst
-
- file_name = entries_map[entry.index_id]
- file_entry = \
- FileEntry(id=entry.index_id, name=file_name, offset=entry.file_offset, length=entry.file_length)
-
- lst.append(file_entry)
-
- final_map[file_name] = lst
-
- return final_map
-
-def main(argv: List[str]) -> int:
- opts = parse_options(argv[1:])
- if opts.debug:
- print_utils.DEBUG = opts.debug
- print_utils.debug_print(opts)
-
- prefetch_file = open_iorap_prefetch_file(opts.input)
-
- if opts.raw:
- print(prefetch_file)
-
- print_stats_summary(prefetch_file, opts.upper_percent)
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/startop/scripts/iorap/collector b/startop/scripts/iorap/collector
deleted file mode 100755
index 3dc080a..0000000
--- a/startop/scripts/iorap/collector
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017, 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-APP_STARTUP_DIR="$DIR/../app_startup/"
-source "$DIR/common"
-
-usage() {
- cat <<EOF
-Usage: collector [OPTIONS]...
-
-Runs an application, causes an iorap trace to be collected for it, and then invokes the iorap
-compiler to generate a TraceFile.pb.
-
- -p, --package package of the app to test
- -a, --activity activity of the app to test
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -i, --inodes path to inodes file (system/extras/pagecache/pagecache.py -d inodes)
- -b, --trace_buffer_size how big to make trace buffer size (default 32768)
- -w, --wait_time how long to run systrace for (default 10) in seconds
- -c, --compiler-filter override the compilation filter if set (default none)
- -o, --output output trace file protobuf (default 'TraceFile.pb')
-EOF
-}
-
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-trace_buffer_size=32768
-wait_time=10
-comp_filter=""
-output_dest="TraceFile.pb"
-
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -a|--activity)
- activity="$2"
- shift
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -i|--inodes)
- inodes="$2"
- shift
- ;;
- -b|--trace_buffer_size)
- trace_buffer_size="$2"
- shift
- ;;
- -w|--wait_time)
- wait_time="$2"
- shift
- ;;
- -c|--compiler-filter)
- comp_filter="$2"
- shift
- ;;
- -o|--output)
- output_dest="$2"
- shift
- ;;
- -v|--verbose)
- verbose="y"
- ;;
- esac
- shift
- done
-}
-
-remote_pidof() {
- local procname="$1"
- adb shell ps | grep "$procname" | awk '{print $2;}'
-}
-
-remote_pkill() {
- local procname="$1"
- shift
-
- local the_pids=$(remote_pidof "$procname")
- local pid
-
- for pid in $the_pids; do
- verbose_print adb shell kill "$@" "$pid"
- adb shell kill "$@" "$pid"
- done
-}
-
-force_package_compilation() {
- local arg_comp_filter="$1"
- local arg_package="$2"
-
- if [[ $arg_comp_filter == speed-profile ]]; then
- # Force the running app to dump its profiles to disk.
- remote_pkill "$arg_package" -SIGUSR1
- sleep 1 # give some time for above to complete.
- fi
-
- adb shell cmd package compile -m "$arg_comp_filter" -f "$arg_package"
-}
-
-parse_package_dumpsys_line() {
- local what_left="$1"
- local what_right="$2"
- local line="$3"
-
- if [[ $line == *${what_left}*${what_right}* ]]; then
- found="${line#*$what_left}"
- found="${found%$what_right*}"
- echo "$found"
- return 0
- fi
-
- return 1
-}
-
-parse_package_dumpsys_section() {
- local what_left="$1"
- local what_right="$2"
- shift
- local lines="$@"
-
- lines="${lines//$'\n'/}"
-
- local new_lines=()
-
- local current_line=""
- local newline=n
- local line
- for line in "${lines[@]}"; do
- if [[ $line == *: ]]; then
- newline=y
- current_line=""
- new_lines+=("$current_line")
-
- parse_package_dumpsys_line "$what_left" "$what_right" "$current_line" && return 0
- else
- # strip all spaces from the start
- line="${line//$' '/}"
- current_line+="$line"
- #prepend to current line
- fi
- done
- [[ "$current_line" != "" ]] && new_lines+=("$current_line")
-
- parse_package_dumpsys_line "$what_left" "$what_right" "$current_line" && return 0
-
- return 1
-}
-
-parse_package_compilation() {
- local pkg="$1"
-# [com.google.android.apps.maps]
-
- local compilation_filter
- local is_prebuilt
- local isa
- local etc
-
- local ret_code
-
- read compilation_filter is_prebuilt isa etc <<< "$("$APP_STARTUP_DIR"/query_compiler_filter.py --package "$pkg")"
- ret_code=$?
-
- if [[ $ret_code -eq 0 && x$compilation_filter != x ]]; then
- verbose_print "Package compilation info for $pkg was '$compilation_filter'"
- echo "$compilation_filter"
- return 0
- else
- verbose_print "query failed ret code $ret_code filter=$compilation_filter"
- fi
-
- return $ret_code
-}
-
-# Main entry point
-if [[ $# -eq 0 ]]; then
- usage
- exit 1
-else
- parse_arguments "$@"
-
- # if we do not have have package exit early with an error
- [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 1
-
- if [[ -z "$inodes" ]] || ! [[ -f $inodes ]]; then
- echo "--inodes not specified" 1>&2
- exit 1
- fi
-
- if [[ "$activity" == "" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 1
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-fi
-
-adb root > /dev/null
-
-if [[ "$(adb shell getenforce)" != "Permissive" ]]; then
- adb shell setenforce 0
- adb shell stop
- adb shell start
- adb wait-for-device
-fi
-
-compilation_was="$(parse_package_compilation "$package")"
-if [[ $? -ne 0 ]]; then
- echo "Could not determine package compilation filter; was this package installed?" >&2
- exit 1
-fi
-verbose_print "Package compilation: $compilation_was"
-
-# Cannot downgrade (e.g. from speed-profile to quicken) without forceful recompilation.
-# Forceful recompilation will recompile even if compilation filter was unchanged.
-# Therefore avoid recompiling unless the filter is actually different than what we asked for.
-if [[ "x$comp_filter" != "x" ]] && [[ "$compilation_was" != "$comp_filter" ]]; then
- echo "Current compilation filter is '$compilation_was'; force recompile to '$comp_filter'" >&2
- #TODO: this matching seems hopelessly broken, it will always recompile.
-
- force_package_compilation "$comp_filter" "$package"
-fi
-
-# Drop all caches prior to beginning a systrace, otherwise we won't record anything already in pagecache.
-adb shell "echo 3 > /proc/sys/vm/drop_caches"
-
-trace_tmp_file="$(mktemp -t trace.XXXXXXXXX.html)"
-
-function finish {
- [[ -f "$trace_tmp_file" ]] && rm "$trace_tmp_file"
-}
-trap finish EXIT
-
-launch_application_and_wait_for_trace() {
- local package="$1"
- local activity="$2"
- local timeout=30 # seconds
-
- # Ensure application isn't running already.
- remote_pkill "$package"
-
- # 5 second trace of Home screen causes
- # a trace of the home screen.
- # There is no way to abort the trace
- # so just wait for it to complete instead.
- sleep 30
-
- local time_now="$(logcat_save_timestamp)"
- local retcode=0
-
- verbose_print "Drop caches for non-warm start."
- # Drop all caches to get cold starts.
- adb shell "echo 3 > /proc/sys/vm/drop_caches"
-
- verbose_print "now launching application"
- # Launch an application
- "$APP_STARTUP_DIR"/launch_application "$package" "$activity"
- retcode=$?
- if [[ $retcode -ne 0 ]]; then
- echo "FATAL: Application launch failed." >&2
- return $retcode
- fi
-
- # This blocks until 'am start' returns at which point the application is
- # already to be considered "started" as the first frame has been drawn.
-
- # TODO: check for cold start w.r.t to activitymanager?
-
- # Wait for application to start from the point of view of ActivityTaskManager.
- local pattern="ActivityTaskManager: Displayed $package"
- logcat_wait_for_pattern "$timeout" "$time_now" "$pattern"
- retcode=$?
- if [[ $retcode -ne 0 ]]; then
- echo "FATAL: Could not find '$pattern' in logcat." >&2
- return $retcode
- fi
-
- # Wait for iorapd to finish writing out the perfetto traces for this app.
- iorapd_perfetto_wait_for_app_trace "$package" "$activity" "$timeout" "$time_now"
- retcode=$?
- if [[ $retcode -ne 0 ]]; then
- echo "FATAL: Could not save perfetto app trace file." >&2
- return $retcode
- fi
-
- verbose_print "iorapd has finished collecting app trace file for $package/$activity"
-}
-
-collector_main() {
- # don't even bother trying to run anything until the screen is unlocked.
- "$APP_STARTUP_DIR"/unlock_screen
-
- # Don't mutate state while iorapd is running.
- iorapd_stop || return $?
-
- # Remove all existing metadata for a package/activity in iorapd.
- iorapd_perfetto_purge_app_trace "$package" "$activity" || return $?
- iorapd_compiler_purge_trace_file "$package" "$activity" || return $?
-
- iorapd_perfetto_enable || return $?
- iorapd_readahead_disable || return $?
- iorapd_start || return $?
-
- # Wait for perfetto trace to finished writing itself out.
- launch_application_and_wait_for_trace "$package" "$activity" || return $?
-
- # Pull the perfetto trace for manual inspection.
- iorapd_perfetto_pull_trace_file "$package" "$activity" "perfetto_trace.pb"
-
- # Compile the trace so that the next app run can use prefetching.
- iorapd_compiler_for_app_trace "$package" "$activity" "$inodes" || return $?
-
- # Save TraceFile.pb to local file.
- iorapd_compiler_pull_trace_file "$package" "$activity" "$output_dest" || return $?
- # Remove the TraceFile.pb from the device.
- iorapd_compiler_purge_trace_file "$package" "$activity" || return $?
-
- # TODO: better transactional support for restoring iorapd global properties
- iorapd_perfetto_disable || return $?
-}
-
-collector_main "$@"
-
-verbose_print "Collector finished. Children: "
-if [[ $verbose == y ]]; then
- jobs -p
- ps f -g$$
-fi
-
-exit $?
-
-
-verbose_print "About to begin systrace"
-coproc systrace_fd {
- # Disable stdout buffering since we need to know the output of systrace RIGHT AWAY.
- stdbuf -oL "$ANDROID_BUILD_TOP"/external/chromium-trace/systrace.py --target=android -b "$trace_buffer_size" -t "$wait_time" am pagecache dalvik -o "$trace_tmp_file"
-}
-
-verbose_print "Systrace began"
-
-systrace_pid="$!"
-
-while read -r -u "${systrace_fd[0]}" systrace_output; do
- verbose_print "$systrace_output"
- if [[ "$systrace_output" == *"Starting tracing"* ]]; then
- verbose_print "WE DID SEE STARTING TRACING."
- break
- fi
-done
-# Systrace has begun recording the tracing.
-# Run the application and collect the results.
-
-am_output="$(adb shell am start -S -W "$package"/"$activity")"
-if [[ $? -ne 0 ]]; then
- echo "am start failed" >&2
-
- exit 1
-fi
-
-verbose_print "$am_output"
-total_time="$(echo "$am_output" | grep 'TotalTime:' | sed 's/TotalTime: //g')"
-verbose_print "total time: $total_time"
-
-# Now wait for systrace to finish.
-
-wait "$systrace_pid" || { echo "Systrace finished before am start was finished, try a longer --wait_time"; exit 1; }
-verbose_print "Systrace has now finished"
-verbose_print "$(ls -la "$trace_tmp_file")"
-
-
-iorapd_perfetto_disable
-
-# Now that systrace has finished, convert the trace file html file to a protobuf.
-
-"$ANDROID_BUILD_TOP"/system/iorap/src/py/collector/trace_parser.py -i "$inodes" -t "$trace_tmp_file" -o "$output_dest" || exit 1
-
-echo "Trace file collection complete, trace file saved to \"$output_dest\"!" >&2
-
-finish
diff --git a/startop/scripts/iorap/common b/startop/scripts/iorap/common
deleted file mode 100755
index 387e45d..0000000
--- a/startop/scripts/iorap/common
+++ /dev/null
@@ -1,253 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, 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.
-
-DIR_IORAP_COMMON="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-APP_STARTUP_DIR="$DIR_IORAP_COMMON/../app_startup/"
-source "$APP_STARTUP_DIR/lib/common"
-
-IORAPD_DATA_PATH="/data/misc/iorapd"
-
-iorapd_start() {
- verbose_print 'iorapd_start'
- adb shell start iorapd
- sleep 1
- # TODO: block until logcat prints successfully connecting
-}
-
-iorapd_stop() {
- verbose_print 'iorapd_stop'
- adb shell stop iorapd
-}
-
-iorapd_reset() {
- iorapd_stop
- iorapd_start
-}
-
-# Enable perfetto tracing.
-# Subsequent launches of an application will record a perfetto trace protobuf.
-iorapd_perfetto_enable() {
- verbose_print 'enable perfetto'
- adb shell setprop iorapd.perfetto.enable true
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-# Disable perfetto tracing.
-# Subsequent launches of applications will no longer record perfetto trace protobufs.
-iorapd_perfetto_disable() {
- verbose_print 'disable perfetto'
- adb shell setprop iorapd.perfetto.enable false
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-# Enable readahead
-# Subsequent launches of an application will be sped up by iorapd readahead prefetching
-# (Provided an appropriate compiled trace exists for that application)
-iorapd_readahead_enable() {
- if [[ "$(adb shell getprop iorapd.readahead.enable)" == true ]]; then
- verbose_print 'enable readahead [already enabled]'
- return 0
- fi
- verbose_print 'enable readahead [reset iorapd]'
- adb shell setprop iorapd.readahead.enable true
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-# Disable readahead
-# Subsequent launches of an application will be not be sped up by iorapd readahead prefetching.
-iorapd_readahead_disable() {
- if [[ "$(adb shell getprop iorapd.readahead.enable)" == false ]]; then
- verbose_print 'disable readahead [already disabled]'
- return 0
- fi
- verbose_print 'disable readahead [reset iorapd]'
- adb shell setprop iorapd.readahead.enable false
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-_iorapd_path_to_data_file() {
- local package="$1"
- local activity="$2"
- local suffix="$3"
-
- # Match logic of 'AppComponentName' in iorap::compiler C++ code.
- echo "${IORAPD_DATA_PATH}/${package}%2F${activity}.${suffix}"
-}
-
-iorapd_perfetto_wait_for_app_trace() {
- local package="$1"
- local activity="$2"
- local timeout="$3"
- local timestamp="$4"
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
-
- verbose_print "iorapd_perfetto_wait_for_app_trace on file '$remote_path'"
-
- # see event_manager.cc
- local pattern="Perfetto TraceBuffer saved to file: $remote_path"
- logcat_wait_for_pattern "$timeout" "$timestamp" "$pattern"
-}
-
-# Purge all perfetto traces for a given application.
-iorapd_perfetto_purge_app_trace() {
- local package="$1"
- local activity="$2"
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
-
- verbose_print 'iorapd-perfetto: purge app trace in ' "$remote_path"
- adb shell "[[ -f '$remote_path' ]] && rm -f '$remote_path' || exit 0"
-}
-
-# Pull the remote perfetto trace file into a local file.
-iorapd_perfetto_pull_trace_file() {
- local package="$1"
- local activity="$2"
- local output_file="$3" # local path
-
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
-
- if ! adb shell "[[ -f '$compiled_path' ]]"; then
- echo "Error: Remote path '$compiled_path' invalid" >&2
- return 1
- fi
- if ! mkdir -p "$(dirname "$output_file")"; then
- echo "Error: Fail to make output directory for '$output_file'" >&2
- return 1
- fi
- verbose_print adb pull "$compiled_path" "$output_file"
- adb pull "$compiled_path" "$output_file"
-}
-
-# Compile a perfetto trace for a given application.
-# This requires the app has run at least once with perfetto tracing enabled.
-iorapd_compiler_for_app_trace() {
- local package="$1"
- local activity="$2"
- local inodes="$3" # local path
-
- # remote path calculations
- local input_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.tmp.pb")"
- local compiled_path_final="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- if ! adb shell "[[ -f '$input_path' ]]"; then
- echo "Error: Missing perfetto traces; nothing to compile. Expected: '$input_path'" >&2
- return 1
- fi
-
- if ! [[ -f $inodes ]]; then
- # We could compile using 'diskscan' but it's non-deterministic, so refuse instead.
- echo "Error: Missing inodes textcache at '$inodes'; refusing to compile." >&2
- return 1
- fi
-
- # inodes file needs to be on the device for iorap.cmd.compiler to access it
- local remote_inodes=/data/local/tmp/prefetch/inodes.txt
- adb shell "mkdir -p \"$(dirname "$remote_inodes")\"" || return 1
- verbose_print adb push "$inodes" "$remote_inodes"
- adb push "$inodes" "$remote_inodes"
-
- verbose_print 'iorapd-compiler: compile app trace in ' "$input_path"
- verbose_print adb shell "iorap.cmd.compiler '$input_path' --inode-textcache '$remote_inodes' --output-proto '$compiled_path'"
- adb shell "iorap.cmd.compiler '$input_path' --inode-textcache '$remote_inodes' --output-proto '$compiled_path'"
- retcode=$?
-
- # Don't overwrite the true 'compiled_trace.pb' unless the compiler completed without error.
- # TODO: The native compiler code should be handling its own transaction-safety.
- if [[ $retcode -eq 0 ]]; then
- adb shell "mv '$compiled_path' '$compiled_path_final'"
- else
- adb shell "[[ -f '$compiled_path' ]] && rm -f '$compiled_path'"
- fi
-
- # Clean up inodes file we just pushed.
-# adb shell "[[ -f '$remote_inodes' ]] && rm -f '$remote_inodes'"
-
- return $retcode
-}
-
-# Pull the remote compiled trace file into a local file.
-iorapd_compiler_pull_trace_file() {
- local package="$1"
- local activity="$2"
- local output_file="$3" # local path
-
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- if ! adb shell "[[ -f '$compiled_path' ]]"; then
- echo "Error: Remote path '$compiled_path' invalid" >&2
- return 1
- fi
- if ! mkdir -p "$(dirname "$output_file")"; then
- echo "Error: Fail to make output directory for '$output_file'" >&2
- return 1
- fi
- verbose_print adb pull "$compiled_path" "$output_file"
- adb pull "$compiled_path" "$output_file"
-}
-
-# Install a compiled trace file.
-iorapd_compiler_install_trace_file() {
- local package="$1"
- local activity="$2"
- local input_file="$3" # local path
-
- # remote path calculations
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- if ! [[ -f $input_file ]]; then
- echo "Error: File '$input_file' does not exist." >&2
- return 1
- fi
-
- adb shell "mkdir -p \"$(dirname "$compiled_path")\"" || return 1
-
- verbose_print adb push "$input_file" "$compiled_path"
- adb push "$input_file" "$compiled_path"
-}
-
-iorapd_compiler_purge_trace_file() {
- local package="$1"
- local activity="$2"
- local input_file="$3" # local path
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- adb shell "[[ -f '$remote_path' ]] && rm -f '$remote_path' || exit 0"
-}
-
-# Blocks until the readahead for the requested package/activity has finished.
-# This assumes that the trace file was already installed, and also that
-# the application launched but not completed yet.
-iorapd_readahead_wait_until_finished() {
- local package="$1"
- local activity="$2"
- local timestamp="$3"
- local timeout="$4"
-
- if [[ $# -lt 4 ]]; then
- echo "FATAL: Expected 4 arguments (actual $# $@)" >&2
- exit 1
- fi
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- # See 'read_ahead.cc' LOG(INFO).
- local pattern="Description = $remote_path"
- logcat_wait_for_pattern "$timeout" "$timestamp" "$pattern"
-}
diff --git a/startop/scripts/iorap/compile_handcrafted_file.py b/startop/scripts/iorap/compile_handcrafted_file.py
deleted file mode 100755
index 6dbbeaf..0000000
--- a/startop/scripts/iorap/compile_handcrafted_file.py
+++ /dev/null
@@ -1,297 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-import argparse
-import asyncio
-import csv
-import itertools
-import os
-import re
-import struct
-import sys
-import tempfile
-import time
-import zipfile
-from typing import Any, Callable, Dict, Generic, Iterable, List, NamedTuple, TextIO, Tuple, TypeVar, Optional, Union
-
-# Include generated protos.
-dir_name = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(dir_name + "/generated")
-
-from TraceFile_pb2 import *
-
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Compile a TraceFile.proto from a manual text file.")
- # argparse considers args starting with - and -- optional in --help, even though required=True.
- # by using a named argument group --help will clearly say that it's required instead of optional.
- required_named = parser.add_argument_group('required named arguments')
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-opb', '--output-proto-binary', dest='output_proto_binary', action='store', help='Write binary proto output to file.')
- optional_named.add_argument('-pm', '--pinlist-meta', dest='pinlist_meta', action='store', help='Path to pinlist.meta (default=none) binary file.')
- optional_named.add_argument('-pmp', '--pinlist-meta-parent', dest='pinlist_meta_parent', action='store', help='Device path that the pinlist.meta applies to (e.g. /data/.../somefile.apk)')
- optional_named.add_argument('-i', '--input', dest='input', action='store', help='Input text file (default stdin).')
- optional_named.add_argument('-zp', '--zip_path', dest='zip_path', action='append', help='Directory containing zip files.')
- optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
- optional_named.add_argument('-ot', '--output-text', dest='output_text', action='store', help='Output text file (default stdout).')
-
- return parser.parse_args(argv)
-
-# TODO: refactor this with a common library file with analyze_metrics.py
-def _debug_print(*args, **kwargs):
- """Print the args to sys.stderr if the --debug/-d flag was passed in."""
- if _debug:
- print(*args, **kwargs, file=sys.stderr)
-
-class BadInputError(Exception):
- pass
-
-InputRecord = NamedTuple('InputRecord', [('filepath', str), ('offset', int), ('length', int), ('remark', str)])
-
-def find_zip_in_paths(original_name, zip_paths):
- # /foo/bar/bax.zip -> bax.zip
- file_basename = os.path.split(original_name)[1]
-
- # the file must be located in one of the --zip-path arguments
- matched = None
- for zip_path in zip_paths:
- for dir_entry in os.listdir(zip_path):
- if dir_entry == file_basename:
- matched = os.path.join(zip_path, dir_entry)
- break
- if matched:
- break
-
- if not matched:
- raise ValueError("%s could not be found in any of the --zip_path specified." %(file_basename))
-
- _debug_print("found zip file ", file_basename, " in ", matched)
-
- if not zipfile.is_zipfile(matched):
- raise ValueError("%s is not a zip file" %(matched))
-
- return matched
-
-def handle_zip_entry(input_record, zip_paths):
-
- res = re.match("([^!]+)[!](.*)", input_record.filepath)
-
- if not res:
- return input_record
-
- # 'foo!bar'
- in_filepath = res[1] # -> 'foo'
- in_zip_entry = res[2] # -> 'bar'
-
- matched = find_zip_in_paths(in_filepath, zip_paths)
-
- zip = zipfile.ZipFile(matched)
-
- try:
- zip_info = zip.getinfo(in_zip_entry)
- except KeyError:
- raise ValueError("%s is not an item in the zip file %s" %(in_zip_entry, matched))
-
- # TODO: do we also need to add header size to this?
- in_offset = zip_info.header_offset
-
- # TODO: if a range is specified, use that instead.
- in_length = zip_info.compress_size
-
- return InputRecord(in_filepath, in_offset, in_length, 'zip entry (%s)' %(in_zip_entry))
-
-def parse_input_file(input: Iterable[str], zip_paths: List[str]) -> Iterable[InputRecord]:
- for line in input:
- line = line.strip()
-
- _debug_print("Line = ", line)
- if not line:
- _debug_print(" skip empty line", line)
- continue
- elif line[0] == "#":
- _debug_print(" skip commented line", line)
- continue
-
- res = re.match("([^\s]+)\s+(\d+)\s+(\d+)", line)
- if not res:
- raise BadInputError("Expected input of form: <str:filepath> <int:offset> <int:length>")
-
- in_filepath = res[1]
- in_offset = int(res[2])
- in_length = int(res[3])
-
- yield handle_zip_entry(InputRecord(in_filepath, in_offset, in_length, 'regular file'), zip_paths)
-
-# format:
-# (<big_endian(i32):file_offset> <big_endian(i32):range_length>)+
-PIN_META_FORMAT = ">ii"
-PIN_META_READ_SIZE = struct.calcsize(PIN_META_FORMAT)
-
-def parse_pin_meta(pin_meta_file, pinlist_meta_parent, zip_paths):
- if not pin_meta_file:
- return ()
-
- global PIN_META_FORMAT
- global PIN_META_READ_SIZE
-
- # '/data/app/com.google.android.GoogleCamera-aNQhzSznf4h_bvJ_MRbweQ==/base.apk'
- # -> 'com.google.android.GoogleCamera'
- package_name_match = re.match('/.*/(.*)-.*=/base.apk', pinlist_meta_parent)
-
- if not package_name_match:
- raise ValueError("%s did not contain the <packagename>.apk" %(pinlist_meta_parent))
-
- package_name = package_name_match[1]
- # "com.google.android.GoogleCamera" -> "GoogleCamera.apk"
- apk_name = package_name.split(".")[-1] + ".apk"
-
- path_to_zip_on_host = find_zip_in_paths(apk_name, zip_paths)
- apk_file_size = os.path.getsize(path_to_zip_on_host)
- _debug_print("APK path '%s' file size '%d'" %(path_to_zip_on_host, apk_file_size))
-
- while True:
- data = pin_meta_file.read(PIN_META_READ_SIZE)
-
- if not data:
- break
-
- (pin_offset, pin_length) = struct.unpack(PIN_META_FORMAT, data) # (offset, length)
-
- remark = 'regular file (pinlist.meta)'
-
- remaining_size = apk_file_size - pin_offset
- if remaining_size < 0:
- print("WARNING: Clamp entry (%d, %d), offset too large (max file size = %d)" %(pin_offset, pin_length, apk_file_size))
-
- pin_length = pin_length + remaining_size
- pin_offset = pin_offset + remaining_size
-
- if pin_offset < 0:
- pin_offset = 0
-
- remark += '[clamped.offset]'
-
- pin_last_offset = pin_offset + pin_length
- remaining_size = apk_file_size - pin_last_offset
-
- if remaining_size < 0:
- print("WARNING: Clamp entry (%d, %d), length too large (max file size = %d)" %(pin_offset, pin_length, apk_file_size))
- pin_length = pin_length + remaining_size
-
- remark += '[clamped.length]'
-
- yield InputRecord(pinlist_meta_parent, pin_offset, pin_length, remark)
-
-def write_text_file_output(input_records: Iterable[InputRecord], output_text_file):
- for rec in input_records:
- output_text_file.write("%s %d %d #%s\n" %(rec.filepath, rec.offset, rec.length, rec.remark))
-
-def build_trace_file(input_records: Iterable[InputRecord]) -> TraceFile:
- trace_file = TraceFile()
- trace_file_index = trace_file.index
-
- file_id_counter = 0
- file_id_map = {} # filename -> id
-
- stats_length_total = 0
- filename_stats = {} # filename -> total size
-
- for rec in input_records:
- filename = rec.filepath
-
- file_id = file_id_map.get(filename)
- if not file_id:
- file_id = file_id_counter
- file_id_map[filename] = file_id_counter
- file_id_counter = file_id_counter + 1
-
- file_index_entry = trace_file_index.entries.add()
- file_index_entry.id = file_id
- file_index_entry.file_name = filename
-
- # already in the file index, add the file entry.
- file_entry = trace_file.list.entries.add()
- file_entry.index_id = file_id
- file_entry.file_length = rec.length
- stats_length_total += file_entry.file_length
- file_entry.file_offset = rec.offset
-
- filename_stats[filename] = filename_stats.get(filename, 0) + file_entry.file_length
-
- return trace_file
-
-def main():
- global _debug
-
- options= parse_options()
- _debug = options.debug
- _debug_print("parsed options: ", options)
-
- if not options.input:
- input_file = sys.stdin
- _debug_print("input = stdin")
- else:
- input_file = open(options.input)
- _debug_print("input = (file)", options.input)
-
- if not options.output_proto_binary:
- output_proto_file = None
- else:
- output_proto_file = open(options.output_proto_binary, 'wb')
- _debug_print("output_proto_binary = ", output_proto_file)
-
- pinlist_meta_parent = options.pinlist_meta_parent
- if options.pinlist_meta:
- pin_meta_file = open(options.pinlist_meta, 'rb')
- else:
- pin_meta_file = None
-
- if (pinlist_meta_parent == None) != (pin_meta_file == None):
- print("Options must be used together: --pinlist-meta and --pinlist-meta-path")
- return 1
-
- if not options.output_text:
- output_text_file = sys.stdout
- _debug_print("output = stdout")
- else:
- output_text_file = open(options.output_text, 'w')
- _debug_print("output = (file)", options.output_text)
-
- zip_paths = options.zip_path or []
-
- input_records = list(parse_pin_meta(pin_meta_file, pinlist_meta_parent, zip_paths))
- input_records = input_records + list(parse_input_file(input_file, zip_paths))
-
- for p in input_records:
- _debug_print(p)
-
- write_text_file_output(input_records, output_text_file)
- output_text_file.close()
-
- out_proto = build_trace_file(input_records)
-
- if output_proto_file:
- output_proto_file.write(out_proto.SerializeToString())
- output_proto_file.close()
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py
deleted file mode 100644
index 1426d34..0000000
--- a/startop/scripts/iorap/compiler.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-import importlib
-import os
-import sys
-import tempfile
-from enum import Enum
-from typing import TextIO, List
-
-# local import
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-import lib.print_utils as print_utils
-
-# Type of compiler.
-class CompilerType(Enum):
- HOST = 1 # iorap.cmd.compiler on host
- DEVICE = 2 # adb shell iorap.cmd.compiler
- RI = 3 # compiler.py
-
-def compile_perfetto_trace_ri(
- argv: List[str],
- compiler) -> TextIO:
- print_utils.debug_print('Compile using RI compiler.')
- compiler_trace_file = tempfile.NamedTemporaryFile()
- argv.extend(['-o', compiler_trace_file.name])
- print_utils.debug_print(argv)
- compiler.main([''] + argv)
- return compiler_trace_file
-
-def compile_perfetto_trace_device(inodes_path: str,
- package: str,
- activity: str,
- compiler) -> TextIO:
- print_utils.debug_print('Compile using on-device compiler.')
- compiler_trace_file = tempfile.NamedTemporaryFile()
- compiler.main(inodes_path, package, activity, compiler_trace_file.name)
- return compiler_trace_file
-
-def compile(compiler_type: CompilerType,
- inodes_path: str,
- ri_compiler_argv,
- package: str,
- activity: str) -> TextIO:
- if compiler_type == CompilerType.RI:
- compiler = importlib.import_module('iorap.compiler_ri')
- compiler_trace_file = compile_perfetto_trace_ri(ri_compiler_argv,
- compiler)
- return compiler_trace_file
- if compiler_type == CompilerType.DEVICE:
- compiler = importlib.import_module('iorap.compiler_device')
- compiler_trace_file = compile_perfetto_trace_device(inodes_path,
- package,
- activity,
- compiler)
- return compiler_trace_file
-
- # Should not arrive here.
- raise ValueError('Unknown compiler type')
diff --git a/startop/scripts/iorap/compiler_device.py b/startop/scripts/iorap/compiler_device.py
deleted file mode 100644
index d941cd9..0000000
--- a/startop/scripts/iorap/compiler_device.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-import argparse
-import os
-import sys
-from typing import List
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR)) # framework/base/startop/script
-import lib.print_utils as print_utils
-import iorap.lib.iorapd_utils as iorapd_utils
-from app_startup.lib.app_runner import AppRunner
-
-IORAP_COMMON_BASH_SCRIPT = os.path.join(DIR, 'common')
-
-def parse_options(argv: List[str] = None):
- """Parses command line arguments and returns an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Compile perfetto trace file")
- required_named = parser.add_argument_group('required named arguments')
-
- required_named.add_argument('-i', dest='inodes', metavar='FILE',
- help='Read cached inode data from a file saved '
- 'earlier with pagecache.py -d')
- required_named.add_argument('-p', dest='package',
- help='Package of the app to be compiled')
-
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-o', dest='output',
- help='The compiled trace is stored into the output file')
- optional_named.add_argument('-a', dest='activity',
- help='Activity of the app to be compiled')
- optional_named.add_argument('-d', dest='debug', action='store_true'
- , help='Activity of the app to be compiled')
-
- return parser.parse_args(argv)
-
-def main(inodes, package, activity, output, **kwargs) -> int:
- """Entries of the program."""
- if not activity:
- activity = AppRunner.get_activity(package)
-
- passed = iorapd_utils.compile_perfetto_trace_on_device(package, activity,
- inodes)
- if passed and output:
- iorapd_utils.get_iorapd_compiler_trace(package, activity, output)
-
- return 0
-
-if __name__ == '__main__':
- opts = parse_options()
- if opts.debug:
- print_utils.DEBUG = opts.debug
- print_utils.debug_print(opts)
- sys.exit(main(**(vars(opts))))
diff --git a/startop/scripts/iorap/compiler_ri.py b/startop/scripts/iorap/compiler_ri.py
deleted file mode 100755
index 90fc8a8..0000000
--- a/startop/scripts/iorap/compiler_ri.py
+++ /dev/null
@@ -1,325 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# Copyright (C) 2019 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.
-#
-
-#
-# Dependencies:
-#
-# $> sudo apt-get install python3-pip
-# $> pip3 install --user protobuf sqlalchemy sqlite3
-#
-
-import optparse
-import os
-import re
-import sys
-import tempfile
-from pathlib import Path
-from datetime import timedelta
-from typing import Iterable, Optional, List
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-from iorap.generated.TraceFile_pb2 import *
-from iorap.lib.inode2filename import Inode2Filename
-
-parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-sys.path.append(parent_dir_name)
-from trace_analyzer.lib.trace2db import Trace2Db, MmFilemapAddToPageCache, \
- RawFtraceEntry
-import lib.cmd_utils as cmd_utils
-
-_PAGE_SIZE = 4096 # adb shell getconf PAGESIZE ## size of a memory page in bytes.
-ANDROID_BUILD_TOP = Path(parent_dir_name).parents[3]
-TRACECONV_BIN = ANDROID_BUILD_TOP.joinpath(
- 'external/perfetto/tools/traceconv')
-
-class PageRun:
- """
- Intermediate representation for a run of one or more pages.
- """
- def __init__(self, device_number: int, inode: int, offset: int, length: int):
- self.device_number = device_number
- self.inode = inode
- self.offset = offset
- self.length = length
-
- def __str__(self):
- return "PageRun(device_number=%d, inode=%d, offset=%d, length=%d)" \
- %(self.device_number, self.inode, self.offset, self.length)
-
-def debug_print(msg):
- #print(msg)
- pass
-
-UNDER_LAUNCH = False
-
-def page_cache_entries_to_runs(page_cache_entries: Iterable[MmFilemapAddToPageCache]):
- global _PAGE_SIZE
-
- runs = [
- PageRun(device_number=pg_entry.dev, inode=pg_entry.ino, offset=pg_entry.ofs,
- length=_PAGE_SIZE)
- for pg_entry in page_cache_entries
- ]
-
- for r in runs:
- debug_print(r)
-
- print("Stats: Page runs totaling byte length: %d" %(len(runs) * _PAGE_SIZE))
-
- return runs
-
-def optimize_page_runs(page_runs):
- new_entries = []
- last_entry = None
- for pg_entry in page_runs:
- if last_entry:
- if pg_entry.device_number == last_entry.device_number and pg_entry.inode == last_entry.inode:
- # we are dealing with a run for the same exact file as a previous run.
- if pg_entry.offset == last_entry.offset + last_entry.length:
- # trivially contiguous entries. merge them together.
- last_entry.length += pg_entry.length
- continue
- # Default: Add the run without merging it to a previous run.
- last_entry = pg_entry
- new_entries.append(pg_entry)
- return new_entries
-
-def is_filename_matching_filter(file_name, filters=[]):
- """
- Blacklist-style regular expression filters.
-
- :return: True iff file_name has an RE match in one of the filters.
- """
- for filt in filters:
- res = re.search(filt, file_name)
- if res:
- return True
-
- return False
-
-def build_protobuf(page_runs, inode2filename, filters=[]):
- trace_file = TraceFile()
- trace_file_index = trace_file.index
-
- file_id_counter = 0
- file_id_map = {} # filename -> id
-
- stats_length_total = 0
- filename_stats = {} # filename -> total size
-
- skipped_inode_map = {}
- filtered_entry_map = {} # filename -> count
-
- for pg_entry in page_runs:
- fn = inode2filename.resolve(pg_entry.device_number, pg_entry.inode)
- if not fn:
- skipped_inode_map[pg_entry.inode] = skipped_inode_map.get(pg_entry.inode, 0) + 1
- continue
-
- filename = fn
-
- if filters and not is_filename_matching_filter(filename, filters):
- filtered_entry_map[filename] = filtered_entry_map.get(filename, 0) + 1
- continue
-
- file_id = file_id_map.get(filename)
- # file_id could 0, which satisfies "if file_id" and causes duplicate
- # filename for file id 0.
- if file_id is None:
- file_id = file_id_counter
- file_id_map[filename] = file_id_counter
- file_id_counter = file_id_counter + 1
-
- file_index_entry = trace_file_index.entries.add()
- file_index_entry.id = file_id
- file_index_entry.file_name = filename
-
- # already in the file index, add the file entry.
- file_entry = trace_file.list.entries.add()
- file_entry.index_id = file_id
- file_entry.file_length = pg_entry.length
- stats_length_total += file_entry.file_length
- file_entry.file_offset = pg_entry.offset
-
- filename_stats[filename] = filename_stats.get(filename, 0) + file_entry.file_length
-
- for inode, count in skipped_inode_map.items():
- print("WARNING: Skip inode %s because it's not in inode map (%d entries)" %(inode, count))
-
- print("Stats: Sum of lengths %d" %(stats_length_total))
-
- if filters:
- print("Filter: %d total files removed." %(len(filtered_entry_map)))
-
- for fn, count in filtered_entry_map.items():
- print("Filter: File '%s' removed '%d' entries." %(fn, count))
-
- for filename, file_size in filename_stats.items():
- print("%s,%s" %(filename, file_size))
-
- return trace_file
-
-def calc_trace_end_time(trace2db: Trace2Db,
- trace_duration: Optional[timedelta]) -> float:
- """
- Calculates the end time based on the trace duration.
- The start time is the first receiving mm file map event.
- The end time is the start time plus the trace duration.
- All of them are in milliseconds.
- """
- # If the duration is not set, assume all time is acceptable.
- if trace_duration is None:
- # float('inf')
- return RawFtraceEntry.__table__.c.timestamp.type.python_type('inf')
-
- first_event = trace2db.session.query(MmFilemapAddToPageCache).join(
- MmFilemapAddToPageCache.raw_ftrace_entry).order_by(
- RawFtraceEntry.timestamp).first()
-
- # total_seconds() will return a float number.
- return first_event.raw_ftrace_entry.timestamp + trace_duration.total_seconds()
-
-def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[timedelta]):
- end_time = calc_trace_end_time(trace2db, trace_duration)
- # SELECT * FROM tbl ORDER BY id;
- return trace2db.session.query(MmFilemapAddToPageCache).join(
- MmFilemapAddToPageCache.raw_ftrace_entry).filter(
- RawFtraceEntry.timestamp <= end_time).order_by(
- MmFilemapAddToPageCache.id).all()
-
-def transform_perfetto_trace_to_systrace(path_to_perfetto_trace: str,
- path_to_tmp_systrace: str) -> None:
- """ Transforms the systrace file from perfetto trace. """
- cmd_utils.run_command_nofail([str(TRACECONV_BIN),
- 'systrace',
- path_to_perfetto_trace,
- path_to_tmp_systrace])
-
-
-def run(sql_db_path:str,
- trace_file:str,
- trace_duration:Optional[timedelta],
- output_file:str,
- inode_table:str,
- filter:List[str]) -> int:
- trace2db = Trace2Db(sql_db_path)
- # Speed optimization: Skip any entries that aren't mm_filemap_add_to_pagecache.
- trace2db.set_raw_ftrace_entry_filter(\
- lambda entry: entry['function'] == 'mm_filemap_add_to_page_cache')
- # TODO: parse multiple trace files here.
- parse_count = trace2db.parse_file_into_db(trace_file)
-
- mm_filemap_add_to_page_cache_rows = query_add_to_page_cache(trace2db,
- trace_duration)
- print("DONE. Parsed %d entries into sql db." %(len(mm_filemap_add_to_page_cache_rows)))
-
- page_runs = page_cache_entries_to_runs(mm_filemap_add_to_page_cache_rows)
- print("DONE. Converted %d entries" %(len(page_runs)))
-
- # TODO: flags to select optimizations.
- optimized_page_runs = optimize_page_runs(page_runs)
- print("DONE. Optimized down to %d entries" %(len(optimized_page_runs)))
-
- print("Build protobuf...")
- trace_file = build_protobuf(optimized_page_runs, inode_table, filter)
-
- print("Write protobuf to file...")
- output_file = open(output_file, 'wb')
- output_file.write(trace_file.SerializeToString())
- output_file.close()
-
- print("DONE")
-
- # TODO: Silent running mode [no output except on error] for build runs.
-
- return 0
-
-def main(argv):
- parser = optparse.OptionParser(usage="Usage: %prog [options]", description="Compile systrace file into TraceFile.pb")
- parser.add_option('-i', dest='inode_data_file', metavar='FILE',
- help='Read cached inode data from a file saved earlier with pagecache.py -d')
- parser.add_option('-t', dest='trace_file', metavar='FILE',
- help='Path to systrace file (trace.html) that will be parsed')
- parser.add_option('--perfetto-trace', dest='perfetto_trace_file',
- metavar='FILE',
- help='Path to perfetto trace that will be parsed')
-
- parser.add_option('--db', dest='sql_db', metavar='FILE',
- help='Path to intermediate sqlite3 database [default: in-memory].')
-
- parser.add_option('-f', dest='filter', action="append", default=[],
- help="Add file filter. All file entries not matching one of the filters are discarded.")
-
- parser.add_option('-l', dest='launch_lock', action="store_true", default=False,
- help="Exclude all events not inside launch_lock")
-
- parser.add_option('-o', dest='output_file', metavar='FILE',
- help='Output protobuf file')
-
- parser.add_option('--duration', dest='trace_duration', action="store",
- type=int, help='The duration of trace in milliseconds.')
-
- options, categories = parser.parse_args(argv[1:])
-
- # TODO: OptionParser should have some flags to make these mandatory.
- if not options.inode_data_file:
- parser.error("-i is required")
- if not options.trace_file and not options.perfetto_trace_file:
- parser.error("one of -t or --perfetto-trace is required")
- if options.trace_file and options.perfetto_trace_file:
- parser.error("please enter either -t or --perfetto-trace, not both")
- if not options.output_file:
- parser.error("-o is required")
-
- if options.launch_lock:
- print("INFO: Launch lock flag (-l) enabled; filtering all events not inside launch_lock.")
-
- inode_table = Inode2Filename.new_from_filename(options.inode_data_file)
-
- sql_db_path = ":memory:"
- if options.sql_db:
- sql_db_path = options.sql_db
-
- trace_duration = timedelta(milliseconds=options.trace_duration) if \
- options.trace_duration is not None else None
-
- # if the input is systrace
- if options.trace_file:
- return run(sql_db_path,
- options.trace_file,
- trace_duration,
- options.output_file,
- inode_table,
- options.filter)
-
- # if the input is perfetto trace
- # TODO python 3.7 switch to using nullcontext
- with tempfile.NamedTemporaryFile() as trace_file:
- transform_perfetto_trace_to_systrace(options.perfetto_trace_file,
- trace_file.name)
- return run(sql_db_path,
- trace_file.name,
- trace_duration,
- options.output_file,
- inode_table,
- options.filter)
-
-if __name__ == '__main__':
- print(sys.argv)
- sys.exit(main(sys.argv))
diff --git a/startop/scripts/iorap/compiler_test.py b/startop/scripts/iorap/compiler_test.py
deleted file mode 100644
index b8de701..0000000
--- a/startop/scripts/iorap/compiler_test.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-
-"""
-Unit tests for the compiler.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> pytest compiler_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-import os
-
-import compiler_ri as compiler
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-TEXTCACHE = os.path.join(DIR, 'test_fixtures/compiler/common_textcache')
-SYSTRACE = os.path.join(DIR, 'test_fixtures/compiler/common_systrace')
-ARGV = [os.path.join(DIR, 'compiler.py'), '-i', TEXTCACHE, '-t', SYSTRACE]
-PERFETTO_TRACE = os.path.join(DIR,
- 'test_fixtures/compiler/common_perfetto_trace.pb')
-
-def assert_compile_result(output, expected, *extra_argv):
- argv = ARGV + ['-o', output] + [args for args in extra_argv]
-
- compiler.main(argv)
-
- with open(output, 'rb') as f1, open(expected, 'rb') as f2:
- assert f1.read() == f2.read()
-
-### Unit tests - testing compiler code directly
-def test_transform_perfetto_trace_to_systrace(tmpdir):
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_systrace')
- output = tmpdir.mkdir('compiler').join('tmp_systrace')
-
- compiler.transform_perfetto_trace_to_systrace(PERFETTO_TRACE, str(output))
-
- with open(output, 'rb') as f1, open(expected, 'rb') as f2:
- assert f1.read() == f2.read()
-
-### Functional tests - calls 'compiler.py --args...'
-def test_compiler_main(tmpdir):
- output = tmpdir.mkdir('compiler').join('output')
-
- # No duration
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_without_duration.TraceFile.pb')
- assert_compile_result(output, expected)
-
- # 10ms duration
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_with_duration.TraceFile.pb')
- assert_compile_result(output, expected, '--duration', '10000')
-
- # 30ms duration
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_without_duration.TraceFile.pb')
- assert_compile_result(output, expected, '--duration', '30000')
diff --git a/startop/scripts/iorap/dump_compiled_pb b/startop/scripts/iorap/dump_compiled_pb
deleted file mode 100755
index ad26a7d..0000000
--- a/startop/scripts/iorap/dump_compiled_pb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-#
-# Dumps an iorap compiler protobuf from iorap.cmd.compiler into text
-# with gqui.
-#
-
-if [[ "$#" -lt 1 ]]; then
- echo "Usage: $0 <compiler_trace_file.pb> [...args]" >&2
- exit 1
-fi
-
-path_to_proto="$DIR/../../../../../system/iorap/src/serialize/TraceFile.proto"
-
-filename="$1"
-shift
-if ! [[ -f $filename ]]; then
- echo "Error: $filename does not exist." >&2
- exit 1
-fi
-
-gqui "rawproto:$filename" proto "$path_to_proto":iorap.serialize.proto.TraceFile "$@"
diff --git a/startop/scripts/iorap/dump_trace_pb b/startop/scripts/iorap/dump_trace_pb
deleted file mode 100755
index bcec4a5..0000000
--- a/startop/scripts/iorap/dump_trace_pb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-#
-# Dumps a perfetto protobuf collected by iorapd (from perfetto) into text
-# with gqui.
-#
-
-if [[ "$#" -lt 1 ]]; then
- echo "Usage: $0 <perfetto_trace.pb> [...args]" >&2
- exit 1
-fi
-
-path_to_perfetto_proto="$DIR/../../../../../external/perfetto/protos/perfetto/trace/perfetto_trace.proto"
-
-filename="$1"
-shift
-if ! [[ -f $filename ]]; then
- echo "Error: $filename does not exist." >&2
- exit 1
-fi
-
-gqui "rawproto:$filename" proto "$path_to_perfetto_proto":perfetto.protos.Trace "$@"
diff --git a/startop/scripts/iorap/generated/TraceFile_pb2.py b/startop/scripts/iorap/generated/TraceFile_pb2.py
deleted file mode 100644
index f005bed..0000000
--- a/startop/scripts/iorap/generated/TraceFile_pb2.py
+++ /dev/null
@@ -1,259 +0,0 @@
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: TraceFile.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='TraceFile.proto',
- package='iorap.serialize.proto',
- syntax='proto2',
- serialized_pb=_b('\n\x0fTraceFile.proto\x12\x15iorap.serialize.proto\"u\n\tTraceFile\x12\x34\n\x05index\x18\x01 \x02(\x0b\x32%.iorap.serialize.proto.TraceFileIndex\x12\x32\n\x04list\x18\x02 \x02(\x0b\x32$.iorap.serialize.proto.TraceFileList\"M\n\x0eTraceFileIndex\x12;\n\x07\x65ntries\x18\x01 \x03(\x0b\x32*.iorap.serialize.proto.TraceFileIndexEntry\"4\n\x13TraceFileIndexEntry\x12\n\n\x02id\x18\x01 \x02(\x03\x12\x11\n\tfile_name\x18\x02 \x02(\t\"G\n\rTraceFileList\x12\x36\n\x07\x65ntries\x18\x01 \x03(\x0b\x32%.iorap.serialize.proto.TraceFileEntry\"L\n\x0eTraceFileEntry\x12\x10\n\x08index_id\x18\x01 \x02(\x03\x12\x13\n\x0b\x66ile_offset\x18\x02 \x02(\x03\x12\x13\n\x0b\x66ile_length\x18\x03 \x02(\x03\x42\x1c\n\x18\x63om.google.android.iorapH\x03')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-
-
-_TRACEFILE = _descriptor.Descriptor(
- name='TraceFile',
- full_name='iorap.serialize.proto.TraceFile',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='index', full_name='iorap.serialize.proto.TraceFile.index', index=0,
- number=1, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='list', full_name='iorap.serialize.proto.TraceFile.list', index=1,
- number=2, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=42,
- serialized_end=159,
-)
-
-
-_TRACEFILEINDEX = _descriptor.Descriptor(
- name='TraceFileIndex',
- full_name='iorap.serialize.proto.TraceFileIndex',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='entries', full_name='iorap.serialize.proto.TraceFileIndex.entries', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=161,
- serialized_end=238,
-)
-
-
-_TRACEFILEINDEXENTRY = _descriptor.Descriptor(
- name='TraceFileIndexEntry',
- full_name='iorap.serialize.proto.TraceFileIndexEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='id', full_name='iorap.serialize.proto.TraceFileIndexEntry.id', index=0,
- number=1, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='file_name', full_name='iorap.serialize.proto.TraceFileIndexEntry.file_name', index=1,
- number=2, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=240,
- serialized_end=292,
-)
-
-
-_TRACEFILELIST = _descriptor.Descriptor(
- name='TraceFileList',
- full_name='iorap.serialize.proto.TraceFileList',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='entries', full_name='iorap.serialize.proto.TraceFileList.entries', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=294,
- serialized_end=365,
-)
-
-
-_TRACEFILEENTRY = _descriptor.Descriptor(
- name='TraceFileEntry',
- full_name='iorap.serialize.proto.TraceFileEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='index_id', full_name='iorap.serialize.proto.TraceFileEntry.index_id', index=0,
- number=1, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='file_offset', full_name='iorap.serialize.proto.TraceFileEntry.file_offset', index=1,
- number=2, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='file_length', full_name='iorap.serialize.proto.TraceFileEntry.file_length', index=2,
- number=3, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=367,
- serialized_end=443,
-)
-
-_TRACEFILE.fields_by_name['index'].message_type = _TRACEFILEINDEX
-_TRACEFILE.fields_by_name['list'].message_type = _TRACEFILELIST
-_TRACEFILEINDEX.fields_by_name['entries'].message_type = _TRACEFILEINDEXENTRY
-_TRACEFILELIST.fields_by_name['entries'].message_type = _TRACEFILEENTRY
-DESCRIPTOR.message_types_by_name['TraceFile'] = _TRACEFILE
-DESCRIPTOR.message_types_by_name['TraceFileIndex'] = _TRACEFILEINDEX
-DESCRIPTOR.message_types_by_name['TraceFileIndexEntry'] = _TRACEFILEINDEXENTRY
-DESCRIPTOR.message_types_by_name['TraceFileList'] = _TRACEFILELIST
-DESCRIPTOR.message_types_by_name['TraceFileEntry'] = _TRACEFILEENTRY
-
-TraceFile = _reflection.GeneratedProtocolMessageType('TraceFile', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILE,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFile)
- ))
-_sym_db.RegisterMessage(TraceFile)
-
-TraceFileIndex = _reflection.GeneratedProtocolMessageType('TraceFileIndex', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILEINDEX,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileIndex)
- ))
-_sym_db.RegisterMessage(TraceFileIndex)
-
-TraceFileIndexEntry = _reflection.GeneratedProtocolMessageType('TraceFileIndexEntry', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILEINDEXENTRY,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileIndexEntry)
- ))
-_sym_db.RegisterMessage(TraceFileIndexEntry)
-
-TraceFileList = _reflection.GeneratedProtocolMessageType('TraceFileList', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILELIST,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileList)
- ))
-_sym_db.RegisterMessage(TraceFileList)
-
-TraceFileEntry = _reflection.GeneratedProtocolMessageType('TraceFileEntry', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILEENTRY,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileEntry)
- ))
-_sym_db.RegisterMessage(TraceFileEntry)
-
-
-DESCRIPTOR.has_options = True
-DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\030com.google.android.iorapH\003'))
-# @@protoc_insertion_point(module_scope)
diff --git a/startop/scripts/iorap/generated/codegen_protos b/startop/scripts/iorap/generated/codegen_protos
deleted file mode 100755
index 5688711..0000000
--- a/startop/scripts/iorap/generated/codegen_protos
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-APROTOC="$(which aprotoc)"
-
-IORAP_SERIALIZE_DIR="${DIR}/../../../../../../system/iorap/src/serialize"
-IORAP_PROTOS=($IORAP_SERIALIZE_DIR/*.proto)
-
-if [[ $? -ne 0 ]]; then
- echo "Fatal: Missing aprotoc. Set APROTOC=... or lunch build/envsetup.sh?" >&2
- exit 1
-fi
-
-if ! [[ -d $IORAP_SERIALIZE_DIR ]]; then
- echo "Fatal: Directory '$IORAP_SERIALIZE_DIR' does not exist." >&2
- exit 1
-fi
-
-# codegen the .py files into the same directory as this script.
-echo "$APROTOC" --proto_path="$IORAP_SERIALIZE_DIR" --python_out="$DIR" "${IORAP_PROTOS[@]}"
-"$APROTOC" --proto_path="$IORAP_SERIALIZE_DIR" --python_out="$DIR" "${IORAP_PROTOS[@]}"
diff --git a/startop/scripts/iorap/lib/inode2filename.py b/startop/scripts/iorap/lib/inode2filename.py
deleted file mode 100644
index 2e71393..0000000
--- a/startop/scripts/iorap/lib/inode2filename.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# Copyright (C) 2019 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.
-#
-
-from typing import Any, Callable, Dict, Generic, Iterable, List, NamedTuple, TextIO, Tuple, TypeVar, Optional, Union, TextIO
-
-import re
-
-class Inode2Filename:
- """
- Parses a text file of the format
- "uint(dev_t) uint(ino_t) int(file_size) string(filepath)\\n"*
-
- Lines not matching this format are ignored.
- """
-
- def __init__(self, inode_data_file: TextIO):
- """
- Create an Inode2Filename that reads cached inode from a file saved earlier
- (e.g. with pagecache.py -d or with inode2filename --format=textcache)
-
- :param inode_data_file: a file object (e.g. created with open or StringIO).
-
- Lifetime: inode_data_file is only used during the construction of the object.
- """
- self._inode_table = Inode2Filename.build_inode_lookup_table(inode_data_file)
-
- @classmethod
- def new_from_filename(cls, textcache_filename: str) -> 'Inode2Filename':
- """
- Create an Inode2Filename that reads cached inode from a file saved earlier
- (e.g. with pagecache.py -d or with inode2filename --format=textcache)
-
- :param textcache_filename: path to textcache
- """
- with open(textcache_filename) as inode_data_file:
- return cls(inode_data_file)
-
- @staticmethod
- def build_inode_lookup_table(inode_data_file: TextIO) -> Dict[Tuple[int, int], Tuple[str, str]]:
- """
- :return: map { (device_int, inode_int) -> (filename_str, size_str) }
- """
- inode2filename = {}
- for line in inode_data_file:
- # stat -c "%d %i %s %n
- # device number, inode number, total size in bytes, file name
- result = re.match('([0-9]+)d? ([0-9]+) -?([0-9]+) (.*)', line)
- if result:
- inode2filename[(int(result.group(1)), int(result.group(2)))] = \
- (result.group(4), result.group(3))
-
- return inode2filename
-
- def resolve(self, dev_t: int, ino_t: int) -> Optional[str]:
- """
- Return a filename (str) from a (dev_t, ino_t) inode pair.
-
- Returns None if the lookup fails.
- """
- maybe_result = self._inode_table.get((dev_t, ino_t))
-
- if not maybe_result:
- return None
-
- return maybe_result[0] # filename str
-
- def __len__(self) -> int:
- """
- :return: the number of inode entries parsed from the file.
- """
- return len(self._inode_table)
-
- def __repr__(self) -> str:
- """
- :return: string representation for debugging/test failures.
- """
- return "Inode2Filename%s" %(repr(self._inode_table))
-
- # end of class.
diff --git a/startop/scripts/iorap/lib/inode2filename_test.py b/startop/scripts/iorap/lib/inode2filename_test.py
deleted file mode 100755
index 1224c61..0000000
--- a/startop/scripts/iorap/lib/inode2filename_test.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-
-"""
-Unit tests for inode2filename module.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./inode2filename_test.py
- $> pytest inode2filename_test.py
- $> python -m pytest inode2filename_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-from contextlib import contextmanager
-import io
-import shlex
-import sys
-import typing
-
-# pip imports
-import pytest
-
-# local imports
-from inode2filename import *
-
-def create_inode2filename(*contents):
- buf = io.StringIO()
-
- for c in contents:
- buf.write(c)
- buf.write("\n")
-
- buf.seek(0)
-
- i2f = Inode2Filename(buf)
-
- buf.close()
-
- return i2f
-
-def test_inode2filename():
- a = create_inode2filename("")
- assert len(a) == 0
- assert a.resolve(1, 2) == None
-
- a = create_inode2filename("1 2 3 foo.bar")
- assert len(a) == 1
- assert a.resolve(1, 2) == "foo.bar"
- assert a.resolve(4, 5) == None
-
- a = create_inode2filename("1 2 3 foo.bar", "4 5 6 bar.baz")
- assert len(a) == 2
- assert a.resolve(1, 2) == "foo.bar"
- assert a.resolve(4, 5) == "bar.baz"
-
- a = create_inode2filename("1567d 8910 -1 /a/b/c/", "4 5 6 bar.baz")
- assert len(a) == 2
- assert a.resolve(1567, 8910) == "/a/b/c/"
- assert a.resolve(4, 5) == "bar.baz"
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/iorap/lib/iorapd_utils.py b/startop/scripts/iorap/lib/iorapd_utils.py
deleted file mode 100644
index f6f21fd..0000000
--- a/startop/scripts/iorap/lib/iorapd_utils.py
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-"""Helper util libraries for iorapd related operations."""
-
-import os
-import sys
-
-# up to two level
-sys.path.append(os.path.join(os.path.abspath(__file__),'../..'))
-import lib.cmd_utils as cmd_utils
-
-IORAPID_LIB_DIR = os.path.abspath(os.path.dirname(__file__))
-IORAPD_DATA_PATH = '/data/misc/iorapd'
-IORAP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(IORAPID_LIB_DIR,
- '../common'))
-
-def _iorapd_path_to_data_file(package: str, activity: str, suffix: str) -> str:
- """Gets conventional data filename.
-
- Returns:
- The path of iorapd data file.
-
- """
- # Match logic of 'AppComponentName' in iorap::compiler C++ code.
- return '{}/{}%2F{}.{}'.format(IORAPD_DATA_PATH, package, activity, suffix)
-
-def compile_perfetto_trace_on_device(package: str, activity: str,
- inodes: str) -> bool:
- """Compiles the perfetto trace using on-device compiler."""
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_compiler_for_app_trace',
- [package, activity, inodes])
- return passed
-
-def get_iorapd_compiler_trace(package: str, activity: str, dest: str) -> str:
- """Gets compiler trace to dest file."""
- src = _iorapd_path_to_data_file(package, activity, 'compiled_trace.pb')
- passed, _ = cmd_utils.run_shell_command('adb pull "{}" "{}"'.format(src, dest))
- if not passed:
- return False
- return True
-
-def iorapd_compiler_install_trace_file(package: str, activity: str,
- input_file: str) -> bool:
- """Installs a compiled trace file.
-
- Returns:
- Whether the trace file is installed successful or not.
- """
- # remote path calculations
- compiled_path = _iorapd_path_to_data_file(package, activity,
- 'compiled_trace.pb')
-
- if not os.path.exists(input_file):
- print('Error: File {} does not exist'.format(input_file))
- return False
-
- passed, _ = cmd_utils.run_adb_shell_command(
- 'mkdir -p "$(dirname "{}")"'.format(compiled_path))
- if not passed:
- return False
-
- passed, _ = cmd_utils.run_shell_command('adb push "{}" "{}"'.format(
- input_file, compiled_path))
-
- return passed
-
-def wait_for_iorapd_finish(package: str,
- activity: str,
- timeout: int,
- debug: bool,
- logcat_timestamp: str)->bool:
- """Waits for the finish of iorapd.
-
- Returns:
- A bool indicates whether the iorapd is done successfully or not.
- """
- # Set verbose for bash script based on debug flag.
- if debug:
- os.putenv('verbose', 'y')
-
- # Validate that readahead completes.
- # If this fails for some reason, then this will also discard the timing of
- # the run.
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_readahead_wait_until_finished',
- [package, activity, logcat_timestamp,
- str(timeout)])
- return passed
-
-
-def enable_iorapd_readahead() -> bool:
- """
- Disable readahead. Subsequent launches of an application will be sped up
- by iorapd readahead prefetching.
-
- Returns:
- A bool indicates whether the enabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_readahead_enable', [])
- return passed
-
-def disable_iorapd_readahead() -> bool:
- """
- Disable readahead. Subsequent launches of an application will be not be sped
- up by iorapd readahead prefetching.
-
- Returns:
- A bool indicates whether the disabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_readahead_disable', [])
- return passed
-
-def enable_iorapd_perfetto() -> bool:
- """
- Enable Perfetto. Subsequent launches of an application will record a perfetto
- trace protobuf.
-
- Returns:
- A bool indicates whether the enabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_perfetto_enable', [])
- return passed
-
-def disable_iorapd_perfetto() -> bool:
- """
- Disable Perfetto. Subsequent launches of applications will no longer record
- perfetto trace protobufs.
-
- Returns:
- A bool indicates whether the disabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_perfetto_disable', [])
- return passed
-
-def start_iorapd() -> bool:
- """
- Starts iorapd.
-
- Returns:
- A bool indicates whether the starting is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_start', [])
- return passed
-
-def stop_iorapd() -> bool:
- """
- Stops iorapd.
-
- Returns:
- A bool indicates whether the stopping is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_stop', [])
- return passed
-
diff --git a/startop/scripts/iorap/pull_textcache b/startop/scripts/iorap/pull_textcache
deleted file mode 100755
index 0554426..0000000
--- a/startop/scripts/iorap/pull_textcache
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019, 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.
-
-if [[ $# -lt 1 ]]; then
- echo "Usage: $0 <output-filename>" >&2
- exit 1
-fi
-
-# see compiler/main.cc for list of roots
-adb shell iorap.inode2filename --output-format=textcache --output=/data/local/tmp/dumpcache --all --root=/system --root=/apex --root=/vendor --root=/data --root=/product --root=/metadata
-adb pull /data/local/tmp/dumpcache "$1"
diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb b/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb
deleted file mode 100644
index a47ad3d..0000000
--- a/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb
+++ /dev/null
Binary files differ
diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_systrace b/startop/scripts/iorap/test_fixtures/compiler/common_systrace
deleted file mode 100644
index 4573738..0000000
--- a/startop/scripts/iorap/test_fixtures/compiler/common_systrace
+++ /dev/null
@@ -1,5 +0,0 @@
-<...>-2965 (-----) [001] .... 10000.746629: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000679ee1ec pfn=1299913 ofs=192512
-<...>-2965 (-----) [001] .... 10010.746664: mm_filemap_add_to_page_cache: dev 253:6 ino 2 page=0000000006cd2fb7 pfn=1296251 ofs=196608
-<...>-2965 (-----) [001] .... 10020.746677: mm_filemap_add_to_page_cache: dev 253:6 ino 3 page=00000000af82f3d6 pfn=1419330 ofs=200704
-<...>-2965 (-----) [001] .... 10030.746693: mm_filemap_add_to_page_cache: dev 253:6 ino 4 page=000000002840f054 pfn=1304928 ofs=204800
-<...>-2965 (-----) [001] .... 10040.746706: mm_filemap_add_to_page_cache: dev 253:6 ino 5 page=000000004a59da17 pfn=1288069 ofs=208896
diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_textcache b/startop/scripts/iorap/test_fixtures/compiler/common_textcache
deleted file mode 100644
index da03004..0000000
--- a/startop/scripts/iorap/test_fixtures/compiler/common_textcache
+++ /dev/null
@@ -1,2 +0,0 @@
-64774 1 -1 /system/test1
-64774 3 -1 /data/test2
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace b/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
deleted file mode 100644
index 59ff753..0000000
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
+++ /dev/null
@@ -1,748 +0,0 @@
-TRACE:
-# tracer: nop
-#
-# entries-in-buffer/entries-written: 30624/30624 #P:4
-#
-# _-----=> irqs-off
-# / _----=> need-resched
-# | / _---=> hardirq/softirq
-# || / _--=> preempt-depth
-# ||| / delay
-# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION
-# | | | | |||| | |
- <unknown>-27388 (-----) [004] .... 1920260.530929: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1461937 ofs=9535488
- <unknown>-27388 (-----) [005] .... 1920260.532161: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1344589 ofs=9474048
- <unknown>-27388 (-----) [005] .... 1920260.532183: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1153671 ofs=9478144
- <unknown>-27388 (-----) [005] .... 1920260.532184: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1219563 ofs=9482240
- <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1083162 ofs=9486336
- <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1147318 ofs=9490432
- <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1333594 ofs=9494528
- <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1375715 ofs=9498624
- <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1184831 ofs=9502720
- <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1241653 ofs=9506816
- <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1134975 ofs=9510912
- <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1145772 ofs=9515008
- <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1090457 ofs=9519104
- <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1137942 ofs=9523200
- <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1130123 ofs=9527296
- <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1208783 ofs=9531392
- <unknown>-27388 (-----) [005] .... 1920260.532192: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1294989 ofs=9539584
- <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1163979 ofs=9543680
- <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1350628 ofs=9547776
- <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1386717 ofs=9551872
- <unknown>-27388 (-----) [005] .... 1920260.532207: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1316148 ofs=9555968
- <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1316419 ofs=9560064
- <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1149076 ofs=9564160
- <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1372772 ofs=9568256
- <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1116389 ofs=9572352
- <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1325458 ofs=9576448
- <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1195423 ofs=9580544
- <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1250964 ofs=9584640
- <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1196027 ofs=9588736
- <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1354059 ofs=9592832
- <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1264649 ofs=9596928
- <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1245285 ofs=9601024
- <unknown>-27388 (-----) [005] .... 1920260.535119: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1411552 ofs=44244992
- <unknown>-27388 (-----) [005] .... 1920260.535129: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1483081 ofs=433524736
- <unknown>-27388 (-----) [004] .... 1920260.536144: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1276173 ofs=438185984
- <unknown>-27388 (-----) [004] .... 1920260.536462: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1174575 ofs=44249088
- <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1126294 ofs=44253184
- <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1248232 ofs=44257280
- <unknown>-27388 (-----) [004] .... 1920260.537065: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1332993 ofs=44240896
- <unknown>-27388 (-----) [006] .... 1920260.537646: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1153343 ofs=44400640
- <unknown>-27388 (-----) [005] .... 1920260.538777: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1358397 ofs=44474368
- <unknown>-12683 (-----) [006] .... 1920260.560094: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1426577 ofs=0
- <unknown>-12683 (-----) [006] .... 1920260.560105: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117587 ofs=1171456
- <unknown>-12683 (-----) [006] .... 1920260.561199: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099987 ofs=4096
- <unknown>-12683 (-----) [006] .... 1920260.561411: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099910 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.561598: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099905 ofs=20480
- <unknown>-12683 (-----) [006] .... 1920260.561758: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099883 ofs=32768
- <unknown>-12683 (-----) [006] .... 1920260.562088: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099809 ofs=36864
- <unknown>-12683 (-----) [006] .... 1920260.562325: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099803 ofs=98304
- <unknown>-12683 (-----) [006] .... 1920260.562516: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099795 ofs=102400
- <unknown>-12683 (-----) [006] .... 1920260.563094: mm_filemap_add_to_page_cache: dev 0:64768 ino 5f3 page=0000000000000000 pfn=1107649 ofs=12288
- <unknown>-12683 (-----) [006] .... 1920260.563105: mm_filemap_add_to_page_cache: dev 0:64768 ino 5f3 page=0000000000000000 pfn=1269029 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.563785: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1451096 ofs=8192
- <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1301480 ofs=12288
- <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1314353 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.563791: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1216744 ofs=24576
- <unknown>-12683 (-----) [006] .... 1920260.564309: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099787 ofs=49152
- <unknown>-12683 (-----) [006] .... 1920260.564514: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099778 ofs=53248
- <unknown>-12683 (-----) [005] .... 1920260.564756: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1148849 ofs=114688
- <unknown>-12683 (-----) [005] .... 1920260.564973: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1164731 ofs=118784
- <unknown>-12683 (-----) [005] .... 1920260.565000: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1170255 ofs=0
- <unknown>-12683 (-----) [005] .... 1920260.565003: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1181043 ofs=4096
- <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1296004 ofs=8192
- <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1102004 ofs=12288
- <unknown>-12683 (-----) [005] .... 1920260.565626: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1351232 ofs=470597632
- <unknown>-12683 (-----) [005] .... 1920260.565982: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1391336 ofs=40210432
- <unknown>-12683 (-----) [005] .... 1920260.565985: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267536 ofs=12668928
- <unknown>-27388 (-----) [007] .... 1920260.566082: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1256752 ofs=43921408
- <unknown>-12683 (-----) [005] .... 1920260.566516: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1110966 ofs=176226304
- <unknown>-12683 (-----) [005] .... 1920260.566519: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1060586 ofs=12967936
- <unknown>-12683 (-----) [004] .... 1920260.567773: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117234 ofs=421888
- <unknown>-12683 (-----) [005] .... 1920260.568604: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1210571 ofs=430080
- <unknown>-12683 (-----) [005] .... 1920260.568887: mm_filemap_add_to_page_cache: dev 0:64771 ino 69 page=0000000000000000 pfn=1055640 ofs=0
- <unknown>-12683 (-----) [005] .... 1920260.568908: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1142694 ofs=0
- <unknown>-12683 (-----) [005] .... 1920260.568910: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1060788 ofs=299008
- <unknown>-12683 (-----) [005] .... 1920260.569418: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1085046 ofs=4096
- <unknown>-12683 (-----) [005] .... 1920260.569640: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1057135 ofs=8192
- <unknown>-12683 (-----) [005] .... 1920260.569833: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1058976 ofs=19406848
- <unknown>-12683 (-----) [005] .... 1920260.569835: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1477947 ofs=10526720
- <unknown>-12683 (-----) [005] .... 1920260.572285: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1237492 ofs=299008
- <unknown>-12683 (-----) [005] .... 1920260.572297: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1264914 ofs=339968
- <unknown>-12683 (-----) [005] .... 1920260.572314: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1434748 ofs=348160
- <unknown>-12683 (-----) [005] .... 1920260.572316: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1372959 ofs=352256
- <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1258955 ofs=356352
- <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1113420 ofs=360448
- <unknown>-12683 (-----) [005] .... 1920260.572318: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1137083 ofs=364544
- <unknown>-12683 (-----) [004] .... 1920260.575490: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1379679 ofs=65536
- <unknown>-12683 (-----) [006] .... 1920260.576194: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1323898 ofs=69632
- <unknown>-12683 (-----) [006] .... 1920260.576248: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323895 ofs=262623232
- <unknown>-12683 (-----) [006] .... 1920260.576251: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323861 ofs=13156352
- <unknown>-12683 (-----) [005] .... 1920260.576810: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1477585 ofs=262590464
- <unknown>-12683 (-----) [004] .... 1920260.577197: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1267617 ofs=25206784
- <unknown>-12683 (-----) [004] .... 1920260.577200: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267618 ofs=12636160
- <unknown>-12683 (-----) [005] .... 1920260.577725: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1056225 ofs=228618240
- <unknown>-12683 (-----) [005] .... 1920260.577727: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1164942 ofs=13082624
- <unknown>-12683 (-----) [007] .... 1920260.578411: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1372616 ofs=0
- <unknown>-12683 (-----) [007] .... 1920260.578422: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1307468 ofs=4096
- <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1120117 ofs=8192
- <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1217989 ofs=12288
- <unknown>-12683 (-----) [007] .... 1920260.578650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1475011 ofs=5419008
- <unknown>-12683 (-----) [007] .... 1920260.578653: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1066084 ofs=236453888
- <unknown>-12683 (-----) [007] .... 1920260.578654: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1100271 ofs=13099008
- <unknown>-12683 (-----) [004] .... 1920260.579004: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1485156 ofs=5423104
- <unknown>-12683 (-----) [004] .... 1920260.579005: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1124212 ofs=5427200
- <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1195377 ofs=5431296
- <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1265888 ofs=5435392
- <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1170194 ofs=5439488
- <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1403742 ofs=5443584
- <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1123826 ofs=5447680
- <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1255034 ofs=5451776
- <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1190447 ofs=5455872
- <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1286864 ofs=5459968
- <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1428535 ofs=5464064
- <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1184092 ofs=5468160
- <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1411906 ofs=5472256
- <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1342349 ofs=5476352
- <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1188185 ofs=5480448
- <unknown>-12683 (-----) [004] .... 1920260.579014: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1158702 ofs=5484544
- <unknown>-12683 (-----) [005] .... 1920260.579430: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1299421 ofs=5230592
- <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1317097 ofs=5234688
- <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1441714 ofs=5238784
- <unknown>-12683 (-----) [005] .... 1920260.579438: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1081974 ofs=5242880
- <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1128684 ofs=5246976
- <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447381 ofs=5251072
- <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1466410 ofs=5255168
- <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1259909 ofs=5259264
- <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1125784 ofs=5263360
- <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1270592 ofs=5267456
- <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246070 ofs=5271552
- <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1472544 ofs=5275648
- <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1113357 ofs=5279744
- <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1202021 ofs=5283840
- <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078639 ofs=5287936
- <unknown>-12683 (-----) [005] .... 1920260.579449: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1176171 ofs=5292032
- <unknown>-12683 (-----) [005] .... 1920260.579450: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1089516 ofs=5296128
- <unknown>-12683 (-----) [005] .... 1920260.579451: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1400065 ofs=5300224
- <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1300489 ofs=5304320
- <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1452081 ofs=5308416
- <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1161862 ofs=5312512
- <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1161871 ofs=5316608
- <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1263798 ofs=5320704
- <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1126887 ofs=5324800
- <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1375498 ofs=5328896
- <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1328067 ofs=5332992
- <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1420691 ofs=5337088
- <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1298707 ofs=5341184
- <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078670 ofs=5345280
- <unknown>-12683 (-----) [005] .... 1920260.579457: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1430498 ofs=5349376
- <unknown>-12683 (-----) [005] .... 1920260.579458: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1338720 ofs=5353472
- <unknown>-12683 (-----) [005] .... 1920260.579476: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1452611 ofs=5357568
- <unknown>-12683 (-----) [006] .... 1920260.580451: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241967 ofs=0
- <unknown>-12683 (-----) [006] .... 1920260.580454: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1116541 ofs=4096
- <unknown>-12683 (-----) [006] .... 1920260.580461: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1145049 ofs=8192
- <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1277255 ofs=12288
- <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1098037 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.580463: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1135986 ofs=20480
- <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1154455 ofs=24576
- <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1221822 ofs=28672
- <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1078684 ofs=32768
- <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1158876 ofs=36864
- <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1289644 ofs=40960
- <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1289386 ofs=45056
- <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1131002 ofs=49152
- <unknown>-12683 (-----) [006] .... 1920260.580467: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1464335 ofs=53248
- <unknown>-12683 (-----) [006] .... 1920260.580468: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1135789 ofs=57344
- <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1240897 ofs=61440
- <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241770 ofs=65536
- <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1421959 ofs=69632
- <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1230007 ofs=73728
- <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1109271 ofs=77824
- <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1159974 ofs=81920
- <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1154528 ofs=86016
- <unknown>-12683 (-----) [006] .... 1920260.580472: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1315790 ofs=90112
- <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1185583 ofs=94208
- <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1253153 ofs=98304
- <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103982 ofs=102400
- <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1284589 ofs=106496
- <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1169601 ofs=110592
- <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1206248 ofs=114688
- <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1261161 ofs=118784
- <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1305841 ofs=122880
- <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1468293 ofs=126976
- <unknown>-12683 (-----) [004] .... 1920260.580646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1318816 ofs=16384
- <unknown>-12683 (-----) [004] .... 1920260.580649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1472922 ofs=20480
- <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1473229 ofs=24576
- <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1524262 ofs=28672
- <unknown>-12683 (-----) [004] .... 1920260.580656: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1205714 ofs=32768
- <unknown>-12683 (-----) [004] .... 1920260.580657: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1310560 ofs=36864
- <unknown>-12683 (-----) [004] .... 1920260.580658: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1295070 ofs=40960
- <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1404093 ofs=45056
- <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1435814 ofs=49152
- <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1435442 ofs=53248
- <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1096077 ofs=57344
- <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1483793 ofs=61440
- <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1231298 ofs=65536
- <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1215648 ofs=69632
- <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1327326 ofs=73728
- <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1108894 ofs=77824
- <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1327545 ofs=81920
- <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1328804 ofs=86016
- <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1300171 ofs=90112
- <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353250 ofs=94208
- <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1333681 ofs=98304
- <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1144969 ofs=102400
- <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1450962 ofs=106496
- <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1255701 ofs=110592
- <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1294782 ofs=114688
- <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1226912 ofs=118784
- <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1294579 ofs=122880
- <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246960 ofs=126976
- <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1199086 ofs=131072
- <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1449590 ofs=135168
- <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1276363 ofs=139264
- <unknown>-12683 (-----) [004] .... 1920260.580675: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1389998 ofs=143360
- <unknown>-12683 (-----) [004] .... 1920260.580739: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1423031 ofs=1249280
- <unknown>-12683 (-----) [004] .... 1920260.580741: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1171032 ofs=1253376
- <unknown>-12683 (-----) [004] .... 1920260.580742: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1320946 ofs=1257472
- <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1314696 ofs=1261568
- <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1414864 ofs=1265664
- <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1334933 ofs=1269760
- <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1242845 ofs=1273856
- <unknown>-12683 (-----) [004] .... 1920260.580747: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1289488 ofs=1277952
- <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1335445 ofs=1282048
- <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1289663 ofs=1286144
- <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1080462 ofs=1290240
- <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1286303 ofs=1294336
- <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353531 ofs=1298432
- <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1280701 ofs=1302528
- <unknown>-12683 (-----) [004] .... 1920260.580751: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1107730 ofs=1306624
- <unknown>-12683 (-----) [004] .... 1920260.580752: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1242729 ofs=1310720
- <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078336 ofs=1314816
- <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1372425 ofs=1318912
- <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1248813 ofs=1323008
- <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1201155 ofs=1327104
- <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1250103 ofs=1331200
- <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1359710 ofs=1335296
- <unknown>-12683 (-----) [004] .... 1920260.580756: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1272462 ofs=1339392
- <unknown>-12683 (-----) [004] .... 1920260.580758: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1097035 ofs=1343488
- <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1233124 ofs=1347584
- <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1455812 ofs=1351680
- <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1355689 ofs=1355776
- <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1263593 ofs=1359872
- <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1230789 ofs=1363968
- <unknown>-12683 (-----) [004] .... 1920260.580761: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1143766 ofs=1368064
- <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1269666 ofs=1372160
- <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353022 ofs=1376256
- <unknown>-12683 (-----) [004] .... 1920260.581613: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1355509 ofs=258048
- <unknown>-12683 (-----) [004] .... 1920260.581615: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1178902 ofs=262144
- <unknown>-12683 (-----) [004] .... 1920260.581616: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1193649 ofs=266240
- <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1225497 ofs=270336
- <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1228259 ofs=274432
- <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1309674 ofs=278528
- <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1239390 ofs=282624
- <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1468083 ofs=286720
- <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1292751 ofs=290816
- <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1318066 ofs=294912
- <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1489314 ofs=299008
- <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1169867 ofs=303104
- <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1314256 ofs=307200
- <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1310230 ofs=311296
- <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1356180 ofs=315392
- <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1419179 ofs=319488
- <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1307265 ofs=323584
- <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1218590 ofs=327680
- <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447586 ofs=331776
- <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1209382 ofs=335872
- <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1072148 ofs=339968
- <unknown>-12683 (-----) [004] .... 1920260.581645: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1227195 ofs=344064
- <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246369 ofs=348160
- <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1193845 ofs=352256
- <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1137553 ofs=356352
- <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1475215 ofs=360448
- <unknown>-12683 (-----) [004] .... 1920260.581648: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1258935 ofs=364544
- <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1448788 ofs=368640
- <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447611 ofs=372736
- <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1290842 ofs=376832
- <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447826 ofs=380928
- <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1181016 ofs=385024
- <unknown>-12683 (-----) [005] .... 1920260.582230: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1216810 ofs=1662976
- <unknown>-12683 (-----) [005] .... 1920260.582234: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1175966 ofs=1667072
- <unknown>-12683 (-----) [005] .... 1920260.582235: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1449798 ofs=1671168
- <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1273480 ofs=1675264
- <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1152779 ofs=1679360
- <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1272810 ofs=1683456
- <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1248634 ofs=1687552
- <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1203376 ofs=1691648
- <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1138880 ofs=1695744
- <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1344591 ofs=1699840
- <unknown>-12683 (-----) [005] .... 1920260.582239: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1416060 ofs=1703936
- <unknown>-12683 (-----) [005] .... 1920260.582246: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1128676 ofs=1708032
- <unknown>-12683 (-----) [005] .... 1920260.582247: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1301921 ofs=1712128
- <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1384569 ofs=1716224
- <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1249106 ofs=1720320
- <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1206596 ofs=1724416
- <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1429831 ofs=1728512
- <unknown>-12683 (-----) [005] .... 1920260.582252: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1107796 ofs=1732608
- <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1098336 ofs=1736704
- <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1230286 ofs=1740800
- <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1100370 ofs=1744896
- <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241930 ofs=1748992
- <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1366807 ofs=1753088
- <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1136252 ofs=1757184
- <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1274291 ofs=1761280
- <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1254775 ofs=1765376
- <unknown>-12683 (-----) [005] .... 1920260.582259: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1194679 ofs=1769472
- <unknown>-12683 (-----) [005] .... 1920260.582262: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1177090 ofs=1773568
- <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1343925 ofs=1777664
- <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1159217 ofs=1781760
- <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435471 ofs=1785856
- <unknown>-12683 (-----) [005] .... 1920260.582264: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435529 ofs=1789952
- <unknown>-12683 (-----) [004] .... 1920260.582524: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1181910 ofs=0
- <unknown>-12683 (-----) [004] .... 1920260.582528: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1212021 ofs=4096
- <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1162778 ofs=8192
- <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1107700 ofs=12288
- <unknown>-12683 (-----) [004] .... 1920260.583553: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1093394 ofs=3399680
- <unknown>-12683 (-----) [004] .... 1920260.583984: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1121431 ofs=242503680
- <unknown>-12683 (-----) [004] .... 1920260.583986: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1168551 ofs=13115392
- <unknown>-12683 (-----) [004] .... 1920260.584304: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347409 ofs=0
- <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1428681 ofs=4096
- <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1259106 ofs=8192
- <unknown>-12683 (-----) [004] .... 1920260.584308: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1343229 ofs=12288
- <unknown>-12694 (-----) [005] .... 1920260.584622: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1098733 ofs=1531904
- <unknown>-12696 (-----) [006] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331319 ofs=1536000
- <unknown>-12694 (-----) [005] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278537 ofs=1540096
- <unknown>-12696 (-----) [006] .... 1920260.584631: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1492534 ofs=1544192
- <unknown>-12694 (-----) [005] .... 1920260.584636: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1460878 ofs=1548288
- <unknown>-12694 (-----) [005] .... 1920260.584640: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092973 ofs=1552384
- <unknown>-12694 (-----) [005] .... 1920260.584641: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1103200 ofs=1556480
- <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1257426 ofs=1560576
- <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1219424 ofs=1564672
- <unknown>-12683 (-----) [004] .... 1920260.584660: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279352 ofs=1568768
- <unknown>-12696 (-----) [006] .... 1920260.584662: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260572 ofs=1572864
- <unknown>-12683 (-----) [004] .... 1920260.584663: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1225809 ofs=1576960
- <unknown>-12696 (-----) [006] .... 1920260.584665: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1350766 ofs=1585152
- <unknown>-12697 (-----) [007] .... 1920260.584666: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1107173 ofs=1581056
- <unknown>-12683 (-----) [004] .... 1920260.584668: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1305885 ofs=1589248
- <unknown>-12694 (-----) [005] .... 1920260.584669: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1293385 ofs=1593344
- <unknown>-12696 (-----) [006] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1173841 ofs=1597440
- <unknown>-12697 (-----) [007] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080021 ofs=1601536
- <unknown>-12683 (-----) [004] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1147419 ofs=1605632
- <unknown>-12696 (-----) [006] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1252762 ofs=1609728
- <unknown>-12694 (-----) [005] .... 1920260.584674: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1323916 ofs=1613824
- <unknown>-12683 (-----) [004] .... 1920260.584675: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1155631 ofs=1617920
- <unknown>-12696 (-----) [006] .... 1920260.584676: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449815 ofs=1622016
- <unknown>-12694 (-----) [005] .... 1920260.584678: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1227069 ofs=1626112
- <unknown>-12696 (-----) [006] .... 1920260.584680: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1317692 ofs=1630208
- <unknown>-12694 (-----) [005] .... 1920260.584681: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1492244 ofs=1634304
- <unknown>-12683 (-----) [004] .... 1920260.584682: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241876 ofs=1638400
- <unknown>-12697 (-----) [007] .... 1920260.585446: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1402958 ofs=167936
- <unknown>-12697 (-----) [007] .... 1920260.585449: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1133263 ofs=172032
- <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1295502 ofs=176128
- <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1249495 ofs=180224
- <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237999 ofs=184320
- <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1280965 ofs=188416
- <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1208361 ofs=192512
- <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1308840 ofs=196608
- <unknown>-12695 (-----) [004] .... 1920260.585455: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1138875 ofs=569344
- <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314886 ofs=573440
- <unknown>-12697 (-----) [007] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242734 ofs=200704
- <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447386 ofs=577536
- <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241302 ofs=204800
- <unknown>-12695 (-----) [004] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1328663 ofs=581632
- <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1476101 ofs=208896
- <unknown>-12695 (-----) [004] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209461 ofs=585728
- <unknown>-12697 (-----) [007] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080147 ofs=212992
- <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128509 ofs=217088
- <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1371915 ofs=221184
- <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1264015 ofs=225280
- <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1211695 ofs=229376
- <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1150386 ofs=233472
- <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1135747 ofs=237568
- <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128230 ofs=241664
- <unknown>-12697 (-----) [007] .... 1920260.585464: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1155451 ofs=245760
- <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1246841 ofs=249856
- <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1462971 ofs=253952
- <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1131333 ofs=258048
- <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289407 ofs=262144
- <unknown>-12695 (-----) [004] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1134730 ofs=589824
- <unknown>-12697 (-----) [007] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289873 ofs=266240
- <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448734 ofs=270336
- <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1129776 ofs=593920
- <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524090 ofs=274432
- <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399725 ofs=598016
- <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524081 ofs=278528
- <unknown>-12695 (-----) [004] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1276535 ofs=602112
- <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524060 ofs=282624
- <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449847 ofs=606208
- <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1158944 ofs=286720
- <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1384536 ofs=610304
- <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1116785 ofs=290816
- <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1308118 ofs=614400
- <unknown>-12697 (-----) [007] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448669 ofs=294912
- <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1227050 ofs=618496
- <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289324 ofs=622592
- <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1187869 ofs=626688
- <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1400523 ofs=630784
- <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1344176 ofs=634880
- <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092871 ofs=638976
- <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092021 ofs=643072
- <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1198169 ofs=647168
- <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1371540 ofs=651264
- <unknown>-12683 (-----) [005] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1195003 ofs=348160
- <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1228787 ofs=655360
- <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1236123 ofs=659456
- <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1137213 ofs=663552
- <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1294618 ofs=667648
- <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241048 ofs=671744
- <unknown>-12695 (-----) [004] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1228779 ofs=675840
- <unknown>-12683 (-----) [005] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1199292 ofs=352256
- <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200861 ofs=356352
- <unknown>-12695 (-----) [004] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1309572 ofs=679936
- <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1215770 ofs=360448
- <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1409002 ofs=684032
- <unknown>-12683 (-----) [005] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1151883 ofs=364544
- <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1103729 ofs=688128
- <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1468126 ofs=368640
- <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1162720 ofs=692224
- <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1251672 ofs=372736
- <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1199221 ofs=696320
- <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1283325 ofs=376832
- <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1190489 ofs=380928
- <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1489117 ofs=385024
- <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1273899 ofs=389120
- <unknown>-12683 (-----) [005] .... 1920260.585485: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1274459 ofs=393216
- <unknown>-12683 (-----) [005] .... 1920260.585486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1316649 ofs=397312
- <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1375678 ofs=401408
- <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1483317 ofs=405504
- <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1240286 ofs=409600
- <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1131345 ofs=413696
- <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200483 ofs=417792
- <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1384693 ofs=421888
- <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1161385 ofs=425984
- <unknown>-12683 (-----) [005] .... 1920260.585494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1452025 ofs=430080
- <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1253654 ofs=434176
- <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1116697 ofs=438272
- <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1432645 ofs=442368
- <unknown>-12694 (-----) [006] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1337397 ofs=16384
- <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1304229 ofs=446464
- <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1419147 ofs=450560
- <unknown>-12683 (-----) [005] .... 1920260.585498: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1349246 ofs=454656
- <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128519 ofs=458752
- <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1125168 ofs=462848
- <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1081031 ofs=20480
- <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1293022 ofs=24576
- <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1113007 ofs=28672
- <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1339312 ofs=32768
- <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1412311 ofs=36864
- <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260960 ofs=40960
- <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189529 ofs=45056
- <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1412184 ofs=49152
- <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1481227 ofs=53248
- <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1455940 ofs=57344
- <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299132 ofs=61440
- <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1337375 ofs=65536
- <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1328742 ofs=69632
- <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1315646 ofs=73728
- <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1225475 ofs=77824
- <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1146097 ofs=81920
- <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1318775 ofs=86016
- <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448391 ofs=90112
- <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1441412 ofs=94208
- <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1138111 ofs=98304
- <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1143223 ofs=102400
- <unknown>-12683 (-----) [005] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1079876 ofs=466944
- <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447637 ofs=106496
- <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1220585 ofs=110592
- <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449051 ofs=114688
- <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313180 ofs=118784
- <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313166 ofs=122880
- <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313154 ofs=126976
- <unknown>-12683 (-----) [005] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1218394 ofs=471040
- <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1144047 ofs=131072
- <unknown>-12683 (-----) [005] .... 1920260.585537: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1218579 ofs=475136
- <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241332 ofs=135168
- <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1097199 ofs=139264
- <unknown>-12694 (-----) [006] .... 1920260.585545: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1214197 ofs=143360
- <unknown>-12694 (-----) [006] .... 1920260.585645: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197633 ofs=147456
- <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1311536 ofs=151552
- <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1322952 ofs=155648
- <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346974 ofs=159744
- <unknown>-12694 (-----) [006] .... 1920260.585648: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1257232 ofs=163840
- <unknown>-12695 (-----) [004] .... 1920260.586355: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1204484 ofs=700416
- <unknown>-12695 (-----) [004] .... 1920260.586357: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1326426 ofs=704512
- <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1151808 ofs=708608
- <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209422 ofs=712704
- <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1408387 ofs=716800
- <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197336 ofs=720896
- <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1205652 ofs=724992
- <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1133421 ofs=729088
- <unknown>-12695 (-----) [004] .... 1920260.586364: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092173 ofs=733184
- <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1124430 ofs=737280
- <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1143926 ofs=741376
- <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1090109 ofs=745472
- <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1102012 ofs=749568
- <unknown>-12695 (-----) [004] .... 1920260.586367: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1154930 ofs=753664
- <unknown>-12695 (-----) [004] .... 1920260.586368: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1132993 ofs=757760
- <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1430780 ofs=761856
- <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197452 ofs=765952
- <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075111 ofs=770048
- <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1275616 ofs=774144
- <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1444981 ofs=778240
- <unknown>-12695 (-----) [004] .... 1920260.586371: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1452592 ofs=782336
- <unknown>-12695 (-----) [004] .... 1920260.586374: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1102857 ofs=786432
- <unknown>-12695 (-----) [004] .... 1920260.586376: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406969 ofs=790528
- <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1522553 ofs=794624
- <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260771 ofs=798720
- <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1474649 ofs=802816
- <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1268708 ofs=806912
- <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346144 ofs=811008
- <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1081167 ofs=815104
- <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1137677 ofs=819200
- <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1161175 ofs=823296
- <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1461331 ofs=827392
- <unknown>-12695 (-----) [004] .... 1920260.586492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347219 ofs=831488
- <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1290004 ofs=835584
- <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299174 ofs=839680
- <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1317595 ofs=843776
- <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1484924 ofs=847872
- <unknown>-12695 (-----) [004] .... 1920260.586497: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1169920 ofs=851968
- <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1359189 ofs=856064
- <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1307842 ofs=860160
- <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237858 ofs=864256
- <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189461 ofs=868352
- <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1223232 ofs=872448
- <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1104076 ofs=876544
- <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1079223 ofs=880640
- <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092537 ofs=884736
- <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1353960 ofs=888832
- <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346330 ofs=892928
- <unknown>-12695 (-----) [004] .... 1920260.586506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345764 ofs=897024
- <unknown>-12695 (-----) [004] .... 1920260.586507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1363913 ofs=901120
- <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1319570 ofs=905216
- <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1367024 ofs=909312
- <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1333808 ofs=913408
- <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1158627 ofs=917504
- <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1300368 ofs=921600
- <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1245363 ofs=925696
- <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345609 ofs=929792
- <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1393826 ofs=933888
- <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200552 ofs=937984
- <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1170885 ofs=942080
- <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1536209 ofs=946176
- <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189630 ofs=950272
- <unknown>-12695 (-----) [004] .... 1920260.586513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1121010 ofs=954368
- <unknown>-12695 (-----) [004] .... 1920260.586514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324474 ofs=958464
- <unknown>-12697 (-----) [007] .... 1920260.586578: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1129628 ofs=299008
- <unknown>-12697 (-----) [007] .... 1920260.586579: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1307120 ofs=303104
- <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347284 ofs=307200
- <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1312996 ofs=311296
- <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1170623 ofs=315392
- <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1359281 ofs=319488
- <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1180021 ofs=323584
- <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1195728 ofs=327680
- <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1163642 ofs=331776
- <unknown>-12697 (-----) [007] .... 1920260.586587: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1152538 ofs=335872
- <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345922 ofs=339968
- <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1343604 ofs=344064
- <unknown>-12697 (-----) [007] .... 1920260.586721: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399371 ofs=479232
- <unknown>-12697 (-----) [007] .... 1920260.586723: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1106549 ofs=483328
- <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331546 ofs=487424
- <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299299 ofs=491520
- <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1288883 ofs=495616
- <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399049 ofs=499712
- <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1146931 ofs=503808
- <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1296592 ofs=507904
- <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1468397 ofs=512000
- <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1215698 ofs=516096
- <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1177341 ofs=520192
- <unknown>-12697 (-----) [007] .... 1920260.586731: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189162 ofs=524288
- <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1435997 ofs=528384
- <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209896 ofs=532480
- <unknown>-12697 (-----) [007] .... 1920260.586733: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1255888 ofs=536576
- <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1234200 ofs=540672
- <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1422854 ofs=544768
- <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1435794 ofs=548864
- <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1236279 ofs=552960
- <unknown>-12697 (-----) [007] .... 1920260.586736: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1485732 ofs=557056
- <unknown>-12683 (-----) [005] .... 1920260.586743: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1417198 ofs=561152
- <unknown>-12683 (-----) [005] .... 1920260.586746: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1469450 ofs=565248
- <unknown>-12696 (-----) [004] .... 1920260.587465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1489023 ofs=1040384
- <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449498 ofs=1044480
- <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447737 ofs=1048576
- <unknown>-12696 (-----) [004] .... 1920260.587470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1124530 ofs=1052672
- <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1246743 ofs=1056768
- <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1441927 ofs=1060864
- <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1280581 ofs=1064960
- <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289438 ofs=1069056
- <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1464236 ofs=1073152
- <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1125808 ofs=1077248
- <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1329385 ofs=1081344
- <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314093 ofs=1085440
- <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1201837 ofs=1089536
- <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1327734 ofs=1093632
- <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406568 ofs=1097728
- <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331873 ofs=1101824
- <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331898 ofs=1105920
- <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331917 ofs=1110016
- <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1332091 ofs=1114112
- <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1108186 ofs=1118208
- <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1182631 ofs=1122304
- <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1085941 ofs=1126400
- <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1433982 ofs=1130496
- <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1387028 ofs=1134592
- <unknown>-12696 (-----) [004] .... 1920260.587488: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1353117 ofs=1138688
- <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1352364 ofs=1142784
- <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1144513 ofs=1146880
- <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1403984 ofs=1150976
- <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278970 ofs=1155072
- <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1326743 ofs=1159168
- <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1221809 ofs=1163264
- <unknown>-12696 (-----) [004] .... 1920260.587492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1268668 ofs=1167360
- <unknown>-12695 (-----) [005] .... 1920260.587502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1074544 ofs=962560
- <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1074294 ofs=966656
- <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075097 ofs=970752
- <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1162407 ofs=974848
- <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1141370 ofs=978944
- <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306487 ofs=983040
- <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306434 ofs=987136
- <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306347 ofs=991232
- <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306247 ofs=995328
- <unknown>-12695 (-----) [005] .... 1920260.587515: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306195 ofs=999424
- <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306039 ofs=1003520
- <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1305983 ofs=1007616
- <unknown>-12694 (-----) [006] .... 1920260.587701: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1216391 ofs=1171456
- <unknown>-12694 (-----) [006] .... 1920260.587705: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1262462 ofs=1175552
- <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1358114 ofs=1179648
- <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1357898 ofs=1183744
- <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237003 ofs=1187840
- <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1126319 ofs=1191936
- <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1415489 ofs=1196032
- <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279558 ofs=1200128
- <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1434022 ofs=1204224
- <unknown>-12694 (-----) [006] .... 1920260.587709: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1220130 ofs=1208320
- <unknown>-12694 (-----) [006] .... 1920260.587710: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1163037 ofs=1212416
- <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1404501 ofs=1216512
- <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406287 ofs=1220608
- <unknown>-12697 (-----) [007] .... 1920260.588132: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1355143 ofs=1376256
- <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1213923 ofs=1380352
- <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1243190 ofs=1384448
- <unknown>-12697 (-----) [007] .... 1920260.588143: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1300698 ofs=1388544
- <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1482568 ofs=1392640
- <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1461789 ofs=1396736
- <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242314 ofs=1400832
- <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1471996 ofs=1404928
- <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242742 ofs=1409024
- <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242579 ofs=1413120
- <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242553 ofs=1417216
- <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1457332 ofs=1421312
- <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1315431 ofs=1425408
- <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080653 ofs=1429504
- <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324174 ofs=1433600
- <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324142 ofs=1437696
- <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1157760 ofs=1441792
- <unknown>-12697 (-----) [007] .... 1920260.588151: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075059 ofs=1445888
- <unknown>-12683 (-----) [006] .... 1920260.589785: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279192 ofs=1486848
- <unknown>-12683 (-----) [006] .... 1920260.589790: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278527 ofs=1490944
- <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1091778 ofs=1495040
- <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1339447 ofs=1499136
- <unknown>-12683 (-----) [006] .... 1920260.589792: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1254007 ofs=1503232
- <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1115173 ofs=1507328
- <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1393985 ofs=1511424
- <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1369123 ofs=1515520
- <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314257 ofs=1519616
- <unknown>-12683 (-----) [006] .... 1920260.589802: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1404487 ofs=1523712
- <unknown>-12683 (-----) [006] .... 1920260.589803: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1354554 ofs=1527808
- <unknown>-12683 (-----) [006] .... 1920260.594312: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1141445 ofs=9801728
- <unknown>-12683 (-----) [006] .... 1920260.594322: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323774 ofs=231460864
- <unknown>-12683 (-----) [006] .... 1920260.594326: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323772 ofs=10993664
- <unknown>-12683 (-----) [006] .... 1920260.595212: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481305 ofs=9805824
- <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481306 ofs=9809920
- <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481316 ofs=9814016
- <unknown>-12683 (-----) [006] .... 1920260.595215: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481340 ofs=9818112
- <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1394587 ofs=9822208
- <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103455 ofs=9826304
- <unknown>-12683 (-----) [006] .... 1920260.595217: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103271 ofs=9830400
- <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103168 ofs=9834496
- <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103145 ofs=9838592
- <unknown>-12683 (-----) [006] .... 1920260.595219: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103115 ofs=9842688
- <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103057 ofs=9846784
- <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1331958 ofs=9850880
- <unknown>-12683 (-----) [006] .... 1920260.595227: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1356305 ofs=9854976
- <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103708 ofs=9859072
- <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1099286 ofs=9863168
- <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435190 ofs=9867264
- <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1395504 ofs=9871360
- <unknown>-12683 (-----) [006] .... 1920260.595230: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1352916 ofs=9875456
- <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1255529 ofs=9879552
- <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1336145 ofs=9883648
- <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1334143 ofs=9887744
- <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1328548 ofs=9891840
- <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1222215 ofs=9895936
- <unknown>-12683 (-----) [006] .... 1920260.595233: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1461056 ofs=9900032
- <unknown>-12683 (-----) [006] .... 1920260.595234: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1228276 ofs=9904128
- <unknown>-12683 (-----) [006] .... 1920260.595235: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1151188 ofs=9908224
- <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1443605 ofs=9912320
- <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1146821 ofs=9916416
- <unknown>-12683 (-----) [006] .... 1920260.595237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103669 ofs=9920512
- <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103744 ofs=9924608
- <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103868 ofs=9928704
- <unknown>-12683 (-----) [006] .... 1920260.595789: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1465942 ofs=15855616
- <unknown>-12683 (-----) [006] .... 1920260.595792: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323712 ofs=261189632
- <unknown>-12683 (-----) [006] .... 1920260.595998: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323701 ofs=262094848
- <unknown>-12683 (-----) [006] .... 1920260.596191: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1222287 ofs=15859712
- <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1213146 ofs=15863808
- <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1310396 ofs=15867904
- <unknown>-12683 (-----) [006] .... 1920260.596193: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1310177 ofs=15872000
- <unknown>-12683 (-----) [006] .... 1920260.596194: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1187914 ofs=15876096
- <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1322409 ofs=15880192
- <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1282484 ofs=15884288
- <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1097245 ofs=15888384
- <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1416816 ofs=15892480
- <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1257125 ofs=15896576
- <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1403527 ofs=15900672
- <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1218006 ofs=15904768
- <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1153893 ofs=15908864
- <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1328023 ofs=15912960
- <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1465412 ofs=15917056
- <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1092448 ofs=15921152
- <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1239220 ofs=15925248
- <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1276491 ofs=15929344
- <unknown>-12683 (-----) [006] .... 1920260.596205: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1262240 ofs=15933440
- <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1323793 ofs=15937536
- <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1074937 ofs=15941632
- <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1311157 ofs=15945728
- <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1308442 ofs=15949824
- <unknown>-12683 (-----) [006] .... 1920260.596210: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1467709 ofs=15953920
- <unknown>-12683 (-----) [006] .... 1920260.596211: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1394299 ofs=15958016
- <unknown>-12683 (-----) [004] .... 1920260.612586: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1316156 ofs=344064
- <unknown>-12683 (-----) [004] .... 1920260.612591: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1406323 ofs=348160
- <unknown>-12683 (-----) [004] .... 1920260.612601: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1216972 ofs=352256
- <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1271924 ofs=356352
- <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1369225 ofs=360448
- <unknown>-12683 (-----) [004] .... 1920260.612608: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1318474 ofs=364544
- <unknown>-12683 (-----) [004] .... 1920260.612609: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1227283 ofs=368640
- <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1364376 ofs=372736
- <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1073400 ofs=376832
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pb b/startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pb
deleted file mode 100644
index ab3df45..0000000
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pb
+++ /dev/null
Binary files differ
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pb b/startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pb
deleted file mode 100644
index 17cb116..0000000
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pb
+++ /dev/null
Binary files differ
diff --git a/startop/scripts/lib/cmd_utils.py b/startop/scripts/lib/cmd_utils.py
deleted file mode 100644
index 6071f14..0000000
--- a/startop/scripts/lib/cmd_utils.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-"""Helper util libraries for command line operations."""
-
-import asyncio
-import sys
-import time
-from typing import Tuple, Optional, List
-
-import lib.print_utils as print_utils
-
-TIMEOUT = 50
-SIMULATE = False
-
-def run_command_nofail(cmd: List[str], **kwargs) -> None:
- """Runs cmd list with default timeout.
-
- Throws exception if the execution fails.
- """
- my_kwargs = {"timeout": TIMEOUT, "shell": False, "simulate": False}
- my_kwargs.update(kwargs)
- passed, out = execute_arbitrary_command(cmd, **my_kwargs)
- if not passed:
- raise RuntimeError(
- "Failed to execute %s (kwargs=%s), output=%s" % (cmd, kwargs, out))
-
-def run_adb_shell_command(cmd: str) -> Tuple[bool, str]:
- """Runs command using adb shell.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed).
- """
- return run_shell_command('adb shell "{}"'.format(cmd))
-
-def run_shell_func(script_path: str,
- func: str,
- args: List[str]) -> Tuple[bool, str]:
- """Runs shell function with default timeout.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed) .
- """
- if args:
- cmd = 'bash -c "source {script_path}; {func} {args}"'.format(
- script_path=script_path,
- func=func,
- args=' '.join("'{}'".format(arg) for arg in args))
- else:
- cmd = 'bash -c "source {script_path}; {func}"'.format(
- script_path=script_path,
- func=func)
-
- print_utils.debug_print(cmd)
- return run_shell_command(cmd)
-
-def run_shell_command(cmd: str) -> Tuple[bool, str]:
- """Runs shell command with default timeout.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed) .
- """
- return execute_arbitrary_command([cmd],
- TIMEOUT,
- shell=True,
- simulate=SIMULATE)
-
-def execute_arbitrary_command(cmd: List[str],
- timeout: int,
- shell: bool,
- simulate: bool) -> Tuple[bool, str]:
- """Run arbitrary shell command with default timeout.
-
- Mostly copy from
- frameworks/base/startop/scripts/app_startup/app_startup_runner.py.
-
- Args:
- cmd: list of cmd strings.
- timeout: the time limit of running cmd.
- shell: indicate if the cmd is a shell command.
- simulate: if it's true, do not run the command and assume the running is
- successful.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed) .
- """
- if simulate:
- print(cmd)
- return True, ''
-
- print_utils.debug_print('[EXECUTE]', cmd)
- # block until either command finishes or the timeout occurs.
- loop = asyncio.get_event_loop()
-
- (return_code, script_output) = loop.run_until_complete(
- _run_command(*cmd, shell=shell, timeout=timeout))
-
- script_output = script_output.decode() # convert bytes to str
-
- passed = (return_code == 0)
- print_utils.debug_print('[$?]', return_code)
- if not passed:
- print('[FAILED, code:%s]' % (return_code), script_output, file=sys.stderr)
-
- return passed, script_output.rstrip()
-
-async def _run_command(*args: List[str],
- shell: bool = False,
- timeout: Optional[int] = None) -> Tuple[int, bytes]:
- if shell:
- process = await asyncio.create_subprocess_shell(
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
- else:
- process = await asyncio.create_subprocess_exec(
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
-
- script_output = b''
-
- print_utils.debug_print('[PID]', process.pid)
-
- timeout_remaining = timeout
- time_started = time.time()
-
- # read line (sequence of bytes ending with b'\n') asynchronously
- while True:
- try:
- line = await asyncio.wait_for(process.stdout.readline(),
- timeout_remaining)
- print_utils.debug_print('[STDOUT]', line)
- script_output += line
-
- if timeout_remaining:
- time_elapsed = time.time() - time_started
- timeout_remaining = timeout - time_elapsed
- except asyncio.TimeoutError:
- print_utils.debug_print('[TIMEDOUT] Process ', process.pid)
-
- print_utils.debug_print('[TIMEDOUT] Sending SIGTERM.')
- process.terminate()
-
- # 5 second timeout for process to handle SIGTERM nicely.
- try:
- (remaining_stdout,
- remaining_stderr) = await asyncio.wait_for(process.communicate(), 5)
- script_output += remaining_stdout
- except asyncio.TimeoutError:
- print_utils.debug_print('[TIMEDOUT] Sending SIGKILL.')
- process.kill()
-
- # 5 second timeout to finish with SIGKILL.
- try:
- (remaining_stdout,
- remaining_stderr) = await asyncio.wait_for(process.communicate(), 5)
- script_output += remaining_stdout
- except asyncio.TimeoutError:
- # give up, this will leave a zombie process.
- print_utils.debug_print('[TIMEDOUT] SIGKILL failed for process ',
- process.pid)
- time.sleep(100)
-
- return -1, script_output
- else:
- if not line: # EOF
- break
-
- code = await process.wait() # wait for child process to exit
- return code, script_output
diff --git a/startop/scripts/lib/logcat_utils.py b/startop/scripts/lib/logcat_utils.py
deleted file mode 100644
index 8a3d00b..0000000
--- a/startop/scripts/lib/logcat_utils.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-"""Helper util libraries for parsing logcat logs."""
-
-import asyncio
-import re
-from datetime import datetime
-from typing import Optional, Pattern
-
-# local import
-import lib.print_utils as print_utils
-
-def parse_logcat_datetime(timestamp: str) -> Optional[datetime]:
- """Parses the timestamp of logcat.
-
- Params:
- timestamp: for example "2019-07-01 16:13:55.221".
-
- Returns:
- a datetime of timestamp with the year now.
- """
- try:
- # Match the format of logcat. For example: "2019-07-01 16:13:55.221",
- # because it doesn't have year, set current year to it.
- timestamp = datetime.strptime(timestamp,
- '%Y-%m-%d %H:%M:%S.%f')
- return timestamp
- except ValueError as ve:
- print_utils.debug_print('Invalid line: ' + timestamp)
- return None
-
-def _is_time_out(timeout: datetime, line: str) -> bool:
- """Checks if the timestamp of this line exceeds the timeout.
-
- Returns:
- true if the timestamp exceeds the timeout.
- """
- # Get the timestampe string.
- cur_timestamp_str = ' '.join(re.split(r'\s+', line)[0:2])
- timestamp = parse_logcat_datetime(cur_timestamp_str)
- if not timestamp:
- return False
-
- return timestamp > timeout
-
-async def _blocking_wait_for_logcat_pattern(timestamp: datetime,
- pattern: Pattern,
- timeout: datetime) -> Optional[str]:
- # Show the year in the timestampe.
- logcat_cmd = 'adb logcat -v UTC -v year -v threadtime -T'.split()
- logcat_cmd.append(str(timestamp))
- print_utils.debug_print('[LOGCAT]:' + ' '.join(logcat_cmd))
-
- # Create subprocess
- process = await asyncio.create_subprocess_exec(
- *logcat_cmd,
- # stdout must a pipe to be accessible as process.stdout
- stdout=asyncio.subprocess.PIPE)
-
- while (True):
- # Read one line of output.
- data = await process.stdout.readline()
- line = data.decode('utf-8').rstrip()
-
- # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager: Displayed
- # com.android.settings/.Settings: +927ms
- # TODO: Detect timeouts even when there is no logcat output.
- if _is_time_out(timeout, line):
- print_utils.debug_print('DID TIMEOUT BEFORE SEEING ANYTHING ('
- 'timeout={timeout} seconds << {pattern} '
- '>>'.format(timeout=timeout, pattern=pattern))
- return None
-
- if pattern.match(line):
- print_utils.debug_print(
- 'WE DID SEE PATTERN << "{}" >>.'.format(pattern))
- return line
-
-def blocking_wait_for_logcat_pattern(timestamp: datetime,
- pattern: Pattern,
- timeout: datetime) -> Optional[str]:
- """Selects the line that matches the pattern and within the timeout.
-
- Returns:
- the line that matches the pattern and within the timeout.
- """
- loop = asyncio.get_event_loop()
- result = loop.run_until_complete(
- _blocking_wait_for_logcat_pattern(timestamp, pattern, timeout))
- return result
diff --git a/startop/scripts/lib/logcat_utils_test.py b/startop/scripts/lib/logcat_utils_test.py
deleted file mode 100644
index ab82515..0000000
--- a/startop/scripts/lib/logcat_utils_test.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-"""Unit tests for the logcat_utils.py script."""
-
-import asyncio
-import datetime
-import re
-
-import logcat_utils
-from mock import MagicMock, patch
-
-def test_parse_logcat_datatime():
- # Act
- result = logcat_utils.parse_logcat_datetime('2019-07-01 16:13:55.221')
-
- # Assert
- assert result == datetime.datetime(2019, 7, 1, 16, 13, 55, 221000)
-
-class AsyncMock(MagicMock):
- async def __call__(self, *args, **kwargs):
- return super(AsyncMock, self).__call__(*args, **kwargs)
-
-def _async_return():
- f = asyncio.Future()
- f.set_result(
- b'2019-07-01 15:51:53.290 27365 27392 I ActivityTaskManager: '
- b'Displayed com.google.android.music/com.android.music.activitymanagement.'
- b'TopLevelActivity: +1s7ms')
- return f
-
-def test_parse_displayed_time_succeed():
- # Act
- with patch('asyncio.create_subprocess_exec',
- new_callable=AsyncMock) as asyncio_mock:
- asyncio_mock.return_value.stdout.readline = _async_return
- timestamp = datetime.datetime(datetime.datetime.now().year, 7, 1, 16, 13,
- 55, 221000)
- timeout_dt = timestamp + datetime.timedelta(0, 10)
- pattern = re.compile('.*ActivityTaskManager: Displayed '
- 'com.google.android.music/com.android.music.*')
- result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_dt)
-
- # Assert
- assert result == '2019-07-01 15:51:53.290 27365 27392 I ' \
- 'ActivityTaskManager: ' \
- 'Displayed com.google.android.music/com.android.music.' \
- 'activitymanagement.TopLevelActivity: +1s7ms'
-
-def _async_timeout_return():
- f = asyncio.Future()
- f.set_result(
- b'2019-07-01 17:51:53.290 27365 27392 I ActivityTaskManager: '
- b'Displayed com.google.android.music/com.android.music.activitymanagement.'
- b'TopLevelActivity: +1s7ms')
- return f
-
-def test_parse_displayed_time_timeout():
- # Act
- with patch('asyncio.create_subprocess_exec',
- new_callable=AsyncMock) as asyncio_mock:
- asyncio_mock.return_value.stdout.readline = _async_timeout_return
- timestamp = datetime.datetime(datetime.datetime.now().year,
- 7, 1, 16, 13, 55, 221000)
- timeout_dt = timestamp + datetime.timedelta(0, 10)
- pattern = re.compile('.*ActivityTaskManager: Displayed '
- 'com.google.android.music/com.android.music.*')
- result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_dt)
-
- # Assert
- assert result == None
diff --git a/startop/scripts/lib/print_utils.py b/startop/scripts/lib/print_utils.py
deleted file mode 100644
index 8c5999d..0000000
--- a/startop/scripts/lib/print_utils.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-
-"""Helper util libraries for debug printing."""
-
-import sys
-
-DEBUG = False
-
-def debug_print(*args, **kwargs):
- """Prints the args to sys.stderr if the DEBUG is set."""
- if DEBUG:
- print(*args, **kwargs, file=sys.stderr)
-
-def error_print(*args, **kwargs):
- print('[ERROR]:', *args, file=sys.stderr, **kwargs)
-
-def _expand_gen_repr(args):
- """Like repr but any generator-like object has its iterator consumed
- and then called repr on."""
- new_args_list = []
- for i in args:
- # detect iterable objects that do not have their own override of __str__
- if hasattr(i, '__iter__'):
- to_str = getattr(i, '__str__')
- if to_str.__objclass__ == object:
- # the repr for a generator is just type+address, expand it out instead.
- new_args_list.append([_expand_gen_repr([j])[0] for j in i])
- continue
- # normal case: uses the built-in to-string
- new_args_list.append(i)
- return new_args_list
-
-def debug_print_gen(*args, **kwargs):
- """Like _debug_print but will turn any iterable args into a list."""
- if not DEBUG:
- return
-
- new_args_list = _expand_gen_repr(args)
- debug_print(*new_args_list, **kwargs)
-
-def debug_print_nd(*args, **kwargs):
- """Like _debug_print but will turn any NamedTuple-type args into a string."""
- if not DEBUG:
- return
-
- new_args_list = []
- for i in args:
- if hasattr(i, '_field_types'):
- new_args_list.append("%s: %s" % (i.__name__, i._field_types))
- else:
- new_args_list.append(i)
-
- debug_print(*new_args_list, **kwargs)
diff --git a/startop/scripts/trace_analyzer/lib/trace2db.py b/startop/scripts/trace_analyzer/lib/trace2db.py
deleted file mode 100644
index 42a33af..0000000
--- a/startop/scripts/trace_analyzer/lib/trace2db.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/python3
-# Copyright (C) 2019 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.
-
-import re
-import sys
-
-from sqlalchemy import create_engine
-from sqlalchemy import Column, Date, Integer, Float, String, ForeignKey
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import relationship
-
-from sqlalchemy.orm import sessionmaker
-
-import sqlalchemy
-
-from typing import Optional, Tuple
-
-_DEBUG = False # print sql commands to console
-_FLUSH_LIMIT = 10000 # how many entries are parsed before flushing to DB from memory
-
-Base = declarative_base()
-
-class RawFtraceEntry(Base):
- __tablename__ = 'raw_ftrace_entries'
-
- id = Column(Integer, primary_key=True)
- task_name = Column(String, nullable=True) # <...> -> None.
- task_pid = Column(String, nullable=False)
- tgid = Column(Integer, nullable=True) # ----- -> None.
- cpu = Column(Integer, nullable=False)
- timestamp = Column(Float, nullable=False)
- function = Column(String, nullable=False)
- function_args = Column(String, nullable=False)
-
- # 1:1 relation with MmFilemapAddToPageCache.
- mm_filemap_add_to_page_cache = relationship("MmFilemapAddToPageCache",
- back_populates="raw_ftrace_entry")
-
- @staticmethod
- def parse_dict(line):
- # ' <...>-5521 (-----) [003] ...1 17148.446877: tracing_mark_write: trace_event_clock_sync: parent_ts=17148.447266'
- m = re.match('\s*(.*)-(\d+)\s+\(([^\)]+)\)\s+\[(\d+)\]\s+([\w.]{4})\s+(\d+[.]\d+):\s+(\w+):\s+(.*)', line)
- if not m:
- return None
-
- groups = m.groups()
- # groups example:
- # ('<...>',
- # '5521',
- # '-----',
- # '003',
- # '...1',
- # '17148.446877',
- # 'tracing_mark_write',
- # 'trace_event_clock_sync: parent_ts=17148.447266')
- task_name = groups[0]
- if task_name == '<...>':
- task_name = None
-
- task_pid = int(groups[1])
- tgid = groups[2]
- if tgid == '-----':
- tgid = None
-
- cpu = int(groups[3])
- # irq_flags = groups[4]
- timestamp = float(groups[5])
- function = groups[6]
- function_args = groups[7]
-
- return {'task_name': task_name, 'task_pid': task_pid, 'tgid': tgid, 'cpu': cpu, 'timestamp': timestamp, 'function': function, 'function_args': function_args}
-
-class SchedSwitch(Base):
- __tablename__ = 'sched_switches'
-
- id = Column(Integer, ForeignKey('raw_ftrace_entries.id'), primary_key=True)
-
- prev_comm = Column(String, nullable=False)
- prev_pid = Column(Integer, nullable=False)
- prev_prio = Column(Integer, nullable=False)
- prev_state = Column(String, nullable=False)
-
- next_comm = Column(String, nullable=False)
- next_pid = Column(Integer, nullable=False)
- next_prio = Column(Integer, nullable=False)
-
- @staticmethod
- def parse_dict(function_args, id = None):
- # 'prev_comm=kworker/u16:5 prev_pid=13971 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120'
- m = re.match("prev_comm=(.*) prev_pid=(\d+) prev_prio=(\d+) prev_state=(.*) ==> next_comm=(.*) next_pid=(\d+) next_prio=(\d+) ?", function_args)
- if not m:
- return None
-
- groups = m.groups()
- # ('kworker/u16:5', '13971', '120', 'S', 'swapper/4', '0', '120')
- d = {}
- if id is not None:
- d['id'] = id
- d['prev_comm'] = groups[0]
- d['prev_pid'] = int(groups[1])
- d['prev_prio'] = int(groups[2])
- d['prev_state'] = groups[3]
- d['next_comm'] = groups[4]
- d['next_pid'] = int(groups[5])
- d['next_prio'] = int(groups[6])
-
- return d
-
-class SchedBlockedReason(Base):
- __tablename__ = 'sched_blocked_reasons'
-
- id = Column(Integer, ForeignKey('raw_ftrace_entries.id'), primary_key=True)
-
- pid = Column(Integer, nullable=False)
- iowait = Column(Integer, nullable=False)
- caller = Column(String, nullable=False)
-
- @staticmethod
- def parse_dict(function_args, id = None):
- # 'pid=2289 iowait=1 caller=wait_on_page_bit_common+0x2a8/0x5f'
- m = re.match("pid=(\d+) iowait=(\d+) caller=(.*) ?", function_args)
- if not m:
- return None
-
- groups = m.groups()
- # ('2289', '1', 'wait_on_page_bit_common+0x2a8/0x5f8')
- d = {}
- if id is not None:
- d['id'] = id
- d['pid'] = int(groups[0])
- d['iowait'] = int(groups[1])
- d['caller'] = groups[2]
-
- return d
-
-class MmFilemapAddToPageCache(Base):
- __tablename__ = 'mm_filemap_add_to_page_caches'
-
- id = Column(Integer, ForeignKey('raw_ftrace_entries.id'), primary_key=True)
-
- dev = Column(Integer, nullable=False) # decoded from ${major}:${minor} syntax.
- dev_major = Column(Integer, nullable=False) # original ${major} value.
- dev_minor = Column(Integer, nullable=False) # original ${minor} value.
-
- ino = Column(Integer, nullable=False) # decoded from hex to base 10
- page = Column(Integer, nullable=False) # decoded from hex to base 10
-
- pfn = Column(Integer, nullable=False)
- ofs = Column(Integer, nullable=False)
-
- # 1:1 relation with RawFtraceEntry.
- raw_ftrace_entry = relationship("RawFtraceEntry", uselist=False)
-
- @staticmethod
- def parse_dict(function_args, id = None):
- # dev 253:6 ino b2c7 page=00000000ec787cd9 pfn=1478539 ofs=4096
- m = re.match("dev (\d+):(\d+) ino ([0-9a-fA-F]+) page=([0-9a-fA-F]+) pfn=(\d+) ofs=(\d+)", function_args)
- if not m:
- return None
-
- groups = m.groups()
- # ('253', '6', 'b2c7', '00000000ec787cd9', '1478539', '4096')
- d = {}
- if id is not None:
- d['id'] = id
-
- device_major = d['dev_major'] = int(groups[0])
- device_minor = d['dev_minor'] = int(groups[1])
- d['dev'] = device_major << 8 | device_minor
- d['ino'] = int(groups[2], 16)
- d['page'] = int(groups[3], 16)
- d['pfn'] = int(groups[4])
- d['ofs'] = int(groups[5])
-
- return d
-
-class Trace2Db:
- def __init__(self, db_filename: str):
- (s, e) = self._init_sqlalchemy(db_filename)
- self._session = s
- self._engine = e
- self._raw_ftrace_entry_filter = lambda x: True
-
- def set_raw_ftrace_entry_filter(self, flt):
- """
- Install a function dict(RawFtraceEntry) -> bool
-
- If this returns 'false', then we skip adding the RawFtraceEntry to the database.
- """
- self._raw_ftrace_entry_filter = flt
-
- @staticmethod
- def _init_sqlalchemy(db_filename: str) -> Tuple[object, object]:
- global _DEBUG
- engine = create_engine('sqlite:///' + db_filename, echo=_DEBUG)
-
- # CREATE ... (tables)
- Base.metadata.create_all(engine)
-
- Session = sessionmaker(bind=engine)
- session = Session()
- return (session, engine)
-
- def parse_file_into_db(self, filename: str, limit: Optional[int] = None):
- """
- Parse the ftrace/systrace at 'filename',
- inserting the values into the current sqlite database.
-
- :return: number of RawFtraceEntry inserted.
- """
- return parse_file(filename, self._session, self._engine, self._raw_ftrace_entry_filter, limit)
-
- def parse_file_buf_into_db(self, file_buf, limit: Optional[int] = None):
- """
- Parse the ftrace/systrace at 'filename',
- inserting the values into the current sqlite database.
-
- :return: number of RawFtraceEntry inserted.
- """
- return parse_file_buf(file_buf, self._session, self._engine, self._raw_ftrace_entry_filter, limit)
-
-
- @property
- def session(self):
- return self._session
-
-def insert_pending_entries(engine, kls, lst):
- if len(lst) > 0:
- # for some reason, it tries to generate an empty INSERT statement with len=0,
- # which of course violates the first non-null constraint.
- try:
- # Performance-sensitive parsing according to:
- # https://docs.sqlalchemy.org/en/13/faq/performance.html#i-m-inserting-400-000-rows-with-the-orm-and-it-s-really-slow
- engine.execute(kls.__table__.insert(), lst)
- lst.clear()
- except sqlalchemy.exc.IntegrityError as err:
- # possibly violating some SQL constraint, print data here.
- print(err)
- print(lst)
- raise
-
-def parse_file(filename: str, *args, **kwargs) -> int:
- # use explicit encoding to avoid UnicodeDecodeError.
- with open(filename, encoding="ISO-8859-1") as f:
- return parse_file_buf(f, *args, **kwargs)
-
-def parse_file_buf(filebuf, session, engine, raw_ftrace_entry_filter, limit=None) -> int:
- global _FLUSH_LIMIT
- count = 0
- # count and id are not equal, because count still increases for invalid lines.
- id = 0
-
- pending_entries = []
- pending_sched_switch = []
- pending_sched_blocked_reasons = []
- pending_mm_filemap_add_to_pagecaches = []
-
- def insert_all_pending_entries():
- insert_pending_entries(engine, RawFtraceEntry, pending_entries)
- insert_pending_entries(engine, SchedSwitch, pending_sched_switch)
- insert_pending_entries(engine, SchedBlockedReason, pending_sched_blocked_reasons)
- insert_pending_entries(engine, MmFilemapAddToPageCache, pending_mm_filemap_add_to_pagecaches)
-
- # for trace.html files produced by systrace,
- # the actual ftrace is in the 'second' trace-data script class.
- parsing_trace_data = 0
- parsing_systrace_file = False
-
- f = filebuf
- for l in f:
- if parsing_trace_data == 0 and l == "<!DOCTYPE html>\n":
- parsing_systrace_file = True
- continue
- if parsing_trace_data != 2 and parsing_systrace_file:
- if l == ' <script class="trace-data" type="application/text">\n':
- parsing_trace_data = parsing_trace_data + 1
- continue
-
- if parsing_systrace_file and parsing_trace_data != 2:
- continue
- elif parsing_systrace_file and parsing_trace_data == 2 and l == " </script>\n":
- # the rest of this file is just random html
- break
-
- # now parsing the ftrace data.
- if len(l) > 1 and l[0] == '#':
- continue
-
- count = count + 1
-
- if limit and count >= limit:
- break
-
- raw_ftrace_entry = RawFtraceEntry.parse_dict(l)
- if not raw_ftrace_entry:
- print("WARNING: Failed to parse raw ftrace entry: " + l)
- continue
-
- if not raw_ftrace_entry_filter(raw_ftrace_entry):
- # Skip processing raw ftrace entries that don't match a filter.
- # This is an optimization for when Trace2Db is used programatically
- # to avoid having an overly large database.
- continue
-
- pending_entries.append(raw_ftrace_entry)
- id = id + 1
-
- if raw_ftrace_entry['function'] == 'sched_switch':
- sched_switch = SchedSwitch.parse_dict(raw_ftrace_entry['function_args'], id)
-
- if not sched_switch:
- print("WARNING: Failed to parse sched_switch: " + l)
- else:
- pending_sched_switch.append(sched_switch)
-
- elif raw_ftrace_entry['function'] == 'sched_blocked_reason':
- sbr = SchedBlockedReason.parse_dict(raw_ftrace_entry['function_args'], id)
-
- if not sbr:
- print("WARNING: Failed to parse sched_blocked_reason: " + l)
- else:
- pending_sched_blocked_reasons.append(sbr)
-
- elif raw_ftrace_entry['function'] == 'mm_filemap_add_to_page_cache':
- d = MmFilemapAddToPageCache.parse_dict(raw_ftrace_entry['function_args'],
- id)
- if not d:
- print("WARNING: Failed to parse mm_filemap_add_to_page_cache: " + l)
- else:
- pending_mm_filemap_add_to_pagecaches.append(d)
-
- # Objects are cached in python memory, not yet sent to SQL database.
-
- # Send INSERT/UPDATE/etc statements to the underlying SQL database.
- if count % _FLUSH_LIMIT == 0:
- insert_all_pending_entries()
-
- insert_all_pending_entries()
-
- # Ensure underlying database commits changes from memory to disk.
- session.commit()
-
- return count
diff --git a/startop/scripts/trace_analyzer/lib/trace2db_test.py b/startop/scripts/trace_analyzer/lib/trace2db_test.py
deleted file mode 100755
index 3b326f0..0000000
--- a/startop/scripts/trace_analyzer/lib/trace2db_test.py
+++ /dev/null
@@ -1,222 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-
-"""
-Unit tests for inode2filename module.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./inode2filename_test.py
- $> pytest inode2filename_test.py
- $> python -m pytest inode2filename_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-import io
-from copy import deepcopy
-
-# pip imports
-# local imports
-from trace2db import *
-
-# This pretty-prints the raw dictionary of the sqlalchemy object if it fails.
-class EqualsSqlAlchemyObject:
- # For convenience to write shorter tests, we also add 'ignore_fields' which allow us to specify
- # which fields to ignore when doing the comparison.
- def __init__(self_, self, ignore_fields=[]):
- self_.self = self
- self_.ignore_fields = ignore_fields
-
- # Do field-by-field comparison.
- # It seems that SQLAlchemy does not implement __eq__ itself so we have to do it ourselves.
- def __eq__(self_, other):
- if isinstance(other, EqualsSqlAlchemyObject):
- other = other.self
-
- self = self_.self
-
- classes_match = isinstance(other, self.__class__)
- a, b = deepcopy(self.__dict__), deepcopy(other.__dict__)
-
- #compare based on equality our attributes, ignoring SQLAlchemy internal stuff
-
- a.pop('_sa_instance_state', None)
- b.pop('_sa_instance_state', None)
-
- for f in self_.ignore_fields:
- a.pop(f, None)
- b.pop(f, None)
-
- attrs_match = (a == b)
- return classes_match and attrs_match
-
- def __repr__(self):
- return repr(self.self.__dict__)
-
-
-def assert_eq_ignore_id(left, right):
- # This pretty-prints the raw dictionary of the sqlalchemy object if it fails.
- # It does field-by-field comparison, but ignores the 'id' field.
- assert EqualsSqlAlchemyObject(left, ignore_fields=['id']) == EqualsSqlAlchemyObject(right)
-
-def parse_trace_file_to_db(*contents):
- """
- Make temporary in-memory sqlite3 database by parsing the string contents as a trace.
-
- :return: Trace2Db instance
- """
- buf = io.StringIO()
-
- for c in contents:
- buf.write(c)
- buf.write("\n")
-
- buf.seek(0)
-
- t2d = Trace2Db(":memory:")
- t2d.parse_file_buf_into_db(buf)
-
- buf.close()
-
- return t2d
-
-def test_ftrace_mm_filemap_add_to_pagecache():
- test_contents = """
-MediaStoreImpor-27212 (27176) [000] .... 16136.595194: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
-MediaStoreImpor-27212 (27176) [000] .... 16136.595920: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000048e2e156 pfn=677645 ofs=126976
-MediaStoreImpor-27212 (27176) [000] .... 16136.597793: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000051eabfb2 pfn=677644 ofs=122880
-MediaStoreImpor-27212 (27176) [000] .... 16136.597815: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000ce7cd606 pfn=677643 ofs=131072
-MediaStoreImpor-27212 (27176) [000] .... 16136.603732: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=000000008ffd3030 pfn=730119 ofs=186482688
-MediaStoreImpor-27212 (27176) [000] .... 16136.604126: mm_filemap_add_to_page_cache: dev 253:6 ino b1d8 page=0000000098d4d2e2 pfn=829676 ofs=0
- <...>-27197 (-----) [002] .... 16136.613471: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000aca88a97 pfn=743346 ofs=241664
- <...>-27197 (-----) [002] .... 16136.615979: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000351f2bc1 pfn=777799 ofs=106496
- <...>-27224 (-----) [006] .... 16137.400090: mm_filemap_add_to_page_cache: dev 253:6 ino 712d page=000000006ff7ffdb pfn=754861 ofs=0
- <...>-1396 (-----) [000] .... 16137.451660: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000ba0cbb34 pfn=769173 ofs=187191296
- <...>-1396 (-----) [000] .... 16137.453020: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000f6ef038e pfn=820291 ofs=0
- <...>-1396 (-----) [000] .... 16137.453067: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=0000000083ebc446 pfn=956463 ofs=4096
- <...>-1396 (-----) [000] .... 16137.453101: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000009dc2cd25 pfn=822813 ofs=8192
- <...>-1396 (-----) [000] .... 16137.453113: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000a11167fb pfn=928650 ofs=12288
- <...>-1396 (-----) [000] .... 16137.453126: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000c1c3311b pfn=621110 ofs=16384
- <...>-1396 (-----) [000] .... 16137.453139: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000009aa78342 pfn=689370 ofs=20480
- <...>-1396 (-----) [000] .... 16137.453151: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=0000000082cddcd6 pfn=755584 ofs=24576
- <...>-1396 (-----) [000] .... 16137.453162: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000b0249bc7 pfn=691431 ofs=28672
- <...>-1396 (-----) [000] .... 16137.453183: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000006a776ff0 pfn=795084 ofs=32768
- <...>-1396 (-----) [000] .... 16137.453203: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000001a4918a7 pfn=806998 ofs=36864
- <...>-2578 (-----) [002] .... 16137.561871: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000d65af9d2 pfn=719246 ofs=187015168
- <...>-2578 (-----) [002] .... 16137.562846: mm_filemap_add_to_page_cache: dev 253:6 ino b25a page=000000002f6ba74f pfn=864982 ofs=0
- <...>-2578 (-----) [000] .... 16138.104500: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000f888d0f6 pfn=805812 ofs=192794624
- <...>-2578 (-----) [000] .... 16138.105836: mm_filemap_add_to_page_cache: dev 253:6 ino b7dd page=000000003749523b pfn=977196 ofs=0
- <...>-27215 (-----) [001] .... 16138.256881: mm_filemap_add_to_page_cache: dev 253:6 ino 758f page=000000001b375de1 pfn=755928 ofs=0
- <...>-27215 (-----) [001] .... 16138.257526: mm_filemap_add_to_page_cache: dev 253:6 ino 7591 page=000000004e039481 pfn=841534 ofs=0
- NonUserFacing6-5246 ( 1322) [005] .... 16138.356491: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000d65af9d2 pfn=719246 ofs=161890304
- NonUserFacing6-5246 ( 1322) [005] .... 16138.357538: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000002f6ba74f pfn=864982 ofs=0
- NonUserFacing6-5246 ( 1322) [005] .... 16138.357581: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- <...>-27197 (-----) [005] .... 16140.143224: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000a42527c6 pfn=1076669 ofs=32768
- """
-
- t2d = parse_trace_file_to_db(test_contents)
- session = t2d.session
-
- first_row = session.query(MmFilemapAddToPageCache).order_by(MmFilemapAddToPageCache.id).first()
-
- #dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x7580, page=0x0000000060e990c7, pfn=677646, ofs=159744), first_row)
-
- second_to_last_row = session.query(MmFilemapAddToPageCache).filter(MmFilemapAddToPageCache.page.in_([0x000000006e0f8322])).first()
-
- # dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x9a64, page=0x000000006e0f8322, pfn=797894, ofs=4096), second_to_last_row)
-
-def test_systrace_mm_filemap_add_to_pagecache():
- test_contents = """
-<!DOCTYPE html>
-<html>
-<head i18n-values="dir:textdirection;">
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta charset="utf-8"/>
-<title>Android System Trace</title>
- <script class="trace-data" type="application/text">
-PROCESS DUMP
-USER PID PPID VSZ RSS WCHAN PC S NAME COMM
-root 1 0 62148 5976 0 0 S init [init]
-root 2 0 0 0 0 0 S [kthreadd] [kthreadd]
- </script>
-
- <script class="trace-data" type="application/text">
-MediaStoreImpor-27212 (27176) [000] .... 16136.595194: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
-NonUserFacing6-5246 ( 1322) [005] .... 16138.357581: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- </script>
-
- <script class="trace-data" type="application/text">
-{"traceEvents": [{"category": "process_argv", "name": "process_argv", "args": {"argv": ["/mnt/ssd3/workspace/master/external/chromium-trace/systrace.py", "-t", "5", "pagecache"]}, "pid": 160383, "ts": 1037300940509.7991, "tid": 139628672526080, "ph": "M"}, {"category": "python", "name": "clock_sync", "args": {"issue_ts": 1037307346185.212, "sync_id": "9a7e4fe3-89ad-441f-8226-8fe533fe973e"}, "pid": 160383, "ts": 1037307351643.906, "tid": 139628726089536, "ph": "c"}], "metadata": {"clock-domain": "SYSTRACE"}}
- </script>
-<!-- END TRACE -->
- """
-
- t2d = parse_trace_file_to_db(test_contents)
- session = t2d.session
-
- first_row = session.query(MmFilemapAddToPageCache).order_by(MmFilemapAddToPageCache.id).first()
-
- #dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x7580, page=0x0000000060e990c7, pfn=677646, ofs=159744), first_row)
-
- second_to_last_row = session.query(MmFilemapAddToPageCache).filter(MmFilemapAddToPageCache.page.in_([0x000000006e0f8322])).first()
-
- # dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x9a64, page=0x000000006e0f8322, pfn=797894, ofs=4096), second_to_last_row)
-
-def test_timestamp_filter():
- test_contents = """
- MediaStoreImpor-27212 (27176) [000] .... 16136.595194: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
- NonUserFacing6-5246 ( 1322) [005] .... 16139.357581: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- MediaStoreImpor-27212 (27176) [000] .... 16136.604126: mm_filemap_add_to_page_cache: dev 253:6 ino b1d8 page=0000000098d4d2e2 pfn=829676 ofs=0
- """
-
- t2d = parse_trace_file_to_db(test_contents)
- session = t2d.session
-
- end_time = 16137.0
-
- results = session.query(MmFilemapAddToPageCache).join(
- MmFilemapAddToPageCache.raw_ftrace_entry).filter(
- RawFtraceEntry.timestamp <= end_time).order_by(
- MmFilemapAddToPageCache.id).all()
-
- assert len(results) == 2
- assert_eq_ignore_id(
- MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x7580, page=0x0000000060e990c7, pfn=677646,
- ofs=159744), results[0])
- assert_eq_ignore_id(
- MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0xb1d8, page=0x0000000098d4d2e2, pfn=829676,
- ofs=0), results[1])
-
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/trace_analyzer/queries_all.sql b/startop/scripts/trace_analyzer/queries_all.sql
deleted file mode 100644
index 41d1c08..0000000
--- a/startop/scripts/trace_analyzer/queries_all.sql
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
--- filter for atrace writes
-CREATE VIEW IF NOT EXISTS tracing_mark_writes AS
- SELECT *
- FROM raw_ftrace_entries
- WHERE function = 'tracing_mark_write';
-
--- split the tracing_mark_write function args by ||s
-DROP TABLE IF exists tracing_mark_write_split_array;
-
-CREATE TABLE tracing_mark_write_split_array (
- predictorset_id INT REFERENCES raw_ftrace_entries (id),
- predictor_name,
- rest,
- gen,
-
- UNIQUE(predictorset_id, gen) -- drops redundant inserts into table
-);
-
-CREATE INDEX "tracing_mark_write_split_array_id" ON tracing_mark_write_split_array (
- predictorset_id COLLATE BINARY COLLATE BINARY
-);
-
-INSERT INTO tracing_mark_write_split_array
- WITH
- split(predictorset_id, predictor_name, rest, gen) AS (
- -- split by |
- SELECT id, '', function_args || '|', 0 FROM tracing_mark_writes WHERE id
- UNION ALL
- SELECT predictorset_id,
- substr(rest, 0, instr(rest, '|')),
- substr(rest, instr(rest, '|')+1),
- gen + 1
- FROM split
- WHERE rest <> ''),
- split_results AS (
- SELECT * FROM split WHERE predictor_name <> ''
- )
- SELECT * from split_results
-;
-
-
diff --git a/startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql b/startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql
deleted file mode 100644
index c28475e..0000000
--- a/startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
--- use the 'launching: $process_name' async slice to figure out launch duration.
-DROP VIEW IF EXISTS launch_durations_named;
-
-CREATE VIEW launch_durations_named AS
-WITH
- launch_traces_raw AS (
- SELECT *
- FROM tracing_mark_write_split AS tmw,
- raw_ftrace_entries AS rfe
- WHERE atrace_message LIKE 'launching: %' AND rfe.id = tmw.raw_ftrace_entry_id
- ),
- launch_traces_joined AS (
- SELECT started.timestamp AS started_timestamp,
- finished.timestamp AS finished_timestamp,
- started.id AS started_id,
- finished.id AS finished_id,
- SUBSTR(started.atrace_message, 12) AS proc_name -- crop out "launching: " from the string.
- FROM launch_traces_raw AS started,
- launch_traces_raw AS finished
- -- async slices ('S' -> 'F') have matching counters given the same PID.
- WHERE started.atrace_type == 'S'
- AND finished.atrace_type == 'F'
- AND started.atrace_count == finished.atrace_count
- AND started.atrace_pid == finished.atrace_pid
- )
-SELECT * from launch_traces_joined;
-
-SELECT * FROM launch_durations_named;
diff --git a/startop/scripts/trace_analyzer/queries_block_launch.sql b/startop/scripts/trace_analyzer/queries_block_launch.sql
deleted file mode 100644
index 34e5f03..0000000
--- a/startop/scripts/trace_analyzer/queries_block_launch.sql
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-DROP VIEW IF EXISTS blocked_iowait_for_app_launches;
-
-CREATE VIEW blocked_iowait_for_app_launches AS
-WITH
- block_launch_join AS (
- SELECT *
- FROM blocking_durations AS bd,
- launch_durations_named AS ld
- WHERE bd.block_timestamp >= ld.started_timestamp
- AND bd.unblock_timestamp <= ld.finished_timestamp
- ),
- blocked_ui_threads AS (
- SELECT *
- FROM start_process_ui_threads AS sp,
- block_launch_join AS blj
- WHERE sp.atm_ui_thread_tid == unblock_pid
- AND sp.process_name = blj.proc_name
- ),
- summed_raw AS (
- SELECT SUM(unblock_timestamp-block_timestamp)*1000 AS sum_block_duration_ms,
- *
- FROM blocked_ui_threads
- GROUP BY unblock_pid
- ),
- summed_neat AS (
- SELECT sum_block_duration_ms AS blocked_iowait_duration_ms,
- process_name,
- (finished_timestamp - started_timestamp) * 1000 AS launching_duration_ms,
- started_timestamp * 1000 AS launching_started_timestamp_ms,
- finished_timestamp * 1000 AS launching_finished_timestamp_ms
- -- filter out the rest because its just selecting 1 arbitrary row (due to the SUM aggregate).,
- FROM summed_raw
- )
-SELECT * FROM summed_neat;
-
-SELECT * FROM blocked_iowait_for_app_launches;
diff --git a/startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql b/startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql
deleted file mode 100644
index 788d0da..0000000
--- a/startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-DROP VIEW IF EXISTS sched_switch_iowaits_pre;
-
--- scan for the closest pair such that:
--- sched_block_reason pid=$PID iowait=1 ...
--- ...
--- sched_switch next_pid=$PID
-CREATE VIEW sched_switch_iowaits_pre AS
- SELECT MAX(sbr.id) AS blocked_id,
- ss.id AS sched_switch_id,
- pid, -- iow.pid
- iowait, -- iowait=0 or iowait=1
- caller,
- sbr_f.timestamp AS blocked_timestamp,
- ss_f.timestamp AS sched_switch_timestamp,
- next_comm, -- name of next_pid
- next_pid -- same as iow.pid
- FROM sched_blocked_reasons AS sbr,
- raw_ftrace_entries AS sbr_f,
- sched_switches AS ss,
- raw_ftrace_entries AS ss_f
- WHERE sbr_f.id == sbr.id
- AND ss_f.id == ss.id
- AND sbr.pid == ss.next_pid
- AND sbr.iowait = 1
- AND sbr_f.timestamp < ss_f.timestamp -- ensures the 'closest' sched_blocked_reason is selected.
- GROUP BY ss.id
-;
-
-DROP VIEW IF EXISTS sched_switch_iowaits;
-
-CREATE VIEW sched_switch_iowaits AS
- SELECT *, MIN(sched_switch_timestamp) AS ss_timestamp -- drop all of the 'too large' sched_switch entries except the closest one.
- FROM sched_switch_iowaits_pre
- GROUP BY blocked_id;
-
-SELECT * FROM sched_switch_iowaits;
-
--- use a real table here instead of a view, otherwise SQLiteStudio segfaults for some reason.
-DROP TABLE IF EXISTS blocking_durations;
-
-CREATE TABLE blocking_durations AS
-WITH
- blocking_durations_raw AS (
- SELECT MAX(ss.id) AS block_id,
- ssf.timestamp AS block_timestamp,
- iow.sched_switch_timestamp AS unblock_timestamp,
- ss.prev_comm as block_prev_comm,
- iow.next_comm AS unblock_next_comm,
- ss.prev_state AS block_prev_state,
- iow.sched_switch_id AS unblock_id,
- iow.pid AS unblock_pid,
- iow.caller AS unblock_caller
- FROM sched_switches AS ss, -- this is the sched_switch that caused a block (in the future when it unblocks, the reason is iowait=1).
- sched_switch_iowaits AS iow, -- this is the sched_switch that removes the block (it is now running again).
- raw_ftrace_entries AS ssf
- WHERE ssf.id = ss.id AND ss.prev_pid == iow.next_pid AND ssf.timestamp < iow.sched_switch_timestamp
- GROUP BY unblock_timestamp
- ),
- blocking_durations_tmp AS (
- SELECT block_id,
- unblock_timestamp,
- block_timestamp,
- block_prev_comm as comm,
- block_prev_state as block_state,
- unblock_id,
- unblock_pid,
- unblock_caller
- FROM blocking_durations_raw
- )
- SELECT * FROM blocking_durations_tmp;-- ORDER BY block_id ASC;
- --SELECT SUM(block_duration_ms) AS sum, * FROM blocking_durations GROUP BY unblock_pid ORDER BY sum DESC;
-
-DROP INDEX IF EXISTS "blocking_durations_block_timestamp";
-
-CREATE INDEX "blocking_durations_block_timestamp" ON blocking_durations (
- block_timestamp COLLATE BINARY COLLATE BINARY
-);
-
-DROP INDEX IF EXISTS "blocking_durations_unblock_timestamp";
-
-CREATE INDEX "blocking_durations_unblock_timestamp" ON blocking_durations (
- unblock_timestamp COLLATE BINARY COLLATE BINARY
-);
-
-SELECT * FROM blocking_durations;
diff --git a/startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql b/startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql
deleted file mode 100644
index 0c166b0..0000000
--- a/startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-DROP VIEW IF EXISTS sched_switch_next_comm_pids;
-
-CREATE VIEW IF NOT EXISTS sched_switch_next_comm_pids AS
-
--- TODO: switch to using sched_switches table.
-
-WITH
- sched_switchs AS (
- SELECT * FROM raw_ftrace_entries WHERE function = 'sched_switch' AND function_args LIKE '% next_pid=%' AND function_args NOT LIKE '% next_comm=main %'
- ),
- comm_and_pids_raws AS (
- SELECT id,
- SUBSTR(function_args, instr(function_args, "next_comm="), instr(function_args, "next_pid=") - instr(function_args, "next_comm=")) AS next_comm_raw,
- SUBSTR(function_args, instr(function_args, "next_pid="), instr(function_args, "next_prio=") - instr(function_args, "next_pid=")) AS next_pid_raw
- FROM sched_switchs
- ),
- comm_and_pids AS (
- SELECT id,
- id AS raw_ftrace_entry_id,
- TRIM(SUBSTR(next_pid_raw, 10)) AS next_pid, -- len("next_pid=") is 10
- TRIM(SUBSTR(next_comm_raw, 11)) AS next_comm -- len("next_comm=") is 11
- FROM comm_and_pids_raws
- )
-SELECT * from comm_and_pids;
-
-SELECT * from sched_switch_next_comm_pids;
diff --git a/startop/scripts/trace_analyzer/queries_get_procs.sql b/startop/scripts/trace_analyzer/queries_get_procs.sql
deleted file mode 100644
index 06871c6..0000000
--- a/startop/scripts/trace_analyzer/queries_get_procs.sql
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-DROP VIEW IF EXISTS start_procs;
-
-CREATE VIEW IF NOT EXISTS start_procs AS
-WITH
- start_procs_raw AS (
- SELECT * from tracing_mark_write_split WHERE atrace_message LIKE 'Start proc: %'
- ),
- start_procs_substr AS (
- -- note: "12" is len("Start proc: ")+1. sqlite indices start at 1.
- SELECT raw_ftrace_entry_id, atrace_pid, SUBSTR(atrace_message, 13) AS process_name FROM start_procs_raw
- )
-SELECT * from start_procs_substr;
-
-SELECT * from start_procs;
diff --git a/startop/scripts/trace_analyzer/queries_get_ui_threads.sql b/startop/scripts/trace_analyzer/queries_get_ui_threads.sql
deleted file mode 100644
index 876e50e..0000000
--- a/startop/scripts/trace_analyzer/queries_get_ui_threads.sql
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
--- note: These queries do comparisons based on raw_ftrace_entries.id by treating it as if it was equivalent to the temporal timestamp.
--- in practice, the ID of raw_ftrace_entries is based on its order in the ftrace buffer [and on the same cpu its equivalent].
--- we can always resort raw_ftrace_entries to ensure id order matches timestamp order. We should rarely need to compare by timestamp directly.
--- accessing 'floats' is inferior as they are harder to index, and will result in slower queries.
---
--- Naming convention note: '_fid' corresponds to 'raw_ftrace_entry.id'.
-DROP VIEW IF EXISTS start_process_ui_threads;
-
--- Map of started process names to their UI thread's TID (as returned by gettid).
-CREATE VIEW IF NOT EXISTS start_process_ui_threads AS
-WITH
- start_proc_tids AS (
- SELECT sp.raw_ftrace_entry_id AS start_proc_fid,
- sp.atrace_pid AS atrace_pid,
- sp.process_name AS process_name,
- --MIN(nc.raw_ftrace_entry_id) as next_comm_fid,
- nc.raw_ftrace_entry_id AS next_comm_fid,
- nc.next_pid as next_pid,
- nc.next_comm as next_comm,
- SUBSTR(sp.process_name, -15) AS cut -- why -15? See TASK_MAX in kernel, the sched_switch name is truncated to 16 bytes.
- FROM start_procs AS sp,
- sched_switch_next_comm_pids AS nc
- WHERE sp.process_name LIKE '%' || nc.next_comm -- kernel truncates the sched_switch::next_comm event, so we must match the prefix of the full name.
- --WHERE SUBSTR(sp.process_name, -16) == nc.next_comm
- --WHERE cut == nc.next_comm
- ),
- start_proc_tids_filtered AS (
- SELECT *
- FROM start_proc_tids
- WHERE next_comm_fid > start_proc_fid -- safeguard that avoids choosing "earlier" sched_switch before process was even started.
- --ORDER BY start_proc_fid, next_comm_fid
- ),
- start_proc_all_threads AS (
- SELECT DISTINCT
- start_proc_fid, -- this is the ftrace entry of the system server 'Start proc: $process_name'. only need this to join for timestamp.
- process_name, -- this is the '$process_name' from the system server entry.
- -- next up we have all the possible thread IDs as parsed from sched_switch that corresponds most closest to the start proc.
- next_pid AS ui_thread_tpid, -- sched_switch.next_pid. This can be any of the threads in that process, it's not necessarily the main UI thread yet.
- next_comm,
- MIN(next_comm_fid) AS next_comm_fid -- don't pick the 'later' next_comm_fid because it could correspond to another app start.
- FROM start_proc_tids_filtered
- GROUP BY start_proc_fid, ui_thread_tpid
- ),
- activity_thread_mains AS (
- SELECT * FROM tracing_mark_write_split WHERE atrace_message = 'ActivityThreadMain'
- ),
- start_proc_ui_threads AS (
- SELECT start_proc_fid,
- process_name,
- ui_thread_tpid,
- next_comm,
- next_comm_fid,
- atm.raw_ftrace_entry_id as atm_fid,
- atm.atrace_pid as atm_ui_thread_tid
- FROM start_proc_all_threads AS spt,
- activity_thread_mains AS atm
- WHERE atm.atrace_pid == spt.ui_thread_tpid AND atm.raw_ftrace_entry_id > spt.start_proc_fid -- Ensure we ignore earlier ActivityThreadMains prior to their Start proc.
- ),
- start_proc_ui_threads_filtered AS (
- SELECT start_proc_fid,
- process_name, -- e.g. 'com.android.settings'
- --ui_thread_tpid,
- --next_comm,
- --next_comm_fid,
- MIN(atm_fid) AS atm_fid,
- atm_ui_thread_tid -- equivalent to gettid() for the process's UI thread.
- FROM start_proc_ui_threads
- GROUP BY start_proc_fid, atm_ui_thread_tid -- find the temporally closest ActivityTaskMain to a "Start proc: $process_name"
- )
-SELECT * FROM start_proc_ui_threads_filtered;
-
-SELECT * FROM start_process_ui_threads;
diff --git a/startop/scripts/trace_analyzer/queries_mark_write_join.sql b/startop/scripts/trace_analyzer/queries_mark_write_join.sql
deleted file mode 100644
index 100f0740..0000000
--- a/startop/scripts/trace_analyzer/queries_mark_write_join.sql
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-DROP TABLE IF EXISTS tracing_mark_write_split;
-
-CREATE TABLE tracing_mark_write_split (
- raw_ftrace_entry_id INT REFERENCES raw_ftrace_entries (id),
- atrace_type CHAR(1), -- only null for the first 2 sync timers. usually 'B', 'C', E', ...
- atrace_pid INT, -- only null for first 2 sync timers
- atrace_message, -- usually null for type='E' etc.
- atrace_count, -- usually non-null only for 'C'
-
- UNIQUE(raw_ftrace_entry_id) -- drops redundant inserts into table
-);
-
-INSERT INTO tracing_mark_write_split
-WITH
- pivoted AS (
- SELECT tx.predictorset_id,
- --ty.predictorset_id,
- --tz.predictorset_id,
- --tzz.predictorset_id,
- tx.predictor_name AS atrace_type,
- CAST(ty.predictor_name AS integer) AS atrace_pid,
- tz.predictor_name AS atrace_message,
- CAST(tzz.predictor_name AS integer) AS atrace_count
- FROM (SELECT * from tracing_mark_write_split_array WHERE gen = 1) AS tx
- LEFT JOIN
- (SELECT * FROM tracing_mark_write_split_array WHERE gen = 2) AS ty
- ON tx.predictorset_id = ty.predictorset_id
- LEFT JOIN
- (SELECT * FROM tracing_mark_write_split_array WHERE gen = 3) AS tz
- ON tx.predictorset_id = tz.predictorset_id
- LEFT JOIN
- (SELECT * FROM tracing_mark_write_split_array WHERE gen = 4) AS tzz
- ON tx.predictorset_id = tzz.predictorset_id
- )
-SELECT * from pivoted ORDER BY predictorset_id;-- LIMIT 100;
-
-SELECT * FROM tracing_mark_write_split;
diff --git a/startop/scripts/trace_analyzer/queries_pretty_print_block_launch.sql b/startop/scripts/trace_analyzer/queries_pretty_print_block_launch.sql
deleted file mode 100644
index bf5e3cc..0000000
--- a/startop/scripts/trace_analyzer/queries_pretty_print_block_launch.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-.headers on
-.mode quote
-
-SELECT * FROM blocked_iowait_for_app_launches;
-
-/*
-Output as CSV example:
-
-'blocked_iowait_duration_ms','process_name','launching_duration_ms','launching_started_timestamp_ms','launching_finished_timestamp_ms'
-125.33199995596078224,'com.android.settings',1022.4840000009862706,17149896.822000000626,17150919.305999998003
-
-*/
diff --git a/startop/scripts/trace_analyzer/run-sql-queries b/startop/scripts/trace_analyzer/run-sql-queries
deleted file mode 100755
index 61a0ad4..0000000
--- a/startop/scripts/trace_analyzer/run-sql-queries
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-DIR="$( cd "$(dirname "$0")" ; pwd -P )"
-
-if [[ $# -lt 1 ]]; then
- echo "Usage: $0 <db-file>"
-fi
-
-DB_TARGET=$1
-
-if ! [[ -f $DB_TARGET ]]; then
- echo "ERROR: File '$DB_TARGET' does not exist." >&2
- exit 1
-fi
-
-exec_sql_file() {
- local filename="$1"
- if ! [[ -f $filename ]]; then
- echo "ERROR: Can't exec SQL file, '$filename' does not exist." >&2
- return 1
- fi
-
- sqlite3 "$DB_TARGET" < "$DIR"/"$filename"
-}
-
-exec_sql_file_quiet() {
- exec_sql_file "$@" > /dev/null
-}
-
-# Some views/tables need other views already created, so order does matter.
-# x -> y , means x depends on y.
-
-# View: tracing_mark_writes
-# Table: tracing_mark_write_split_array -> tracing_mark_writes
-exec_sql_file_quiet "queries_all.sql"
-
-# Table: tracing_mark_write_split -> tracing_mark_write_split_array
-exec_sql_file_quiet "queries_mark_write_join.sql"
-
-# View: start_procs -> tracing_mark_write_split
-exec_sql_file_quiet "queries_get_procs.sql"
-
-# View: sched_switch_next_comm_pids
-exec_sql_file_quiet "queries_get_comm_and_pids.sql"
-
-# View: start_process_ui_threads -> start_procs, sched_switch_next_comm_pids
-exec_sql_file_quiet "queries_get_ui_threads.sql"
-
-# View: launch_durations_named -> tracing_mark_write_split
-exec_sql_file_quiet "queries_app_launch_spans_with_name.sql"
-
-# View: sched_switch_iowaits_pre
-# View: sched_switch_iowaits -> sched_switch_iowaits_pre
-# Table: blocking_durations -> sched_switch_iowaits
-exec_sql_file_quiet "queries_find_sched_switch_unblocked.sql"
-
-# View: blocked_iowait_for_app_launches -> launch_durations_named, blocking_durations
-exec_sql_file_quiet "queries_block_launch.sql"
-
-#####
-#####
-#####
-
-# Final queries
-
-exec_sql_file "queries_pretty_print_block_launch.sql"
diff --git a/startop/scripts/trace_analyzer/test_fixtures/common_systrace b/startop/scripts/trace_analyzer/test_fixtures/common_systrace
deleted file mode 100644
index 802cb55..0000000
--- a/startop/scripts/trace_analyzer/test_fixtures/common_systrace
+++ /dev/null
@@ -1,518 +0,0 @@
-# tracer: nop
-#
-# entries-in-buffer/entries-written: 411983/411983 #P:8
-#
-# _-----=> irqs-off
-# / _----=> need-resched
-# | / _---=> hardirq/softirq
-# || / _--=> preempt-depth
-# ||| / delay
-# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION
-# | | | | |||| | |
- <...>-14603 (-----) [000] ...1 14592.893157: tracing_mark_write: trace_event_clock_sync: parent_ts=14592.892578
- <...>-14603 (-----) [000] ...1 14592.893172: tracing_mark_write: trace_event_clock_sync: realtime_ts=1557129597951
- <...>-18150 (-----) [004] d..2 14594.182110: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=kworker/u16:16 next_pid=23269 next_prio=120
- kworker/u16:16-23269 (23269) [004] d.h3 14594.182228: sched_blocked_reason: pid=18150 iowait=0 caller=a6xx_oob_set+0x194/0x3dc
- kworker/u16:16-23269 (23269) [004] d..2 14594.182248: sched_switch: prev_comm=kworker/u16:16 prev_pid=23269 prev_prio=120 prev_state=D ==> next_comm=kworker/u16:18 next_pid=18150 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182312: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182488: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- kworker/u16:16-23269 (23269) [005] d..2 14594.182610: sched_switch: prev_comm=kworker/u16:16 prev_pid=23269 prev_prio=120 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182626: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182755: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182975: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.183209: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.183371: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.184286: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120
- kworker/u16:16-23269 (23269) [005] d..2 14594.184495: sched_switch: prev_comm=kworker/u16:16 prev_pid=23269 prev_prio=120 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.184498: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120
- ksoftirqd/4-47 ( 47) [004] d..2 14594.185678: sched_switch: prev_comm=ksoftirqd/4 prev_pid=47 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120
- kworker/6:2-10610 (10610) [006] d..2 14594.186012: sched_switch: prev_comm=kworker/6:2 prev_pid=10610 prev_prio=120 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-656 (-----) [001] .... 14594.219464: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-1803 (-----) [000] d..2 14594.219595: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-3359 (-----) [001] ...1 14594.219856: tracing_mark_write: S|1368|launching: com.google.android.dialer|0
- <...>-3359 (-----) [001] ...1 14594.219863: tracing_mark_write: B|1368|MetricsLogger:launchObserverNotifyActivityLaunched
- <...>-3359 (-----) [001] ...1 14594.219869: tracing_mark_write: B|1368|MetricsLogger:convertActivityRecordToProto
- <...>-1398 (-----) [006] ...1 14594.220160: tracing_mark_write: B|1368|updateInputWindows
- <...>-3359 (-----) [001] .... 14594.220230: binder_set_priority: proc=1368 thread=3359 old=110 => new=120 desired=120
- <...>-1398 (-----) [006] ...1 14594.220588: tracing_mark_write: B|1368|android.os.Handler: com.android.server.wm.AppWindowToken$1
- <...>-1398 (-----) [006] ...1 14594.220722: tracing_mark_write: B|1368|ResourcesManager#getResources
- <...>-1052 (-----) [002] d..2 14594.220884: sched_switch: prev_comm=statsd.writer prev_pid=1052 prev_prio=120 prev_state=S ==> next_comm=UiThreadHelper next_pid=2045 next_prio=118
- <...>-1398 (-----) [006] ...1 14594.220926: tracing_mark_write: B|1368|Theme::ApplyStyle
- <...>-1398 (-----) [006] ...1 14594.220929: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-2007 (-----) [007] ...1 14594.220996: tracing_mark_write: B|2007|Choreographer#doFrame
- <...>-2007 (-----) [007] ...1 14594.221005: tracing_mark_write: B|2007|animation
- <...>-1398 (-----) [006] ...1 14594.221015: tracing_mark_write: B|1368|ResourcesManager#getResources
- <...>-2045 (-----) [002] ...2 14594.221035: binder_set_priority: proc=1368 thread=1903 old=120 => new=118 desired=118
- <...>-2045 (-----) [002] d..2 14594.221065: sched_switch: prev_comm=UiThreadHelper prev_pid=2045 prev_prio=118 prev_state=S ==> next_comm=Binder:1368_4 next_pid=1903 next_prio=118
- <...>-1398 (-----) [006] ...1 14594.221080: tracing_mark_write: B|1368|AssetManager::SetApkAssets
- <...>-2007 (-----) [007] ...1 14594.221110: tracing_mark_write: B|2007|traversal
- <...>-656 (-----) [000] ...1 14594.221137: tracing_mark_write: B|625|requestNextVsync
- <...>-656 (-----) [000] ...1 14594.221141: tracing_mark_write: B|625|resetIdleTimer
- <...>-2007 (-----) [007] ...1 14594.221146: tracing_mark_write: B|2007|draw
- <...>-2007 (-----) [007] ...1 14594.221160: tracing_mark_write: B|2007|Record View#draw()
- <...>-660 (-----) [005] d..2 14594.221285: sched_switch: prev_comm=app prev_pid=660 prev_prio=97 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-658 (-----) [004] d..2 14594.221327: sched_switch: prev_comm=DispSync prev_pid=658 prev_prio=97 prev_state=S ==> next_comm=android.display next_pid=1397 next_prio=117
- <...>-2738 (-----) [005] ...1 14594.221342: tracing_mark_write: B|2007|notifyFramePending
- <...>-2738 (-----) [005] ...1 14594.221362: tracing_mark_write: B|2007|DrawFrame
- <...>-2738 (-----) [005] ...1 14594.221369: tracing_mark_write: B|2007|query
- <...>-2007 (-----) [007] d..2 14594.221369: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-1903 (-----) [002] .... 14594.221397: binder_set_priority: proc=1368 thread=1903 old=118 => new=120 desired=120
- <...>-2738 (-----) [005] ...2 14594.221400: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [005] d..2 14594.221430: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-1368 (-----) [003] ...1 14594.221431: tracing_mark_write: B|1368|Lock contention on GC thread flip lock (owner tid: 0)
- <...>-656 (-----) [005] ...1 14594.221460: tracing_mark_write: B|625|query
- <...>-656 (-----) [005] .... 14594.221528: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-2738 (-----) [007] ...1 14594.221552: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...2 14594.221563: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [007] d..2 14594.221600: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-1368 (-----) [003] d..2 14594.221623: sched_switch: prev_comm=system_server prev_pid=1368 prev_prio=118 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
- <...>-656 (-----) [007] ...1 14594.221628: tracing_mark_write: B|625|query
- <...>-23031 (-----) [001] d..2 14594.221643: sched_switch: prev_comm=UiAutomation prev_pid=23031 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [007] ...1 14594.221664: tracing_mark_write: B|2007|syncFrameState
- <...>-2738 (-----) [007] ...1 14594.221697: tracing_mark_write: B|2007|prepareTree
- <...>-23008 (-----) [005] d..2 14594.221706: sched_switch: prev_comm=hub.uiautomator prev_pid=23008 prev_prio=120 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-656 (-----) [000] .... 14594.221737: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-1803 (-----) [003] d..2 14594.221747: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
- <...>-1397 (-----) [004] d..2 14594.221806: sched_switch: prev_comm=android.display prev_pid=1397 prev_prio=117 prev_state=S ==> next_comm=Binder:2007_A next_pid=4180 next_prio=120
- <...>-1398 (-----) [006] d..2 14594.221816: sched_switch: prev_comm=android.anim prev_pid=1398 prev_prio=110 prev_state=R ==> next_comm=s.nexuslauncher next_pid=2007 next_prio=110
- <...>-2738 (-----) [007] ...1 14594.221824: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221830: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221834: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221841: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221843: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221846: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221850: tracing_mark_write: B|2007|dequeueBuffer
- <...>-2738 (-----) [007] ...2 14594.221864: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [007] d..2 14594.221985: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=crtc_event:97 next_pid=303 next_prio=83
- <...>-2007 (-----) [006] ...1 14594.221989: tracing_mark_write: B|2007|topResumedActivityChangeItem
- <...>-303 (-----) [007] d..2 14594.222016: sched_switch: prev_comm=crtc_event:97 prev_pid=303 prev_prio=83 prev_state=S ==> next_comm=rcu_preempt next_pid=7 next_prio=120
- rcu_preempt-7 ( 7) [007] d..2 14594.222035: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=120 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- migration/4-46 ( 46) [004] d..2 14594.222037: sched_switch: prev_comm=migration/4 prev_pid=46 prev_prio=0 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-2738 (-----) [007] d..2 14594.222039: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=kworker/u16:18 next_pid=18150 next_prio=120
- <...>-656 (-----) [004] ...1 14594.222100: tracing_mark_write: B|625|dequeueBuffer
- <...>-656 (-----) [004] ...1 14594.222114: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-2007 (-----) [006] ...2 14594.222131: binder_set_priority: proc=1368 thread=1903 old=120 => new=110 desired=110
- <...>-2007 (-----) [006] d..2 14594.222143: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=UiThreadHelper next_pid=2045 next_prio=118
- <...>-2613 (-----) [001] d..2 14594.222158: sched_switch: prev_comm=ogle.android.as prev_pid=2613 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-18150 (-----) [007] d..2 14594.222193: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-656 (-----) [004] .... 14594.222220: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-2738 (-----) [007] ...1 14594.222267: tracing_mark_write: B|2007|HWC release fence 36027 has signaled
- <...>-656 (-----) [007] ...1 14594.223842: tracing_mark_write: B|625|queueBuffer
- <...>-656 (-----) [007] ...1 14594.223845: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-656 (-----) [007] ...1 14594.223871: tracing_mark_write: B|625|requestNextVsync
- <...>-656 (-----) [007] ...1 14594.223873: tracing_mark_write: B|625|resetIdleTimer
- <...>-656 (-----) [007] ...1 14594.223881: tracing_mark_write: B|625|addAndGetFrameTimestamps
- <...>-1395 (-----) [001] d..2 14594.223909: sched_switch: prev_comm=android.ui prev_pid=1395 prev_prio=118 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [007] ...1 14594.223959: tracing_mark_write: B|2007|Trace GPU completion fence 36027
- <...>-11799 (-----) [006] ...1 14594.224006: tracing_mark_write: B|2007|waiting for GPU completion 36027
- <...>-11799 (-----) [006] ...1 14594.224009: tracing_mark_write: B|2007|waitForever
- <...>-2613 (-----) [004] d..2 14594.224014: sched_switch: prev_comm=ogle.android.as prev_pid=2613 prev_prio=120 prev_state=S ==> next_comm=Binder:1803_6 next_pid=2173 next_prio=120
- <...>-11799 (-----) [006] d..1 14594.224014: fence_enable_signal: driver=kgsl-timeline timeline=kgsl-3d0_13-s.nexuslauncher(200 context=27 seqno=78002
- <...>-11799 (-----) [006] d..2 14594.224021: sched_switch: prev_comm=GPU completion prev_pid=11799 prev_prio=110 prev_state=S ==> next_comm=rcuop/6 next_pid=68 next_prio=120
- rcuop/6-68 ( 68) [006] d..2 14594.224044: sched_switch: prev_comm=rcuop/6 prev_pid=68 prev_prio=120 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-259 (-----) [006] d..2 14594.224132: sched_switch: prev_comm=kgsl_worker_thr prev_pid=259 prev_prio=97 prev_state=S ==> next_comm=Binder:2007_A next_pid=4180 next_prio=120
- <...>-3206 (-----) [001] d..2 14594.224167: sched_switch: prev_comm=aiai-vc-0 prev_pid=3206 prev_prio=139 prev_state=R ==> next_comm=ndroid.systemui next_pid=1803 next_prio=120
- lowpool[847]-14589 ( 2446) [005] d..1 14594.224300: mm_filemap_delete_from_page_cache: dev 0:1 ino 3d0034 page=000000008247d586 pfn=676904 ofs=0
- <...>-1803 (-----) [001] d..2 14594.224302: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=aiai-vc-0 next_pid=3206 next_prio=139
- <...>-3206 (-----) [001] d..2 14594.224433: sched_switch: prev_comm=aiai-vc-0 prev_pid=3206 prev_prio=139 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-1903 (-----) [003] ...1 14594.224490: tracing_mark_write: B|1368|dispatchingStartProcess:com.google.android.dialer
- <...>-1903 (-----) [003] ...1 14594.224659: tracing_mark_write: B|1368|wmLayout
- <...>-1903 (-----) [003] ...1 14594.224666: tracing_mark_write: B|1368|performSurfacePlacement
- <...>-1903 (-----) [003] ...1 14594.224683: tracing_mark_write: B|1368|applySurfaceChanges
- <...>-1903 (-----) [003] ...1 14594.224688: tracing_mark_write: B|1368|openSurfaceTransaction
- <...>-2738 (-----) [007] ...1 14594.224711: tracing_mark_write: B|2007|query
- <...>-1903 (-----) [003] ...1 14594.224714: tracing_mark_write: B|1368|performLayout
- <...>-2738 (-----) [007] ...1 14594.224714: tracing_mark_write: B|2007|query
- <...>-1903 (-----) [003] ...1 14594.224723: tracing_mark_write: B|1368|applyPostLayoutPolicy
- <...>-2738 (-----) [007] d..2 14594.224752: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-656 (-----) [007] .... 14594.224766: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-1398 (-----) [002] ...1 14594.224801: tracing_mark_write: B|1368|Theme::ApplyStyle
- <...>-1398 (-----) [002] ...1 14594.224805: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224820: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224826: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224833: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224838: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224846: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224853: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224859: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224864: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-18150 (-----) [006] d..2 14594.228407: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=R+ ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-2738 (-----) [007] d..2 14594.228411: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=kworker/7:0H next_pid=76 next_prio=100
- <...>-1409 (-----) [004] ...1 14594.228417: tracing_mark_write: B|1368|Start proc: com.google.android.dialer
- <...>-440 (-----) [006] d..2 14594.228418: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=kworker/u16:18 next_pid=18150 next_prio=120
- <...>-76 (-----) [007] d..2 14594.228430: sched_switch: prev_comm=kworker/7:0H prev_pid=76 prev_prio=100 prev_state=R+ ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-440 (-----) [007] d..2 14594.228434: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=kworker/7:0H next_pid=76 next_prio=100
- <...>-18150 (-----) [006] d..3 14594.228442: sched_blocked_reason: pid=1398 iowait=1 caller=wait_on_page_bit_common+0x2a8/0x5f8
- <...>-76 (-----) [007] d..2 14594.228442: sched_switch: prev_comm=kworker/7:0H prev_pid=76 prev_prio=100 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-2738 (-----) [007] ...2 14594.228446: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-18150 (-----) [006] d..2 14594.228447: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=R+ ==> next_comm=android.anim next_pid=1398 next_prio=110
- <...>-2738 (-----) [007] d..2 14594.228479: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-1409 (-----) [004] d..2 14594.228499: sched_switch: prev_comm=ActivityManager prev_pid=1409 prev_prio=118 prev_state=D ==> next_comm=Binder:965_2 next_pid=1041 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229271: tracing_mark_write: B|625|handleTransaction
- <...>-1773 (-----) [004] .... 14594.229285: binder_set_priority: proc=625 thread=1773 old=110 => new=120 desired=120
- <...>-440 (-----) [007] d..2 14594.229301: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-2738 (-----) [007] ...1 14594.229318: tracing_mark_write: B|2007|HWC release fence 36028 has signaled
- <...>-2738 (-----) [007] ...1 14594.229331: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.229337: tracing_mark_write: B|2007|eglBeginFrame
- <...>-2738 (-----) [007] ...1 14594.229352: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.229354: tracing_mark_write: B|2007|query
- <...>-791 (-----) [000] d..2 14594.229357: sched_switch: prev_comm=main prev_pid=791 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229440: tracing_mark_write: B|625|doTransaction
- <...>-13916 (-----) [002] d..2 14594.229482: sched_switch: prev_comm=HeapTaskDaemon prev_pid=13916 prev_prio=124 prev_state=D|K ==> next_comm=swapper/2 next_pid=0 next_prio=120
- <...>-13917 (-----) [001] d..2 14594.229492: sched_blocked_reason: pid=13916 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-625 (-----) [003] ...1 14594.229492: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229507: tracing_mark_write: B|625|doTransaction
- <...>-13917 (-----) [001] d..2 14594.229523: sched_switch: prev_comm=ReferenceQueueD prev_pid=13917 prev_prio=124 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-13916 (-----) [002] d..2 14594.229535: sched_blocked_reason: pid=13917 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-625 (-----) [003] ...1 14594.229538: tracing_mark_write: B|625|doTransaction
- <...>-2738 (-----) [007] ...1 14594.229543: tracing_mark_write: B|2007|flush commands
- <...>-13916 (-----) [002] .... 14594.229562: sched_process_exit: comm=HeapTaskDaemon pid=13916 prio=124
- <...>-625 (-----) [003] ...1 14594.229567: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229588: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229628: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229652: tracing_mark_write: B|625|doTransaction
- <...>-13916 (-----) [002] d..2 14594.229676: sched_switch: prev_comm=HeapTaskDaemon prev_pid=13916 prev_prio=124 prev_state=x ==> next_comm=swapper/2 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229676: tracing_mark_write: B|625|doTransaction
- <...>-2007 (-----) [006] d..2 14594.229688: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229703: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229725: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229750: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229772: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229792: tracing_mark_write: B|625|doTransaction
- <...>-791 (-----) [000] d..2 14594.229811: sched_switch: prev_comm=main prev_pid=791 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229824: tracing_mark_write: B|625|doTransaction
- <...>-2738 (-----) [007] ...1 14594.229827: tracing_mark_write: B|2007|eglSwapBuffersWithDamageKHR
- <...>-13917 (-----) [001] d..2 14594.229836: sched_switch: prev_comm=ReferenceQueueD prev_pid=13917 prev_prio=124 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [007] ...1 14594.229837: tracing_mark_write: B|2007|setSurfaceDamage
- <...>-625 (-----) [003] ...1 14594.229850: tracing_mark_write: B|625|doTransaction
- <...>-13918 (-----) [002] d..2 14594.229856: sched_blocked_reason: pid=13917 iowait=0 caller=SyS_madvise+0xd34/0xd3c
- <...>-5281 (-----) [001] d..2 14594.229932: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-89 (-----) [006] d..2 14594.229951: sched_switch: prev_comm=lpass_smem_glin prev_pid=89 prev_prio=98 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229982: tracing_mark_write: B|625|handleMessageInvalidate
- <...>-625 (-----) [003] ...1 14594.229984: tracing_mark_write: B|625|handlePageFlip
- <...>-625 (-----) [003] ...1 14594.230013: tracing_mark_write: B|625|latchBuffer
- <...>-13917 (-----) [000] .... 14594.230015: sched_process_exit: comm=ReferenceQueueD pid=13917 prio=124
- <...>-625 (-----) [003] ...1 14594.230020: tracing_mark_write: B|625|query
- <...>-625 (-----) [003] ...1 14594.230028: tracing_mark_write: B|625|updateTexImage
- <...>-625 (-----) [003] ...1 14594.230035: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [003] ...1 14594.230044: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-2738 (-----) [007] d..2 14594.230057: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=D ==> next_comm=smem_native_lpa next_pid=88 next_prio=120
- <...>-14607 (-----) [000] d..2 14594.259609: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-2738 (-----) [005] d..2 14594.259620: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=120 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1773 (-----) [005] ...1 14594.259649: tracing_mark_write: B|625|query
- <...>-2738 (-----) [005] ...1 14594.259714: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] d..2 14594.259743: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=120 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1773 (-----) [005] ...1 14594.259757: tracing_mark_write: B|625|query
- <...>-2738 (-----) [005] ...1 14594.259810: tracing_mark_write: B|2007|syncFrameState
- <...>-2738 (-----) [005] ...1 14594.259856: tracing_mark_write: B|2007|prepareTree
- Binder:14607_1-14624 (14607) [002] ...1 14594.259863: tracing_mark_write: B|14607|AttachCurrentThread
- Binder:14607_1-14624 (14607) [002] ...1 14594.259869: tracing_mark_write: B|14607|Thread::Attach
- Binder:14607_1-14624 (14607) [002] ...1 14594.259873: tracing_mark_write: B|14607|Thread birth
- Binder:14607_1-14624 (14607) [002] ...1 14594.259916: tracing_mark_write: B|14607|Thread::Init
- Binder:14607_1-14624 (14607) [002] ...1 14594.259920: tracing_mark_write: B|14607|InitStackHwm
- <...>-14607 (-----) [000] d..2 14594.259932: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_1-14624 (14607) [002] d..2 14594.259941: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-3198 (-----) [001] ...1 14594.259942: tracing_mark_write: B|2007|Update SurfaceView position
- Binder:14607_1-14624 (14607) [002] ...1 14594.259963: tracing_mark_write: B|14607|InitTlsEntryPoints
- Binder:14607_1-14624 (14607) [002] ...1 14594.259974: tracing_mark_write: B|14607|InitInterpreterTls
- <...>-14607 (-----) [000] d..2 14594.260005: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-3198 (-----) [001] d..2 14594.260007: sched_switch: prev_comm=hwuiTask1 prev_pid=3198 prev_prio=118 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-14607 (-----) [000] d..2 14594.260024: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_1-14624 (14607) [002] d..2 14594.260038: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260064: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- Binder:14607_1-14624 (14607) [002] ...1 14594.260101: tracing_mark_write: B|14607|ThreadList::Register
- <...>-2738 (-----) [005] ...1 14594.260128: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260140: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260148: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260155: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260161: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260167: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260173: tracing_mark_write: B|2007|dequeueBuffer
- <...>-2007 (-----) [001] d..2 14594.260201: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [005] d..2 14594.260214: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=120 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1773 (-----) [005] ...1 14594.260236: tracing_mark_write: B|625|dequeueBuffer
- <...>-1773 (-----) [005] ...1 14594.260249: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-14607 (-----) [000] d..2 14594.260334: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_1-14624 (14607) [002] d..2 14594.260343: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260376: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.260387: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-2738 (-----) [005] ...1 14594.260401: tracing_mark_write: B|2007|HWC release fence 36030 has signaled
- Binder:14607_1-14624 (14607) [002] d..2 14594.260407: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-2738 (-----) [005] ...1 14594.260419: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260427: tracing_mark_write: B|2007|eglBeginFrame
- <...>-2738 (-----) [005] ...1 14594.260445: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260450: tracing_mark_write: B|2007|query
- Binder:14607_1-14624 (14607) [002] .... 14594.260472: task_newtask: pid=14625 comm=Binder:14607_1 clone_flags=3d0f00 oom_score_adj=-1000
- <...>-14607 (-----) [000] d..2 14594.260517: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260525: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260555: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] ...1 14594.260569: tracing_mark_write: B|14607|ActivityThreadMain
- <...>-14607 (-----) [000] d..2 14594.260581: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260588: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260611: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.260623: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260636: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260663: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.260674: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260694: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260724: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-2738 (-----) [005] ...1 14594.260734: tracing_mark_write: B|2007|flush commands
- <...>-14607 (-----) [000] d..2 14594.260735: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260753: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- Binder:14607_2-14625 (14607) [001] ...1 14594.260925: tracing_mark_write: B|14607|AttachCurrentThread
- Binder:14607_2-14625 (14607) [001] ...1 14594.260930: tracing_mark_write: B|14607|Thread::Attach
- Binder:14607_2-14625 (14607) [001] ...1 14594.260933: tracing_mark_write: B|14607|Thread birth
- Binder:14607_2-14625 (14607) [001] ...1 14594.260973: tracing_mark_write: B|14607|Thread::Init
- Binder:14607_2-14625 (14607) [001] ...1 14594.260977: tracing_mark_write: B|14607|InitStackHwm
- <...>-14607 (-----) [000] d..2 14594.260990: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260998: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- Binder:14607_2-14625 (14607) [001] ...1 14594.261023: tracing_mark_write: B|14607|InitTlsEntryPoints
- Binder:14607_2-14625 (14607) [001] ...1 14594.261034: tracing_mark_write: B|14607|InitInterpreterTls
- <...>-14607 (-----) [000] d..2 14594.261064: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.261075: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.261094: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.261120: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.261132: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.261146: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- Binder:14607_2-14625 (14607) [001] ...1 14594.261167: tracing_mark_write: B|14607|ThreadList::Register
- <...>-14607 (-----) [000] d..2 14594.261209: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-2738 (-----) [005] ...1 14594.261212: tracing_mark_write: B|2007|waitOnFences
- <...>-14607 (-----) [000] d..2 14594.261220: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-2738 (-----) [005] ...1 14594.261232: tracing_mark_write: B|2007|eglSwapBuffersWithDamageKHR
- <...>-2738 (-----) [005] ...1 14594.261244: tracing_mark_write: B|2007|setSurfaceDamage
- Binder:14607_2-14625 (14607) [001] d..2 14594.261246: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] ...1 14594.261326: tracing_mark_write: B|14607|VerifyClass com.android.org.conscrypt.TrustedCertificateStore$PreloadHolder
- <...>-2738 (-----) [005] .... 14594.261621: fence_init: driver=kgsl-timeline timeline=kgsl-3d0_13-s.nexuslauncher(200 context=27 seqno=78005
- <...>-625 (-----) [003] ...1 14594.263903: tracing_mark_write: B|625|resetIdleTimer
- <...>-625 (-----) [003] ...1 14594.263912: tracing_mark_write: B|625|rebuildLayerStacks
- <...>-625 (-----) [003] ...1 14594.263915: tracing_mark_write: B|625|rebuildLayerStacks VR Dirty
- <...>-625 (-----) [003] ...1 14594.263919: tracing_mark_write: B|625|computeVisibleRegions
- <...>-1398 (-----) [006] d..2 14594.263966: sched_switch: prev_comm=android.anim prev_pid=1398 prev_prio=110 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1695 (-----) [001] d..2 14594.264086: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=S ==> next_comm=Binder:1368_14 next_pid=3253 next_prio=120
- <...>-625 (-----) [003] ...1 14594.264293: tracing_mark_write: B|625|calculateWorkingSet
- <...>-625 (-----) [003] ...1 14594.264500: tracing_mark_write: B|625|prepare
- <...>-625 (-----) [003] ...1 14594.264513: tracing_mark_write: B|625|HIDL::IComposerClient::executeCommands_2_2::client
- <...>-625 (-----) [003] ...2 14594.264584: binder_set_priority: proc=627 thread=627 old=97 => new=98 desired=98
- <...>-625 (-----) [003] d..2 14594.264617: sched_switch: prev_comm=surfaceflinger prev_pid=625 prev_prio=98 prev_state=S ==> next_comm=logd.writer next_pid=588 next_prio=130
- <...>-588 (-----) [003] d..2 14594.264851: sched_switch: prev_comm=logd.writer prev_pid=588 prev_prio=130 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
- rcu_preempt-7 ( 7) [007] d..2 14594.265273: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=120 prev_state=S ==> next_comm=kworker/u16:3 next_pid=18008 next_prio=120
- <...>-18008 (-----) [007] d..2 14594.265404: sched_switch: prev_comm=kworker/u16:3 prev_pid=18008 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-18008 (-----) [007] d..2 14594.265471: sched_switch: prev_comm=kworker/u16:3 prev_pid=18008 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.265496: tracing_mark_write: B|625|doComposition
- <...>-625 (-----) [003] ...1 14594.265507: tracing_mark_write: B|625|doComposeSurfaces
- <...>-625 (-----) [003] ...1 14594.265552: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [003] ...1 14594.265563: tracing_mark_write: B|625|postFramebuffer
- <...>-625 (-----) [003] ...1 14594.265567: tracing_mark_write: B|625|presentAndGetReleaseFences
- <...>-625 (-----) [003] d..1 14594.265601: fence_enable_signal: driver=sde_fence:crtc97:91650 timeline=crtc97 context=3 seqno=91650
- <...>-625 (-----) [003] ...1 14594.265735: tracing_mark_write: B|625|logLayerStats
- <...>-625 (-----) [003] ...1 14594.265744: tracing_mark_write: B|625|postComposition
- <...>-625 (-----) [003] ...1 14594.265749: tracing_mark_write: B|625|releaseBuffer
- <...>-625 (-----) [003] ...1 14594.265753: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 1
- <...>-625 (-----) [003] ...1 14594.265791: tracing_mark_write: B|625|releaseBuffer
- <...>-440 (-----) [007] d..2 14594.342366: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=kworker/u17:2 next_pid=1778 next_prio=100
- <...>-2007 (-----) [006] ...1 14594.342375: tracing_mark_write: B|2007|input
- <...>-2007 (-----) [006] ...1 14594.342399: tracing_mark_write: B|2007|animation
- <...>-625 (-----) [003] ...1 14594.342447: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.342489: tracing_mark_write: B|625|doTransaction
- kworker/u17:2-1778 ( 1778) [007] d..3 14594.342532: sched_blocked_reason: pid=14607 iowait=1 caller=wait_on_page_bit_common+0x2a8/0x5f8
- kworker/u17:2-1778 ( 1778) [007] d..2 14594.342544: sched_switch: prev_comm=kworker/u17:2 prev_pid=1778 prev_prio=100 prev_state=S ==> next_comm=kworker/u16:2 next_pid=27544 next_prio=120
- <...>-1773 (-----) [000] ...1 14594.342575: tracing_mark_write: B|625|requestNextVsync
- <...>-1773 (-----) [000] ...1 14594.342579: tracing_mark_write: B|625|resetIdleTimer
- <...>-27544 (-----) [007] d..2 14594.342589: sched_switch: prev_comm=kworker/u16:2 prev_pid=27544 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-656 (-----) [002] d.h3 14594.342604: sched_blocked_reason: pid=1233 iowait=0 caller=geni_i2c_xfer+0x4d8/0x1398
- <...>-1803 (-----) [001] d..2 14594.342605: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.342632: tracing_mark_write: B|625|handleMessageInvalidate
- <...>-625 (-----) [003] ...1 14594.342634: tracing_mark_write: B|625|handlePageFlip
- <...>-2738 (-----) [007] ...1 14594.342641: tracing_mark_write: B|2007|notifyFramePending
- <...>-658 (-----) [002] d..2 14594.342653: sched_switch: prev_comm=DispSync prev_pid=658 prev_prio=97 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=120
- <...>-656 (-----) [002] ...1 14594.342656: tracing_mark_write: B|625|requestNextVsync
- <...>-2738 (-----) [007] d..2 14594.342658: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-656 (-----) [002] ...1 14594.342660: tracing_mark_write: B|625|resetIdleTimer
- <...>-660 (-----) [005] d..2 14594.342663: sched_switch: prev_comm=app prev_pid=660 prev_prio=97 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.342665: tracing_mark_write: B|625|latchBuffer
- <...>-625 (-----) [003] ...1 14594.342673: tracing_mark_write: B|625|query
- <...>-625 (-----) [003] ...1 14594.342682: tracing_mark_write: B|625|updateTexImage
- <...>-625 (-----) [003] ...1 14594.342693: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [003] ...1 14594.342703: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 1
- <...>-660 (-----) [005] d..2 14594.342709: sched_switch: prev_comm=app prev_pid=660 prev_prio=97 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-2007 (-----) [006] ...1 14594.342733: tracing_mark_write: B|2007|traversal
- <...>-2007 (-----) [006] ...1 14594.342776: tracing_mark_write: B|2007|draw
- <...>-2007 (-----) [006] ...1 14594.342791: tracing_mark_write: B|2007|Record View#draw()
- <...>-625 (-----) [003] ...1 14594.342849: tracing_mark_write: B|625|updateInputFlinger
- <...>-2007 (-----) [006] d..2 14594.342903: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=kworker/6:2H next_pid=24261 next_prio=100
- <...>-2738 (-----) [007] ...1 14594.342910: tracing_mark_write: B|2007|DrawFrame
- <...>-2738 (-----) [007] d..2 14594.342917: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-24261 (-----) [006] d..2 14594.342918: sched_switch: prev_comm=kworker/6:2H prev_pid=24261 prev_prio=100 prev_state=S ==> next_comm=.android.dialer next_pid=14607 next_prio=110
- <...>-440 (-----) [007] d..2 14594.342926: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-2738 (-----) [007] ...1 14594.342927: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...2 14594.342959: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [007] d..2 14594.342975: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-656 (-----) [007] ...1 14594.343021: tracing_mark_write: B|625|query
- <...>-656 (-----) [007] .... 14594.343033: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-2738 (-----) [007] ...1 14594.343070: tracing_mark_write: B|2007|query
- <...>-1233 (-----) [004] d..2 14594.343074: sched_switch: prev_comm=sound trigger c prev_pid=1233 prev_prio=120 prev_state=R+ ==> next_comm=irq/144-1436400 next_pid=2522 next_prio=49
- <...>-2738 (-----) [007] ...2 14594.343078: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-625 (-----) [003] ...1 14594.343084: tracing_mark_write: B|625|onMessageReceived
- <...>-625 (-----) [003] ...1 14594.343087: tracing_mark_write: B|625|handleMessageRefresh
- <...>-625 (-----) [003] ...1 14594.343090: tracing_mark_write: B|625|preComposition
- <...>-2738 (-----) [007] d..2 14594.343090: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-625 (-----) [003] ...1 14594.343122: tracing_mark_write: B|625|rebuildLayerStacks
- <...>-625 (-----) [003] ...1 14594.343124: tracing_mark_write: B|625|rebuildLayerStacks VR Dirty
- <...>-89 (-----) [007] d..2 14594.343126: sched_switch: prev_comm=lpass_smem_glin prev_pid=89 prev_prio=98 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-625 (-----) [003] ...1 14594.343129: tracing_mark_write: B|625|computeVisibleRegions
- <...>-656 (-----) [007] ...1 14594.343136: tracing_mark_write: B|625|query
- <...>-14607 (-----) [006] ...2 14594.343141: binder_set_priority: proc=1368 thread=3253 old=120 => new=110 desired=110
- <...>-2965 (-----) [001] .... 14596.746610: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000002ae8fcff pfn=1522884 ofs=188416
- <idle>-0 (-----) [002] d..2 14596.746619: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-2965 (-----) [001] .... 14596.746629: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000679ee1ec pfn=1299913 ofs=192512
- <...>-2965 (-----) [001] .... 14596.746664: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=0000000006cd2fb7 pfn=1296251 ofs=196608
- <...>-2965 (-----) [001] .... 14596.746677: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000af82f3d6 pfn=1419330 ofs=200704
- <...>-2965 (-----) [001] .... 14596.746693: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000002840f054 pfn=1304928 ofs=204800
- <...>-2965 (-----) [001] .... 14596.746706: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000004a59da17 pfn=1288069 ofs=208896
- <...>-2965 (-----) [001] .... 14596.746717: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=0000000023a80dca pfn=1419686 ofs=212992
- <...>-2965 (-----) [001] .... 14596.746730: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000001cf89eab pfn=1315372 ofs=217088
- <...>-2965 (-----) [001] .... 14596.746743: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000005b4c6cb6 pfn=1380698 ofs=221184
- <...>-2965 (-----) [001] .... 14596.746760: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000f8304ae7 pfn=1206753 ofs=225280
- <...>-2965 (-----) [001] .... 14596.746773: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000cb912305 pfn=1325465 ofs=229376
- <...>-2965 (-----) [001] .... 14596.746785: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000f16f3774 pfn=1408056 ofs=233472
- <...>-2965 (-----) [001] .... 14596.746801: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=0000000056d4c926 pfn=1418352 ofs=237568
- <...>-2965 (-----) [001] .... 14596.746815: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000f3eeb42c pfn=1320957 ofs=241664
- <...>-440 (-----) [002] d..2 14596.746916: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=swapper/2 next_pid=0 next_prio=120
-
- <...>-656 (-----) [007] .... 14594.343145: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-14607 (-----) [006] d..2 14594.343164: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=110 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-5281 (-----) [002] d..2 14594.343177: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- irq/144-1436400-2522 ( 2522) [004] d..2 14594.343223: sched_switch: prev_comm=irq/144-1436400 prev_pid=2522 prev_prio=49 prev_state=D ==> next_comm=sound trigger c next_pid=1233 next_prio=120
- <...>-88 (-----) [006] d..2 14594.343240: sched_switch: prev_comm=smem_native_lpa prev_pid=88 prev_prio=98 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-1238 (-----) [001] d..2 14594.343243: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [002] ...1 14594.343244: tracing_mark_write: B|2007|syncFrameState
- <...>-2738 (-----) [002] ...1 14594.343293: tracing_mark_write: B|2007|prepareTree
- <...>-1695 (-----) [001] d..2 14594.343318: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=R+ ==> next_comm=FastMixer next_pid=1238 next_prio=96
- <...>-5281 (-----) [005] d..2 14594.343322: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:1368_14 next_pid=3253 next_prio=110
- <...>-1238 (-----) [001] d..2 14594.343442: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=InputDispatcher next_pid=1695 next_prio=112
- <...>-1695 (-----) [001] d..2 14594.343467: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-5281 (-----) [000] d..2 14594.343484: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.343519: tracing_mark_write: B|625|calculateWorkingSet
- <...>-2738 (-----) [002] ...1 14594.343568: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343577: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343586: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343591: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343597: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343602: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343609: tracing_mark_write: B|2007|dequeueBuffer
- <...>-2007 (-----) [006] d..2 14594.343612: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-2738 (-----) [002] ...2 14594.343633: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [002] d..2 14594.343683: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-625 (-----) [003] ...1 14594.343704: tracing_mark_write: B|625|prepare
- <...>-656 (-----) [002] ...1 14594.343707: tracing_mark_write: B|625|dequeueBuffer
- <...>-625 (-----) [004] ...1 14594.812869: tracing_mark_write: B|625|com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#0: 2
- <...>-2048 (-----) [000] d..2 14594.812895: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=Binder:625_3 next_pid=1431 next_prio=120
- <...>-1431 (-----) [000] ...1 14594.812911: tracing_mark_write: B|625|query
- <...>-625 (-----) [004] ...1 14594.812914: tracing_mark_write: B|625|latchBuffer
- <...>-625 (-----) [004] ...1 14594.812919: tracing_mark_write: B|625|query
- <...>-625 (-----) [004] ...1 14594.812925: tracing_mark_write: B|625|updateTexImage
- <...>-625 (-----) [004] ...1 14594.812928: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [004] ...1 14594.812934: tracing_mark_write: B|625|StatusBar#0: 1
- <...>-2048 (-----) [000] ...1 14594.812962: tracing_mark_write: B|1803|syncFrameState
- <...>-656 (-----) [002] ...1 14594.813044: tracing_mark_write: B|625|setTransactionState
- <...>-14607 (-----) [007] ...2 14594.813083: binder_set_priority: proc=10691 thread=18733 old=120 => new=110 desired=110
- <...>-14607 (-----) [007] d..2 14594.813114: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=110 prev_state=S ==> next_comm=kworker/7:1 next_pid=7092 next_prio=120
- <...>-14655 (-----) [006] d..2 14594.813128: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R ==> next_comm=lpass_smem_glin next_pid=89 next_prio=98
- <...>-89 (-----) [006] d..2 14594.813163: sched_switch: prev_comm=lpass_smem_glin prev_pid=89 prev_prio=98 prev_state=S ==> next_comm=DialerExecutors next_pid=14655 next_prio=130
- <...>-656 (-----) [002] ...1 14594.813218: tracing_mark_write: B|625|requestNextVsync
- <...>-656 (-----) [002] ...1 14594.813222: tracing_mark_write: B|625|resetIdleTimer
- kworker/7:1-7092 ( 7092) [007] d..2 14594.813239: sched_switch: prev_comm=kworker/7:1 prev_pid=7092 prev_prio=120 prev_state=R+ ==> next_comm=smem_native_lpa next_pid=88 next_prio=98
- <...>-5281 (-----) [001] d..2 14594.813245: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:10691_B next_pid=18733 next_prio=110
- <...>-88 (-----) [007] d..2 14594.813248: sched_switch: prev_comm=smem_native_lpa prev_pid=88 prev_prio=98 prev_state=R ==> next_comm=kgsl_worker_thr next_pid=259 next_prio=97
- <...>-2048 (-----) [000] d..2 14594.813249: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=FastMixer next_pid=1238 next_prio=96
- <...>-14655 (-----) [006] d..2 14594.813263: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R+ ==> next_comm=smem_native_lpa next_pid=88 next_prio=98
- <...>-661 (-----) [002] d..2 14594.813265: sched_switch: prev_comm=sf prev_pid=661 prev_prio=97 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
- <...>-259 (-----) [007] d..2 14594.813265: sched_switch: prev_comm=kgsl_worker_thr prev_pid=259 prev_prio=97 prev_state=S ==> next_comm=kworker/7:1 next_pid=7092 next_prio=120
- kworker/7:1-7092 ( 7092) [007] d..2 14594.813271: sched_switch: prev_comm=kworker/7:1 prev_pid=7092 prev_prio=120 prev_state=S ==> next_comm=system next_pid=108 next_prio=120
- <...>-108 (-----) [007] .... 14594.813275: ion_heap_shrink: heap_name=system, len=9469952, total_allocated=189620224
- <...>-88 (-----) [006] d..2 14594.813294: sched_switch: prev_comm=smem_native_lpa prev_pid=88 prev_prio=98 prev_state=S ==> next_comm=DialerExecutors next_pid=14655 next_prio=130
- <...>-625 (-----) [004] ...1 14594.813310: tracing_mark_write: B|625|updateInputFlinger
- <...>-1238 (-----) [000] d..2 14594.813312: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-661 (-----) [002] d..2 14594.813317: sched_switch: prev_comm=sf prev_pid=661 prev_prio=97 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
- <...>-14640 (-----) [005] d..2 14594.813319: sched_switch: prev_comm=DialerExecutors prev_pid=14640 prev_prio=130 prev_state=R ==> next_comm=DispSync next_pid=658 next_prio=97
- <...>-656 (-----) [002] ...1 14594.813336: tracing_mark_write: B|625|~GraphicBuffer
- <...>-658 (-----) [005] d..2 14594.813345: sched_switch: prev_comm=DispSync prev_pid=658 prev_prio=97 prev_state=S ==> next_comm=DialerExecutors next_pid=14640 next_prio=130
- <...>-656 (-----) [002] ...1 14594.813345: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813353: tracing_mark_write: B|625|~GraphicBuffer
- <...>-2048 (-----) [000] d..2 14594.813358: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=FastMixer next_pid=1238 next_prio=96
- <...>-656 (-----) [002] ...1 14594.813364: tracing_mark_write: B|625|~GraphicBuffer
- <...>-5281 (-----) [001] d..2 14594.813369: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:10691_B next_pid=18733 next_prio=110
- <...>-656 (-----) [002] ...1 14594.813372: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813380: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813391: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813398: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813408: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813416: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813424: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813432: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] .n.1 14594.813443: tracing_mark_write: B|625|~GraphicBuffer
- <...>-1238 (-----) [000] d..2 14594.813464: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-5281 (-----) [002] d..2 14594.813525: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
- <...>-656 (-----) [002] ...1 14594.813544: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813557: tracing_mark_write: B|625|~GraphicBuffer
- <...>-2048 (-----) [000] d..2 14594.813594: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=Binder:1368_15 next_pid=3359 next_prio=120
- <...>-18733 (-----) [001] ...2 14594.813635: binder_set_priority: proc=1368 thread=3514 old=120 => new=110 desired=110
- <...>-656 (-----) [002] .... 14594.813637: binder_set_priority: proc=625 thread=656 old=116 => new=120 desired=120
- <...>-108 (-----) [007] d..2 14594.813646: sched_switch: prev_comm=system prev_pid=108 prev_prio=120 prev_state=R+ ==> next_comm=android.anim next_pid=1398 next_prio=116
- <...>-625 (-----) [004] ...1 14594.813646: tracing_mark_write: B|625|onMessageReceived
- <...>-625 (-----) [004] ...1 14594.813649: tracing_mark_write: B|625|handleMessageRefresh
- <...>-625 (-----) [004] ...1 14594.813651: tracing_mark_write: B|625|preComposition
- <...>-625 (-----) [004] ...1 14594.813693: tracing_mark_write: B|625|rebuildLayerStacks
- <...>-625 (-----) [004] ...1 14594.813696: tracing_mark_write: B|625|rebuildLayerStacks VR Dirty
- <...>-625 (-----) [004] ...1 14594.813701: tracing_mark_write: B|625|computeVisibleRegions
- <...>-1398 (-----) [007] d..2 14594.813718: sched_switch: prev_comm=android.anim prev_pid=1398 prev_prio=116 prev_state=S ==> next_comm=system next_pid=108 next_prio=120
- <...>-108 (-----) [007] d..2 14594.813739: sched_switch: prev_comm=system prev_pid=108 prev_prio=120 prev_state=R+ ==> next_comm=android.anim next_pid=1398 next_prio=116
- <...>-1695 (-----) [002] d..2 14594.813970: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=S ==> next_comm=system next_pid=108 next_prio=120
- <...>-1398 (-----) [007] ...1 14594.814029: tracing_mark_write: B|1368|wmLayout
- <...>-1398 (-----) [007] ...1 14594.814033: tracing_mark_write: B|1368|performSurfacePlacement
- <...>-1398 (-----) [007] ...1 14594.814040: tracing_mark_write: B|1368|applySurfaceChanges
- <...>-1398 (-----) [007] ...1 14594.814043: tracing_mark_write: B|1368|openSurfaceTransaction
- <...>-1398 (-----) [007] ...1 14594.814063: tracing_mark_write: B|1368|performLayout
- <...>-625 (-----) [004] ...1 14594.814119: tracing_mark_write: B|625|calculateWorkingSet
- <...>-1398 (-----) [007] ...1 14594.814241: tracing_mark_write: B|1368|layoutInputConsumer
- <...>-2048 (-----) [000] ...1 14594.814260: tracing_mark_write: B|1803|prepareTree
- <...>-1398 (-----) [007] ...1 14594.814263: tracing_mark_write: B|1368|applyPostLayoutPolicy
- <...>-2048 (-----) [000] d..2 14594.814408: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R ==> next_comm=Binder:1368_15 next_pid=3359 next_prio=120
- <...>-625 (-----) [004] ...1 14594.814411: tracing_mark_write: B|625|prepare
- <...>-625 (-----) [004] ...1 14594.814428: tracing_mark_write: B|625|HIDL::IComposerClient::executeCommands_2_2::client
- <...>-2048 (-----) [000] d..2 14594.814533: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=ndroid.systemui next_pid=1803 next_prio=120
- <...>-1803 (-----) [000] d..2 14594.814558: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-2048 (-----) [000] d..2 14594.814572: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=ndroid.systemui next_pid=1803 next_prio=120
- <...>-625 (-----) [004] ...2 14594.814589: binder_set_priority: proc=627 thread=627 old=97 => new=98 desired=98
- <...>-108 (-----) [002] d..2 14594.814650: sched_switch: prev_comm=system prev_pid=108 prev_prio=120 prev_state=R+ ==> next_comm=composer@2.2-se next_pid=627 next_prio=98
- <...>-625 (-----) [004] d..2 14594.814664: sched_switch: prev_comm=surfaceflinger prev_pid=625 prev_prio=98 prev_state=S ==> next_comm=ashmemd next_pid=854 next_prio=129
- <...>-1398 (-----) [007] ...1 14594.814723: tracing_mark_write: B|1368|applyWindowSurfaceChanges
- <...>-854 (-----) [004] .... 14594.814746: binder_set_priority: proc=854 thread=854 old=129 => new=120 desired=120
- <...>-854 (-----) [004] d..2 14594.814757: sched_switch: prev_comm=ashmemd prev_pid=854 prev_prio=120 prev_state=R+ ==> next_comm=highpool[0] next_pid=3493 next_prio=129
- <...>-1803 (-----) [000] d..2 14594.814763: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-18733 (-----) [001] d..1 14594.814819: mm_filemap_delete_from_page_cache: dev 0:1 ino 3ce5e7 page=0000000083f10c7a pfn=1298474 ofs=0
- <...>-2048 (-----) [000] ...1 14594.814842: tracing_mark_write: B|1803|dequeueBuffer
- <...>-1398 (-----) [007] ...1 14594.814850: tracing_mark_write: F|1368|launching: com.google.android.dialer|0
- <...>-1398 (-----) [007] ...1 14594.814855: tracing_mark_write: B|1368|MetricsLogger:launchObserverNotifyActivityLaunchFinished
- <...>-1398 (-----) [007] ...1 14594.814857: tracing_mark_write: B|1368|MetricsLogger:convertActivityRecordToProto
- <...>-2048 (-----) [000] d..2 14594.814905: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=120
- <...>-1410 (-----) [006] .... 14592.997816: mm_filemap_add_to_page_cache: dev 253:6 ino b785 page=00000000615a8f24 pfn=1134764 ofs=0
- <...>-1410 (-----) [006] .... 14592.997831: mm_filemap_add_to_page_cache: dev 253:6 ino b785 page=000000008768a58f pfn=1134751 ofs=4096
-
- <...>-18733 (-----) [001] .... 14594.814914: binder_set_priority: proc=10691 thread=18733 old=110 => new=120 desired=120
- <...>-14655 (-----) [006] d..2 14594.814932: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R ==> next_comm=.android.dialer next_pid=14607 next_prio=110
- <...>-656 (-----) [000] ...1 14594.814948: tracing_mark_write: B|625|dequeueBuffer
- <...>-3514 (-----) [001] .... 14594.814954: binder_set_priority: proc=1368 thread=3514 old=110 => new=120 desired=120
- <...>-656 (-----) [000] ...1 14594.814963: tracing_mark_write: B|625|NavigationBar0#0: 2
- <...>-14607 (-----) [006] ...2 14594.815022: binder_set_priority: proc=1368 thread=3514 old=120 => new=110 desired=110
- <...>-1398 (-----) [007] ...1 14594.815039: tracing_mark_write: B|1368|prepareSurfaces
- <...>-14607 (-----) [006] d..2 14594.815041: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=110 prev_state=S ==> next_comm=DialerExecutors next_pid=14655 next_prio=130
- <...>-3493 (-----) [004] d..2 14594.815057: sched_switch: prev_comm=highpool[0] prev_pid=3493 prev_prio=129 prev_state=R ==> next_comm=Binder:1368_18 next_pid=3514 next_prio=110
- <...>-2048 (-----) [000] ...1 14594.815088: tracing_mark_write: B|1803|HWC release fence 45750 has signaled
- <...>-2048 (-----) [000] ...1 14594.815119: tracing_mark_write: B|1803|eglBeginFrame
- <...>-14655 (-----) [006] d..2 14594.815190: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R ==> next_comm=crtc_commit:97 next_pid=301 next_prio=83
- <...>-3514 (-----) [004] .... 14594.815193: binder_set_priority: proc=1368 thread=3514 old=110 => new=120 desired=120
- <...>-1398 (-----) [007] ...1 14594.815322: tracing_mark_write: B|1368|closeSurfaceTransaction
- <...>-3493 (-----) [004] .... 14594.815353: mm_filemap_add_to_page_cache: dev 253:6 ino 113b page=0000000069e2b98a pfn=628464 ofs=2723840
- <...>-1398 (-----) [007] ...2 14594.815393: binder_set_priority: proc=625 thread=656 old=120 => new=116 desired=116
- rcu_sched-8 ( 8) [007] d..2 14594.815449: sched_switch: prev_comm=rcu_sched prev_pid=8 prev_prio=120 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
diff --git a/startop/scripts/trace_analyzer/trace_analyzer b/startop/scripts/trace_analyzer/trace_analyzer
deleted file mode 100755
index 8c03964..0000000
--- a/startop/scripts/trace_analyzer/trace_analyzer
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-DIR="$( cd "$(dirname "$0")" ; pwd -P )"
-
-if [[ "$#" -lt 2 ]]; then
- echo "Usage: $0 <filename.trace> <sqlite-filename.db>" >&2
- exit 1
-fi
-
-TRACE_FILENAME="$1"
-SQLITE_FILENAME="$2"
-
-#echo "Trace filename: $TRACE_FILENAME"
-#echo "SQLite filename: $SQLITE_FILENAME"
-
-if ! [[ -f "$TRACE_FILENAME" ]]; then
- echo "Error: Trace '$TRACE_FILENAME' does not exist." >&2
- exit 1
-fi
-
-if ! "$DIR/trace_analyzer.py" "$SQLITE_FILENAME" "$TRACE_FILENAME" > /dev/null; then
- echo "Fatal: trace_analyzer.py failed, aborting." >&2
- exit 1
-fi
-
-if ! "$DIR/run-sql-queries" "$SQLITE_FILENAME"; then
- echo "Fatal: Failed to run sql queries, aborting." >&2
- exit 1
-fi
diff --git a/startop/scripts/trace_analyzer/trace_analyzer.py b/startop/scripts/trace_analyzer/trace_analyzer.py
deleted file mode 100755
index 62ae018..0000000
--- a/startop/scripts/trace_analyzer/trace_analyzer.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/python3
-# Copyright (C) 2019 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.
-
-import re
-import sys
-import argparse
-
-from lib.trace2db import Trace2Db
-
-# This script requires 'sqlalchemy' to access the sqlite3 database.
-#
-# $> sudo apt-get install python3-pip
-# $> pip3 install --user sqlalchemy
-#
-
-def main(argv):
- parser = argparse.ArgumentParser(description='Convert ftrace/systrace file into sqlite3 db.')
- parser.add_argument('db_filename', metavar='sql_filename.db', type=str,
- help='path to sqlite3 db filename')
- parser.add_argument('trace_filename', metavar='systrace.ftrace', type=str,
- help='path to ftrace/systrace filename')
- parser.add_argument('--limit', type=int, help='limit the number of entries parsed [for debugging]')
-
- args = parser.parse_args()
-
- db_filename = args.db_filename
- trace_filename = args.trace_filename
-
- trace2db = Trace2Db(db_filename)
- print("SQL Alchemy db initialized")
-
- # parse 'raw_ftrace_entries' table
- count = trace2db.parse_file_into_db(trace_filename, limit=args.limit)
- print("Count was ", count)
-
- return 0
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/startop/scripts/trace_analyzer/trace_analyzer_recursive b/startop/scripts/trace_analyzer/trace_analyzer_recursive
deleted file mode 100755
index 4d9ee0e..0000000
--- a/startop/scripts/trace_analyzer/trace_analyzer_recursive
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-DIR="$( cd "$(dirname "$0")" ; pwd -P )"
-
-if [[ "$#" -lt 3 ]]; then
- echo "Usage: $0 <trace-dir> <db-dir> <output.csv>" >&2
- exit 1
-fi
-
-simulate="n"
-
-TRACE_DIRNAME="$1"
-SQLITE_DIRNAME="$2"
-OUTPUT_FILENAME="$3"
-
-echo "Trace filename: $TRACE_DIRNAME"
-echo "SQLite filename: $SQLITE_DIRNAME"
-
-if ! [[ -d "$TRACE_DIRNAME" ]]; then
- echo "Error: Trace '$TRACE_DIRNAME' does not exist." >&2
- exit 1
-fi
-
-process_trace_file() {
- local trace_filename="$1"
- local db_dirname="$2"
- local output_file="$3"
-
- local db_filename="$db_dirname/$(basename "$trace_filename").db"
-
- if [[ $simulate == y ]]; then
- echo "$DIR/trace_analyzer.py" "$db_filename" "$trace_filename" "> /dev/null"
- else
- if ! "$DIR/trace_analyzer.py" "$db_filename" "$trace_filename" > /dev/null; then
- echo "Fatal: trace_analyzer.py failed, aborting." >&2
- return 1
- fi
- fi
-
- if [[ $simulate == y ]]; then
- echo "$DIR/run-sql-queries" "$db_filename" ">> '$output_file'"
- else
- # append name of trace to CSV, so we can see where data came from
- echo "; $trace_filename" >> "$output_file"
- if ! "$DIR/run-sql-queries" "$db_filename" >> "$output_file"; then
- echo "Fatal: Failed to run sql queries, aborting." >&2
- return 1
- fi
- fi
-
- return 0
-}
-
-find "$TRACE_DIRNAME" -type f -name '*.trace' -print0 |
-while IFS= read -r -d '' file; do
- if [[ $file == *#*.trace && $file != *#1.trace ]]; then
- echo "Skip $file"
- continue
- fi
-
- printf '%s\n' "$file"
- process_trace_file "$file" "$SQLITE_DIRNAME" "$OUTPUT_FILENAME"
-done
-
-echo "Done"
diff --git a/startop/scripts/trace_analyzer/trace_analyzer_test.py b/startop/scripts/trace_analyzer/trace_analyzer_test.py
deleted file mode 100644
index 579529c..0000000
--- a/startop/scripts/trace_analyzer/trace_analyzer_test.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019, 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.
-#
-
-"""
-Unit tests for trace_analyzer module.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> pytest trace_analyzer_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-import os
-import sys
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-
-sys.path.append(os.path.dirname(DIR))
-import lib.cmd_utils as cmd_utils
-
-def test_trace_analyzer(tmpdir):
- # Setup
- bin = os.path.join(DIR, 'trace_analyzer')
- systrace = os.path.join(DIR, 'test_fixtures/common_systrace')
- db_file = tmpdir.mkdir('trace_analyzer').join('test.db')
-
- # Act
- passed, output = cmd_utils.execute_arbitrary_command([bin, systrace,
- str(db_file)],
- timeout=300,
- shell=False,
- simulate=False)
-
- # Assert
- assert passed
- assert output == """\
-'blocked_iowait_duration_ms',\
-'process_name',\
-'launching_duration_ms',\
-'launching_started_timestamp_ms',\
-'launching_finished_timestamp_ms'
-81.697999999960302375,\
-'com.google.android.dialer',\
-594.99400000095192808,\
-14594219.85600000061,\
-14594814.85000000149"""
diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index fcbb008..7d857a2 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -255,6 +255,12 @@
public static final String EXTRA_RESOLUTION_CARD_ID =
"android.service.euicc.extra.RESOLUTION_CARD_ID";
+ /**
+ * Intent extra set for resolution requests containing an int indicating the current port index.
+ */
+ public static final String EXTRA_RESOLUTION_PORT_INDEX =
+ "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "RESULT_" }, value = {
@@ -579,9 +585,32 @@
* @return the result of the switch operation. May be one of the predefined {@code RESULT_}
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#switchToSubscription
+ *
+ * @deprecated prefer {@link #onSwitchToSubscriptionWithPort(int, int, String, boolean)}
*/
- public abstract @Result int onSwitchToSubscription(int slotId, @Nullable String iccid,
- boolean forceDeactivateSim);
+ @Deprecated public abstract @Result int onSwitchToSubscription(int slotId,
+ @Nullable String iccid, boolean forceDeactivateSim);
+
+ /**
+ * Switch to the given subscription.
+ *
+ * @param slotId ID of the SIM slot to use for the operation.
+ * @param portIndex which port on the eUICC to use
+ * @param iccid the ICCID of the subscription to enable. May be null, in which case the current
+ * profile should be deactivated and no profile should be activated to replace it - this is
+ * equivalent to a physical SIM being ejected.
+ * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
+ * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
+ * should be returned to allow the user to consent to this operation first.
+ * @return the result of the switch operation. May be one of the predefined {@code RESULT_}
+ * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
+ * @see android.telephony.euicc.EuiccManager#switchToSubscription
+ */
+ public @Result int onSwitchToSubscriptionWithPort(int slotId, int portIndex,
+ @Nullable String iccid, boolean forceDeactivateSim) {
+ // stub implementation, LPA needs to implement this
+ throw new UnsupportedOperationException("LPA must override onSwitchToSubscriptionWithPort");
+ }
/**
* Update the nickname of the given subscription.
@@ -821,16 +850,15 @@
}
});
}
-
@Override
- public void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
- ISwitchToSubscriptionCallback callback) {
+ public void switchToSubscription(int slotId, int portIndex, String iccid,
+ boolean forceDeactivateSim, ISwitchToSubscriptionCallback callback) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
int result =
- EuiccService.this.onSwitchToSubscription(
- slotId, iccid, forceDeactivateSim);
+ EuiccService.this.onSwitchToSubscriptionWithPort(
+ slotId, portIndex, iccid, forceDeactivateSim);
try {
callback.onComplete(result);
} catch (RemoteException e) {
diff --git a/telephony/java/android/service/euicc/IEuiccService.aidl b/telephony/java/android/service/euicc/IEuiccService.aidl
index bb7b569..aa30c9e8 100644
--- a/telephony/java/android/service/euicc/IEuiccService.aidl
+++ b/telephony/java/android/service/euicc/IEuiccService.aidl
@@ -48,7 +48,7 @@
in IGetDefaultDownloadableSubscriptionListCallback callback);
void getEuiccInfo(int slotId, in IGetEuiccInfoCallback callback);
void deleteSubscription(int slotId, String iccid, in IDeleteSubscriptionCallback callback);
- void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
+ void switchToSubscription(int slotId, int portIndex, String iccid, boolean forceDeactivateSim,
in ISwitchToSubscriptionCallback callback);
void updateSubscriptionNickname(int slotId, String iccid, String nickname,
in IUpdateSubscriptionNicknameCallback callback);
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index e88106c..86b98f1 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -127,7 +127,9 @@
ApnSetting.TYPE_EMERGENCY,
ApnSetting.TYPE_MCX,
ApnSetting.TYPE_XCAP,
- // ApnSetting.TYPE_ENTERPRISE
+ ApnSetting.TYPE_BIP,
+ ApnSetting.TYPE_VSIM,
+ ApnSetting.TYPE_ENTERPRISE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApnType {
@@ -707,6 +709,9 @@
NetworkCapabilities.NET_CAPABILITY_VSIM,
NetworkCapabilities.NET_CAPABILITY_BIP,
NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH
})
public @interface NetCapability { }
@@ -721,4 +726,16 @@
NetworkAgent.VALIDATION_STATUS_NOT_VALID
})
public @interface ValidationStatus {}
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "NET_CAPABILITY_ENTERPRISE_SUB_LEVEL" }, value = {
+ NetworkCapabilities.NET_ENTERPRISE_ID_1,
+ NetworkCapabilities.NET_ENTERPRISE_ID_2,
+ NetworkCapabilities.NET_ENTERPRISE_ID_3,
+ NetworkCapabilities.NET_ENTERPRISE_ID_4,
+ NetworkCapabilities.NET_ENTERPRISE_ID_5
+ })
+
+ public @interface EnterpriseId {}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 77e58aa..ee646d9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5641,6 +5641,13 @@
"telephony_data_handover_retry_rules_string_array";
/**
+ * Indicates whether delay tearing down IMS data network until voice call ends.
+ * @hide
+ */
+ public static final String KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL =
+ "delay_ims_tear_down_until_call_end_bool";
+
+ /**
* The patterns of missed incoming call sms. This is the regular expression used for
* matching the missed incoming call's date, time, and caller id. The pattern should match
* fields for at least month, day, hour, and minute. Year is optional although it is encouraged.
@@ -6458,6 +6465,7 @@
KEY_TELEPHONY_DATA_HANDOVER_RETRY_RULES_STRING_ARRAY, new String[] {
"retry_interval=1000|2000|4000|8000|16000, maximum_retries=5"
});
+ sDefaults.putBoolean(KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL, false);
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 56bf303..3a3b363 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1083,6 +1083,13 @@
*/
public static final int REQUEST_NOT_SUPPORTED = 0x1000A;
+ /**
+ * An internal setup data error initiated by telephony that no retry should be performed.
+ *
+ * @hide
+ */
+ public static final int NO_RETRY_FAILURE = 0x1000B;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
@@ -1515,6 +1522,8 @@
sFailCauseMap.put(DUPLICATE_CID, "DUPLICATE_CID");
sFailCauseMap.put(NO_DEFAULT_DATA, "NO_DEFAULT_DATA");
sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
+ sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED");
+ sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE");
}
private DataFailCause() {
@@ -1565,6 +1574,7 @@
}
/** @hide */
+ // TODO: Migrated to DataConfigManager
public static boolean isPermanentFailure(@NonNull Context context,
@DataFailureCause int failCause,
int subId) {
@@ -1621,6 +1631,7 @@
};
}
+ permanentFailureSet.add(NO_RETRY_FAILURE);
sPermanentFailureCache.put(subId, permanentFailureSet);
}
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index 957f683..1d7c18f 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -22,6 +22,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Objects;
@@ -76,7 +78,8 @@
/**
* @hide
*/
- DataSpecificRegistrationInfo(
+ @VisibleForTesting
+ public DataSpecificRegistrationInfo(
int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable,
boolean isEnDcAvailable, @Nullable VopsSupportInfo vops) {
this.maxDataCalls = maxDataCalls;
@@ -186,7 +189,7 @@
/**
* @return The VOPS (Voice over Packet Switched) support information.
*
- * The instance of {@link LTEVopsSupportInfo}, or {@link NrVopsSupportInfo},
+ * The instance of {@link LteVopsSupportInfo}, or {@link NrVopsSupportInfo},
* null if there is there is no VOPS support information available.
*/
@Nullable
diff --git a/telephony/java/android/telephony/ImsiEncryptionInfo.java b/telephony/java/android/telephony/ImsiEncryptionInfo.java
index 4978692..82333a4 100644
--- a/telephony/java/android/telephony/ImsiEncryptionInfo.java
+++ b/telephony/java/android/telephony/ImsiEncryptionInfo.java
@@ -46,16 +46,17 @@
private final int keyType;
//Date-Time in UTC when the key will expire.
private final Date expirationTime;
+ private final int carrierId;
/** @hide */
public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
- byte[] key, Date expirationTime) {
- this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime);
+ byte[] key, Date expirationTime, int carrierId) {
+ this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime, carrierId);
}
/** @hide */
public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
- PublicKey publicKey, Date expirationTime) {
+ PublicKey publicKey, Date expirationTime, int carrierId) {
// todo need to validate that ImsiEncryptionInfo is being created with the correct params.
// Including validating that the public key is in "X.509" format. This will be done in
// a subsequent CL.
@@ -65,6 +66,7 @@
this.publicKey = publicKey;
this.keyIdentifier = keyIdentifier;
this.expirationTime = expirationTime;
+ this.carrierId = carrierId;
}
/** @hide */
@@ -78,6 +80,7 @@
keyIdentifier = in.readString();
keyType = in.readInt();
expirationTime = new Date(in.readLong());
+ carrierId = in.readInt();
}
/** @hide */
@@ -90,6 +93,11 @@
return this.mcc;
}
+ /** @hide */
+ public int getCarrierId() {
+ return carrierId;
+ }
+
/**
* Returns key identifier, a string that helps the authentication server to locate the
* private key to decrypt the permanent identity, or {@code null} when uavailable.
@@ -157,6 +165,7 @@
dest.writeString(keyIdentifier);
dest.writeInt(keyType);
dest.writeLong(expirationTime.getTime());
+ dest.writeInt(carrierId);
}
@Override
@@ -164,10 +173,11 @@
return "[ImsiEncryptionInfo "
+ "mcc=" + mcc
+ " mnc=" + mnc
- + " publicKey=" + publicKey
+ + ", publicKey=" + publicKey
+ ", keyIdentifier=" + keyIdentifier
+ ", keyType=" + keyType
+ ", expirationTime=" + expirationTime
+ + ", carrier_id=" + carrierId
+ "]";
}
}
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 6a80766..1a5a5ae 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -242,13 +242,16 @@
* @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
* information is not available.
* @param rplmn the registered plmn or the last plmn for attempted registration if reg failed.
+ * @param voiceSpecificInfo Voice specific registration information.
+ * @param dataSpecificInfo Data specific registration information.
*/
private NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
- @RegistrationState int registrationState,
- @NetworkType int accessNetworkTechnology, int rejectCause,
- boolean emergencyOnly,
- @Nullable @ServiceType List<Integer> availableServices,
- @Nullable CellIdentity cellIdentity, @Nullable String rplmn) {
+ @RegistrationState int registrationState,
+ @NetworkType int accessNetworkTechnology, int rejectCause,
+ boolean emergencyOnly, @Nullable @ServiceType List<Integer> availableServices,
+ @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
+ @Nullable VoiceSpecificRegistrationInfo voiceSpecificInfo,
+ @Nullable DataSpecificRegistrationInfo dataSpecificInfo) {
mDomain = domain;
mTransportType = transportType;
mRegistrationState = registrationState;
@@ -262,6 +265,10 @@
mEmergencyOnly = emergencyOnly;
mNrState = NR_STATE_NONE;
mRplmn = rplmn;
+ mVoiceSpecificInfo = voiceSpecificInfo;
+ mDataSpecificInfo = dataSpecificInfo;
+
+ updateNrState();
}
/**
@@ -276,10 +283,9 @@
boolean cssSupported, int roamingIndicator, int systemIsInPrl,
int defaultRoamingIndicator) {
this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
- emergencyOnly, availableServices, cellIdentity, rplmn);
-
- mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
- systemIsInPrl, defaultRoamingIndicator);
+ emergencyOnly, availableServices, cellIdentity, rplmn,
+ new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
+ systemIsInPrl, defaultRoamingIndicator), null);
}
/**
@@ -295,11 +301,9 @@
boolean isNrAvailable, boolean isEndcAvailable,
@Nullable VopsSupportInfo vopsSupportInfo) {
this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
- emergencyOnly, availableServices, cellIdentity, rplmn);
- mDataSpecificInfo = new DataSpecificRegistrationInfo(
- maxDataCalls, isDcNrRestricted, isNrAvailable,
- isEndcAvailable, vopsSupportInfo);
- updateNrState();
+ emergencyOnly, availableServices, cellIdentity, rplmn, null,
+ new DataSpecificRegistrationInfo(maxDataCalls, isDcNrRestricted, isNrAvailable,
+ isEndcAvailable, vopsSupportInfo));
}
private NetworkRegistrationInfo(Parcel source) {
@@ -804,6 +808,12 @@
@NonNull
private String mRplmn = "";
+ @Nullable
+ private DataSpecificRegistrationInfo mDataSpecificRegistrationInfo;
+
+ @Nullable
+ private VoiceSpecificRegistrationInfo mVoiceSpecificRegistrationInfo;
+
/**
* Default constructor for Builder.
*/
@@ -930,6 +940,30 @@
}
/**
+ * Set voice specific registration information.
+ *
+ * @param info The voice specific registration information.
+ * @return The builder.
+ * @hide
+ */
+ public @NonNull Builder setVoiceSpecificInfo(@NonNull VoiceSpecificRegistrationInfo info) {
+ mVoiceSpecificRegistrationInfo = info;
+ return this;
+ }
+
+ /**
+ * Set data specific registration information.
+ *
+ * @param info The data specific registration information.
+ * @return The builder.
+ * @hide
+ */
+ public @NonNull Builder setDataSpecificInfo(@NonNull DataSpecificRegistrationInfo info) {
+ mDataSpecificRegistrationInfo = info;
+ return this;
+ }
+
+ /**
* Build the NetworkRegistrationInfo.
* @return the NetworkRegistrationInfo object.
* @hide
@@ -938,7 +972,8 @@
public @NonNull NetworkRegistrationInfo build() {
return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
- mCellIdentity, mRplmn);
+ mCellIdentity, mRplmn, mVoiceSpecificRegistrationInfo,
+ mDataSpecificRegistrationInfo);
}
}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 9fd2ae4..753935a 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1205,7 +1205,15 @@
}
}
- private void init() {
+ /**
+ * Initialize the service state. Set everything to the default value.
+ *
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+ * {@link NetworkRegistrationInfo}.
+ */
+ private void init(boolean legacyMode) {
if (DBG) Rlog.d(LOG_TAG, "init");
mVoiceRegState = STATE_OUT_OF_SERVICE;
mDataRegState = STATE_OUT_OF_SERVICE;
@@ -1237,6 +1245,13 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
+ if (!legacyMode) {
+ addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+ .build());
+ }
}
mOperatorAlphaLongRaw = null;
mOperatorAlphaShortRaw = null;
@@ -1245,15 +1260,32 @@
}
public void setStateOutOfService() {
- init();
+ init(true);
}
public void setStateOff() {
- init();
+ init(true);
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
}
+ /**
+ * Set the service state to out-of-service
+ *
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+ * @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on).
+ * @hide
+ */
+ public void setOutOfService(boolean legacyMode, boolean powerOff) {
+ init(legacyMode);
+ if (powerOff) {
+ mVoiceRegState = STATE_POWER_OFF;
+ mDataRegState = STATE_POWER_OFF;
+ }
+ }
+
public void setState(int state) {
setVoiceRegState(state);
if (DBG) Rlog.e(LOG_TAG, "[ServiceState] setState deprecated use setVoiceRegState()");
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c6c797e..4b8b590 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2792,10 +2792,43 @@
* outlined above.
* @throws IllegalArgumentException if plans don't meet the requirements
* defined in {@link SubscriptionPlan}.
+ * @deprecated use {@link #setSubscriptionPlans(int, List, long)} instead.
*/
+ @Deprecated
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
+ setSubscriptionPlans(subId, plans, 0);
+ }
+
+ /**
+ * Set the description of the billing relationship plan between a carrier
+ * and a specific subscriber.
+ * <p>
+ * This method is only accessible to the following narrow set of apps:
+ * <ul>
+ * <li>The carrier app for this subscriberId, as determined by
+ * {@link TelephonyManager#hasCarrierPrivileges()}.
+ * <li>The carrier app explicitly delegated access through
+ * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+ * </ul>
+ *
+ * @param subId the subscriber this relationship applies to. An empty list
+ * may be sent to clear any existing plans.
+ * @param plans the list of plans. The first plan is always the primary and
+ * most important plan. Any additional plans are secondary and
+ * may not be displayed or used by decision making logic.
+ * @param expirationDurationMillis the duration after which the subscription plans
+ * will be automatically cleared, or {@code 0} to leave the plans until
+ * explicitly cleared, or the next reboot, whichever happens first.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
+ * @throws IllegalArgumentException if plans don't meet the requirements
+ * defined in {@link SubscriptionPlan}.
+ */
+ public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans,
+ @DurationMillisLong long expirationDurationMillis) {
getNetworkPolicyManager().setSubscriptionPlans(subId,
- plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName());
+ plans.toArray(new SubscriptionPlan[0]), expirationDurationMillis,
+ mContext.getOpPackageName());
}
/**
@@ -2814,17 +2847,17 @@
* @param subId the subscriber this override applies to.
* @param overrideUnmetered set if the billing relationship should be
* considered unmetered.
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
*/
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
setSubscriptionOverrideUnmetered(subId, overrideUnmetered,
- TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+ TelephonyManager.getAllNetworkTypes(), expirationDurationMillis);
}
/**
@@ -2846,8 +2879,8 @@
* @param networkTypes the network types this override applies to. If no
* network types are specified, override values will be ignored.
* {@see TelephonyManager#getAllNetworkTypes()}
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
@@ -2855,10 +2888,10 @@
*/
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@NonNull @Annotation.NetworkType int[] networkTypes,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0;
getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED,
- overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
+ overrideValue, networkTypes, expirationDurationMillis, mContext.getOpPackageName());
}
/**
@@ -2878,17 +2911,17 @@
* @param subId the subscriber this override applies to.
* @param overrideCongested set if the subscription should be considered
* congested.
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
*/
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
setSubscriptionOverrideCongested(subId, overrideCongested,
- TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+ TelephonyManager.getAllNetworkTypes(), expirationDurationMillis);
}
/**
@@ -2911,8 +2944,8 @@
* @param networkTypes the network types this override applies to. If no
* network types are specified, override values will be ignored.
* {@see TelephonyManager#getAllNetworkTypes()}
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
@@ -2920,10 +2953,10 @@
*/
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
@NonNull @Annotation.NetworkType int[] networkTypes,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0;
getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED,
- overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
+ overrideValue, networkTypes, expirationDurationMillis, mContext.getOpPackageName());
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 63ff232..db1f497 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -118,6 +118,7 @@
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
+import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.OperatorInfo;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
@@ -140,6 +141,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
@@ -3475,15 +3477,39 @@
* @see #SIM_STATE_PRESENT
*
* @hide
+ * @deprecated instead use {@link #getSimCardState(int, int)}
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Deprecated
public @SimState int getSimCardState(int physicalSlotIndex) {
- int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
+ int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, DEFAULT_PORT_INDEX));
return getSimCardStateFromSimState(simState);
}
/**
+ * Returns a constant indicating the state of the device SIM card in a physical slot and
+ * port index.
+ *
+ * @param physicalSlotIndex physical slot index
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ *
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_ABSENT
+ * @see #SIM_STATE_CARD_IO_ERROR
+ * @see #SIM_STATE_CARD_RESTRICTED
+ * @see #SIM_STATE_PRESENT
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @SimState int getSimCardState(int physicalSlotIndex, int portIndex) {
+ int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, portIndex));
+ return getSimCardStateFromSimState(simState);
+ }
+ /**
* Converts SIM state to SIM card state.
* @param simState
* @return SIM card state
@@ -3503,13 +3529,19 @@
/**
* Converts a physical slot index to logical slot index.
* @param physicalSlotIndex physical slot index
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
* @return logical slot index
*/
- private int getLogicalSlotIndex(int physicalSlotIndex) {
+ private int getLogicalSlotIndex(int physicalSlotIndex, int portIndex) {
UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length
&& slotInfos[physicalSlotIndex] != null) {
- return slotInfos[physicalSlotIndex].getLogicalSlotIdx();
+ for (UiccPortInfo portInfo : slotInfos[physicalSlotIndex].getPorts()) {
+ if (portInfo.getPortIndex() == portIndex) {
+ return portInfo.getLogicalSlotIndex();
+ }
+ }
}
return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
@@ -3549,12 +3581,42 @@
* @see #SIM_STATE_LOADED
*
* @hide
+ * @deprecated instead use {@link #getSimApplicationState(int, int)}
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Deprecated
public @SimState int getSimApplicationState(int physicalSlotIndex) {
int simState =
- SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+ DEFAULT_PORT_INDEX));
+ return getSimApplicationStateFromSimState(simState);
+ }
+
+ /**
+ * Returns a constant indicating the state of the card applications on the device SIM card in
+ * a physical slot.
+ *
+ * @param physicalSlotIndex physical slot index
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ *
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_PIN_REQUIRED
+ * @see #SIM_STATE_PUK_REQUIRED
+ * @see #SIM_STATE_NETWORK_LOCKED
+ * @see #SIM_STATE_NOT_READY
+ * @see #SIM_STATE_PERM_DISABLED
+ * @see #SIM_STATE_LOADED
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @SimState int getSimApplicationState(int physicalSlotIndex, int portIndex) {
+ int simState =
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+ portIndex));
return getSimApplicationStateFromSimState(simState);
}
@@ -4153,18 +4215,21 @@
* should be {@link #getPhoneCount()} if success, otherwise return an empty map.
*
* @hide
+ * @deprecated use {@link #getSimSlotMapping()} instead.
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@NonNull
+ @Deprecated
public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
Map<Integer, Integer> slotMapping = new HashMap<>();
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- int[] slotMappingArray = telephony.getSlotsMapping(mContext.getOpPackageName());
- for (int i = 0; i < slotMappingArray.length; i++) {
- slotMapping.put(i, slotMappingArray[i]);
+ List<UiccSlotMapping> simSlotsMapping = telephony.getSlotsMapping(
+ mContext.getOpPackageName());
+ for (UiccSlotMapping slotMap : simSlotsMapping) {
+ slotMapping.put(slotMap.getLogicalSlotIndex(), slotMap.getPhysicalSlotIndex());
}
}
} catch (RemoteException e) {
@@ -4173,6 +4238,33 @@
return slotMapping;
}
+ /**
+ * Get the mapping from logical slots to physical sim slots and port indexes. Initially the
+ * logical slot index was mapped to physical slot index, but with support for multi-enabled
+ * profile(MEP) logical slot is now mapped to port index.
+ *
+ * @return a collection of {@link UiccSlotMapping} which indicates the mapping from logical
+ * slots to ports and physical slots.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @NonNull
+ public Collection<UiccSlotMapping> getSimSlotMapping() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ slotMap = telephony.getSlotsMapping(mContext.getOpPackageName());
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ return slotMap;
+ }
//
//
// Subscriber Info
@@ -6684,17 +6776,24 @@
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
* @hide
+ * @deprecated instead use {@link #iccOpenLogicalChannelByPort(int, int, String, int)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
@Nullable
+ @Deprecated
public IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int slotIndex,
@Nullable String aid, int p2) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.iccOpenLogicalChannelBySlot(slotIndex, getOpPackageName(), aid,
- p2);
+ IccLogicalChannelRequest request = new IccLogicalChannelRequest();
+ request.slotIndex = slotIndex;
+ request.aid = aid;
+ request.p2 = p2;
+ request.callingPackage = getOpPackageName();
+ request.binder = new Binder();
+ return telephony.iccOpenLogicalChannel(request);
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -6703,6 +6802,58 @@
}
/**
+ * Opens a logical channel to the ICC card using the physical slot index and port index.
+ *
+ * Use this method when no subscriptions are available on the SIM and the operation must be
+ * performed using the physical slot index and port index.
+ *
+ * This operation wraps two APDU instructions:
+ * <ul>
+ * <li>MANAGE CHANNEL to open a logical channel</li>
+ * <li>SELECT the given {@code AID} using the given {@code p2}</li>
+ * </ul>
+ *
+ * Per Open Mobile API Specification v3.2 section 6.2.7.h, only p2 values of 0x00, 0x04, 0x08,
+ * and 0x0C are guaranteed to be supported.
+ *
+ * If the SELECT command's status word is not '9000', '62xx', or '63xx', the status word will be
+ * considered an error and the channel shall not be opened.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHO command.
+ *
+ * @param slotIndex the physical slot index of the ICC card
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ * @param aid Application id. See ETSI 102.221 and 101.220.
+ * @param p2 P2 parameter (described in ISO 7816-4).
+ * @return an IccOpenLogicalChannelResponse object.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
+ @NonNull
+ public IccOpenLogicalChannelResponse iccOpenLogicalChannelByPort(int slotIndex,
+ int portIndex, @Nullable String aid, int p2) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IccLogicalChannelRequest request = new IccLogicalChannelRequest();
+ request.slotIndex = slotIndex;
+ request.portIndex = portIndex;
+ request.aid = aid;
+ request.p2 = p2;
+ request.callingPackage = getOpPackageName();
+ request.binder = new Binder();
+ return telephony.iccOpenLogicalChannel(request);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Opens a logical channel to the ICC card.
*
* This operation wraps two APDU instructions:
@@ -6761,8 +6912,15 @@
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
try {
ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.iccOpenLogicalChannel(subId, getOpPackageName(), AID, p2);
+ if (telephony != null) {
+ IccLogicalChannelRequest request = new IccLogicalChannelRequest();
+ request.subId = subId;
+ request.callingPackage = getOpPackageName();
+ request.aid = AID;
+ request.p2 = p2;
+ request.binder = new Binder();
+ return telephony.iccOpenLogicalChannel(request);
+ }
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -6785,14 +6943,19 @@
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
* @hide
+ * @deprecated instead use {@link #iccCloseLogicalChannelByPort(int, int, int)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
+ @Deprecated
public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.iccCloseLogicalChannelBySlot(slotIndex, channel);
+ IccLogicalChannelRequest request = new IccLogicalChannelRequest();
+ request.slotIndex = slotIndex;
+ request.channel = channel;
+ return telephony.iccCloseLogicalChannel(request);
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -6801,6 +6964,45 @@
}
/**
+ * Closes a previously opened logical channel to the ICC card using the physical slot index and
+ * port index.
+ *
+ * Use this method when no subscriptions are available on the SIM and the operation must be
+ * performed using the physical slot index and port index.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHC command.
+ *
+ * @param slotIndex the physical slot index of the ICC card
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ * @param channel is the channel id to be closed as returned by a successful
+ * iccOpenLogicalChannel.
+ *
+ * @throws IllegalStateException if the Telephony process is not currently available or modem
+ * currently can't process this command.
+ * @throws IllegalArgumentException if invalid arguments are passed.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
+ public void iccCloseLogicalChannelByPort(int slotIndex, int portIndex, int channel) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IccLogicalChannelRequest request = new IccLogicalChannelRequest();
+ request.slotIndex = slotIndex;
+ request.portIndex = portIndex;
+ request.channel = channel;
+ telephony.iccCloseLogicalChannel(request);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Closes a previously opened logical channel to the ICC card.
*
* Input parameters equivalent to TS 27.007 AT+CCHC command.
@@ -6835,8 +7037,12 @@
public boolean iccCloseLogicalChannel(int subId, int channel) {
try {
ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.iccCloseLogicalChannel(subId, channel);
+ if (telephony != null) {
+ IccLogicalChannelRequest request = new IccLogicalChannelRequest();
+ request.subId = subId;
+ request.channel = channel;
+ return telephony.iccCloseLogicalChannel(request);
+ }
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -6867,17 +7073,20 @@
* @return The APDU response from the ICC card with the status appended at the end, or null if
* there is an issue connecting to the Telephony service.
* @hide
+ * @deprecated instead use
+ * {@link #iccTransmitApduLogicalChannelByPort(int, int, int, int, int, int, int, int, String)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
@Nullable
+ @Deprecated
public String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla,
int instruction, int p1, int p2, int p3, @Nullable String data) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.iccTransmitApduLogicalChannelBySlot(slotIndex, channel, cla,
- instruction, p1, p2, p3, data);
+ return telephony.iccTransmitApduLogicalChannelByPort(slotIndex, DEFAULT_PORT_INDEX,
+ channel, cla, instruction, p1, p2, p3, data);
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -6886,6 +7095,50 @@
}
/**
+ * Transmit an APDU to the ICC card over a logical channel using the physical slot index.
+ *
+ * Use this method when no subscriptions are available on the SIM and the operation must be
+ * performed using the physical slot index.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CGLA command.
+ *
+ * @param slotIndex the physical slot index of the ICC card
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ * @param channel is the channel id to be closed as returned by a successful
+ * iccOpenLogicalChannel.
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at the end, or null if
+ * there is an issue connecting to the Telephony service.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
+ @NonNull
+ public String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel,
+ int cla, int instruction, int p1, int p2, int p3, @Nullable String data) {
+ String response;
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ response = telephony.iccTransmitApduLogicalChannelByPort(slotIndex, portIndex,
+ channel, cla, instruction, p1, p2, p3, data);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ return response;
+ }
+
+ /**
* Transmit an APDU to the ICC card over a logical channel.
*
* Input parameters equivalent to TS 27.007 AT+CGLA command.
@@ -6970,17 +7223,20 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
* @hide
+ * @deprecated instead use
+ * {@link #iccTransmitApduBasicChannelByPort(int, int, int, int, int, int, int, String)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
@NonNull
+ @Deprecated
public String iccTransmitApduBasicChannelBySlot(int slotIndex, int cla, int instruction, int p1,
int p2, int p3, @Nullable String data) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.iccTransmitApduBasicChannelBySlot(slotIndex, getOpPackageName(),
- cla, instruction, p1, p2, p3, data);
+ return telephony.iccTransmitApduBasicChannelByPort(slotIndex, DEFAULT_PORT_INDEX,
+ getOpPackageName(), cla, instruction, p1, p2, p3, data);
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -6989,6 +7245,47 @@
}
/**
+ * Transmit an APDU to the ICC card over the basic channel using the physical slot index.
+ *
+ * Use this method when no subscriptions are available on the SIM and the operation must be
+ * performed using the physical slot index.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CSIM command.
+ *
+ * @param slotIndex the physical slot index of the ICC card to target
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
+ @NonNull
+ public String iccTransmitApduBasicChannelByPort(int slotIndex, int portIndex, int cla,
+ int instruction, int p1, int p2, int p3, @Nullable String data) {
+ String response;
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ response = telephony.iccTransmitApduBasicChannelByPort(slotIndex, portIndex,
+ getOpPackageName(), cla, instruction, p1, p2, p3, data);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ return response;
+ }
+ /**
* Transmit an APDU to the ICC card over the basic channel.
*
* Input parameters equivalent to TS 27.007 AT+CSIM command.
@@ -9306,15 +9603,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @Nullable String getCarrierServicePackageName() {
- // TODO(b/205736323) plumb this through to CarrierPrivilegesTracker, which will cache the
- // value instead of re-querying every time.
- List<String> carrierServicePackages =
- getCarrierPackageNamesForIntent(
- new Intent(CarrierService.CARRIER_SERVICE_INTERFACE));
- if (carrierServicePackages != null && !carrierServicePackages.isEmpty()) {
- return carrierServicePackages.get(0);
- }
- return null;
+ return getCarrierServicePackageNameForLogicalSlot(getPhoneId());
}
/**
@@ -9331,13 +9620,15 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
- // TODO(b/205736323) plumb this through to CarrierPrivilegesTracker, which will cache the
- // value instead of re-querying every time.
- List<String> carrierServicePackages =
- getCarrierPackageNamesForIntentAndPhone(
- new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), logicalSlotIndex);
- if (carrierServicePackages != null && !carrierServicePackages.isEmpty()) {
- return carrierServicePackages.get(0);
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCarrierServicePackageNameForLogicalSlot(logicalSlotIndex);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getCarrierServicePackageNameForLogicalSlot RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getCarrierServicePackageNameForLogicalSlot NPE", ex);
}
return null;
}
@@ -16135,12 +16426,15 @@
}
/**
- * Callback to listen for when the set of packages with carrier privileges for a SIM changes.
+ * Callbacks to listen for when the set of packages with carrier privileges for a SIM changes.
+ *
+ * <p>Of note, when multiple callbacks are registered, they may be triggered one after another.
+ * The ordering of them is not guaranteed and thus should not be depend on.
*
* @hide
*/
@SystemApi
- public interface CarrierPrivilegesListener {
+ public interface CarrierPrivilegesCallback {
/**
* Called when the set of packages with carrier privileges has changed.
*
@@ -16150,59 +16444,81 @@
* <p>At registration, the callback will receive the current set of privileged packages.
*
* @param privilegedPackageNames The updated set of package names that have carrier
- * privileges
- * @param privilegedUids The updated set of UIDs that have carrier privileges
+ * privileges
+ * @param privilegedUids The updated set of UIDs that have carrier privileges
*/
void onCarrierPrivilegesChanged(
- @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids);
+ @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids);
+
+ /**
+ * Called when the {@link CarrierService} for the current user profile has changed.
+ *
+ * <p>This method does nothing by default. Clients that are interested in the carrier
+ * service change should override this method to get package name and UID info.
+ *
+ * <p>At registration, the callback will receive the current carrier service info.
+ *
+ * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+ * switch and the same carrier service remains after switch.
+ *
+ * @param carrierServicePackageName package name of the {@link CarrierService}. May be
+ * {@code null} when no carrier service is detected.
+ * @param carrierServiceUid UID of the {@link CarrierService}. May be
+ * {@link android.os.Process#INVALID_UID} if no carrier
+ * service is detected.
+ */
+ default void onCarrierServiceChanged(
+ @Nullable String carrierServicePackageName, int carrierServiceUid) {
+ // do nothing by default
+ }
}
/**
- * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
+ * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
* receive callbacks when the set of packages with carrier privileges changes. The callback will
* immediately be called with the latest state.
*
* @param logicalSlotIndex The SIM slot to listen on
- * @param executor The executor where {@code listener} will be invoked
- * @param listener The callback to register
+ * @param executor The executor where {@code callback} will be invoked
+ * @param callback The callback to register
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void addCarrierPrivilegesListener(
+ public void registerCarrierPrivilegesCallback(
int logicalSlotIndex,
@NonNull @CallbackExecutor Executor executor,
- @NonNull CarrierPrivilegesListener listener) {
+ @NonNull CarrierPrivilegesCallback callback) {
if (mContext == null) {
throw new IllegalStateException("Telephony service is null");
- } else if (executor == null || listener == null) {
+ } else if (executor == null || callback == null) {
throw new IllegalArgumentException(
- "CarrierPrivilegesListener and executor must be non-null");
+ "CarrierPrivilegesCallback and executor must be non-null");
}
mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
if (mTelephonyRegistryMgr == null) {
throw new IllegalStateException("Telephony registry service is null");
}
- mTelephonyRegistryMgr.addCarrierPrivilegesListener(logicalSlotIndex, executor, listener);
+ mTelephonyRegistryMgr.addCarrierPrivilegesCallback(logicalSlotIndex, executor, callback);
}
/**
- * Unregisters an existing {@link CarrierPrivilegesListener}.
+ * Unregisters an existing {@link CarrierPrivilegesCallback}.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
+ public void unregisterCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
if (mContext == null) {
throw new IllegalStateException("Telephony service is null");
- } else if (listener == null) {
- throw new IllegalArgumentException("CarrierPrivilegesListener must be non-null");
+ } else if (callback == null) {
+ throw new IllegalArgumentException("CarrierPrivilegesCallback must be non-null");
}
mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
if (mTelephonyRegistryMgr == null) {
throw new IllegalStateException("Telephony registry service is null");
}
- mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
+ mTelephonyRegistryMgr.removeCarrierPrivilegesCallback(callback);
}
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index f854020..281b018 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1272,24 +1272,34 @@
*/
public boolean similar(ApnSetting other) {
return (!this.canHandleType(TYPE_DUN)
- && !other.canHandleType(TYPE_DUN)
- && Objects.equals(this.mApnName, other.mApnName)
- && !typeSameAny(this, other)
- && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
- && xorEqualsInt(this.mProxyPort, other.mProxyPort)
- && xorEquals(this.mProtocol, other.mProtocol)
- && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(this.mProfileId, other.mProfileId)
- && Objects.equals(this.mMvnoType, other.mMvnoType)
- && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
- && xorEquals(this.mMmsc, other.mMmsc)
- && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
- && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
- && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId)
- && Objects.equals(mCarrierId, other.mCarrierId)
- && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
+ && xorEqualsInt(this.mProxyPort, other.mProxyPort)
+ && xorEquals(this.mMmsc, other.mMmsc)
+ && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
+ && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
+ && xorEqualsString(this.mUser, other.mUser)
+ && xorEqualsString(this.mPassword, other.mPassword)
+ && xorEqualsInt(this.mAuthType, other.mAuthType)
+ && !typeSameAny(this, other)
+ && Objects.equals(this.mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(this.mProtocol, other.mProtocol)
+ && Objects.equals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && xorEqualsInt(this.mMtuV4, other.mMtuV4)
+ && xorEqualsInt(this.mMtuV6, other.mMtuV6)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(this.mLingeringNetworkTypeBitmask,
+ other.mLingeringNetworkTypeBitmask)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mPersistent, other.mPersistent)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(this.mApnSetId, other.mApnSetId)
+ && Objects.equals(this.mCarrierId, other.mCarrierId)
+ && Objects.equals(this.mSkip464Xlat, other.mSkip464Xlat)
+ && Objects.equals(this.mAlwaysOn, other.mAlwaysOn);
}
// Equal or one is null.
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index ec04c1a..0b361dc 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -26,10 +26,10 @@
import android.net.NetworkCapabilities;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.NetCapability;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
+import android.telephony.data.ApnSetting.ApnType;
import android.telephony.data.ApnSetting.AuthType;
import android.text.TextUtils;
@@ -245,8 +245,7 @@
* @return The supported APN types bitmask.
* @deprecated Use {@link #getApnSetting()} and {@link ApnSetting#getApnTypeBitmask()} instead.
*/
- @Deprecated
- public @ApnType int getSupportedApnTypesBitmask() {
+ @Deprecated public @ApnType int getSupportedApnTypesBitmask() {
if (mApnSetting != null) {
return mApnSetting.getApnTypeBitmask();
}
@@ -425,6 +424,12 @@
return ApnSetting.TYPE_MCX;
case NetworkCapabilities.NET_CAPABILITY_IA:
return ApnSetting.TYPE_IA;
+ case NetworkCapabilities.NET_CAPABILITY_BIP:
+ return ApnSetting.TYPE_BIP;
+ case NetworkCapabilities.NET_CAPABILITY_VSIM:
+ return ApnSetting.TYPE_VSIM;
+ case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE:
+ return ApnSetting.TYPE_ENTERPRISE;
default:
return ApnSetting.TYPE_NONE;
}
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
index 2178fc1..66dcf8f 100644
--- a/telephony/java/android/telephony/data/TrafficDescriptor.java
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -21,8 +21,13 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for UE Route Selection
@@ -31,24 +36,215 @@
* not specify the end point to be used for the data call.
*/
public final class TrafficDescriptor implements Parcelable {
+ /**
+ * The OS/App id
+ *
+ * @hide
+ */
+ public static final class OsAppId {
+ /**
+ * OSId for "Android", using UUID version 5 with namespace ISO OSI.
+ * Prepended to the OsAppId in TrafficDescriptor to use for URSP matching.
+ */
+ public static final UUID ANDROID_OS_ID =
+ UUID.fromString("97a498e3-fc92-5c94-8986-0333d06e4e47");
+
+ /**
+ * Allowed app ids.
+ */
+ // The following app ids are the only apps id Android supports. OEMs or vendors are
+ // prohibited to modify/extend the allowed list, especially passing the real package name to
+ // the network.
+ private static final Set<String> ALLOWED_APP_IDS = Set.of(
+ "ENTERPRISE", "PRIORITIZE_LATENCY", "PRIORITIZE_BANDWIDTH", "CBS"
+ );
+
+ /** OS id in UUID format. */
+ private final @NonNull UUID mOsId;
+
+ /**
+ * App id in string format. Note that Android will not allow use specific app id. This must
+ * be a category/capability identifier.
+ */
+ private final @NonNull String mAppId;
+
+ /**
+ * The differentiator when multiple traffic descriptor has the same OS and app id. Must be
+ * greater than 1.
+ */
+ private final int mDifferentiator;
+
+ /**
+ * Constructor
+ *
+ * @param osId OS id in UUID format.
+ * @param appId App id in string format. Note that Android will not allow use specific app
+ * id. This must be a category/capability identifier.
+ */
+ public OsAppId(@NonNull UUID osId, @NonNull String appId) {
+ this(osId, appId, 1);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param osId OS id in UUID format.
+ * @param appId App id in string format. Note that Android will not allow use specific app
+ * id. This must be a category/capability identifier.
+ * @param differentiator The differentiator when multiple traffic descriptor has the same
+ * OS and app id. Must be greater than 0.
+ */
+ public OsAppId(@NonNull UUID osId, @NonNull String appId, int differentiator) {
+ Objects.requireNonNull(osId);
+ Objects.requireNonNull(appId);
+ if (differentiator < 1) {
+ throw new IllegalArgumentException("Invalid differentiator " + differentiator);
+ }
+
+ mOsId = osId;
+ mAppId = appId;
+ mDifferentiator = differentiator;
+ }
+
+ /**
+ * Constructor from raw byte array.
+ *
+ * @param rawOsAppId The raw OS/App id.
+ */
+ public OsAppId(@NonNull byte[] rawOsAppId) {
+ try {
+ ByteBuffer bb = ByteBuffer.wrap(rawOsAppId);
+ // OS id is the first 16 bytes.
+ mOsId = new UUID(bb.getLong(), bb.getLong());
+ // App id length is 1 byte.
+ int appIdLen = bb.get();
+ // The remaining is the app id + differentiator.
+ byte[] appIdAndDifferentiator = new byte[appIdLen];
+ bb.get(appIdAndDifferentiator, 0, appIdLen);
+ // Extract trailing numbers, for example, "ENTERPRISE", "ENTERPRISE3".
+ String appIdAndDifferentiatorStr = new String(appIdAndDifferentiator);
+ Pattern pattern = Pattern.compile("[^0-9]+([0-9]+)$");
+ Matcher matcher = pattern.matcher(new String(appIdAndDifferentiator));
+ if (matcher.find()) {
+ mDifferentiator = Integer.parseInt(matcher.group(1));
+ mAppId = appIdAndDifferentiatorStr.replace(matcher.group(1), "");
+ } else {
+ mDifferentiator = 1;
+ mAppId = appIdAndDifferentiatorStr;
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to decode " + (rawOsAppId != null
+ ? new BigInteger(1, rawOsAppId).toString(16) : null));
+ }
+ }
+
+ /**
+ * @return The OS id in UUID format.
+ */
+ public @NonNull UUID getOsId() {
+ return mOsId;
+ }
+
+ /**
+ * @return App id in string format. Note that Android will not allow use specific app id.
+ * This must be a category/capability identifier.
+ */
+ public @NonNull String getAppId() {
+ return mAppId;
+ }
+
+ /**
+ * @return The differentiator when multiple traffic descriptor has the same OS and app id.
+ * Must be greater than 1.
+ */
+ public int getDifferentiator() {
+ return mDifferentiator;
+ }
+
+ /**
+ * @return OS/App id in raw byte format.
+ */
+ public @NonNull byte[] getBytes() {
+ byte[] osAppId = (mAppId + (mDifferentiator > 1 ? mDifferentiator : "")).getBytes();
+ // 16 bytes for UUID, 1 byte for length of osAppId, and up to 255 bytes for osAppId
+ ByteBuffer bb = ByteBuffer.allocate(16 + 1 + osAppId.length);
+ bb.putLong(mOsId.getMostSignificantBits());
+ bb.putLong(mOsId.getLeastSignificantBits());
+ bb.put((byte) osAppId.length);
+ bb.put(osAppId);
+ return bb.array();
+ }
+
+ @Override
+ public String toString() {
+ return "[OsAppId: OS=" + mOsId + ", App=" + mAppId + ", differentiator="
+ + mDifferentiator + ", raw="
+ + new BigInteger(1, getBytes()).toString(16) + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ OsAppId osAppId = (OsAppId) o;
+ return mDifferentiator == osAppId.mDifferentiator && mOsId.equals(osAppId.mOsId)
+ && mAppId.equals(osAppId.mAppId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mOsId, mAppId, mDifferentiator);
+ }
+ }
+
private final String mDnn;
- private final byte[] mOsAppId;
+ private final OsAppId mOsAppId;
private TrafficDescriptor(@NonNull Parcel in) {
mDnn = in.readString();
- mOsAppId = in.createByteArray();
+ byte[] osAppIdBytes = in.createByteArray();
+ OsAppId osAppId = null;
+ if (osAppIdBytes != null) {
+ osAppId = new OsAppId(osAppIdBytes);
+ }
+ mOsAppId = osAppId;
+
+ enforceAllowedIds();
}
/**
* Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
* @param dnn optional DNN, which must be used for traffic matching, if present
- * @param osAppId OsId + osAppId of the traffic descriptor
+ * @param osAppIdRawBytes Raw bytes of OsId + osAppId of the traffic descriptor
*
* @hide
*/
- public TrafficDescriptor(String dnn, byte[] osAppId) {
+ public TrafficDescriptor(String dnn, @Nullable byte[] osAppIdRawBytes) {
mDnn = dnn;
+ OsAppId osAppId = null;
+ if (osAppIdRawBytes != null) {
+ osAppId = new OsAppId(osAppIdRawBytes);
+ }
mOsAppId = osAppId;
+
+ enforceAllowedIds();
+ }
+
+ /**
+ * Enforce the OS id and app id are in the allowed list.
+ *
+ * @throws IllegalArgumentException if ids are not allowed.
+ */
+ private void enforceAllowedIds() {
+ if (mOsAppId != null && !mOsAppId.getOsId().equals(OsAppId.ANDROID_OS_ID)) {
+ throw new IllegalArgumentException("OS id " + mOsAppId.getOsId() + " does not match "
+ + OsAppId.ANDROID_OS_ID);
+ }
+
+ if (mOsAppId != null && !OsAppId.ALLOWED_APP_IDS.contains(mOsAppId.getAppId())) {
+ throw new IllegalArgumentException("Illegal app id " + mOsAppId.getAppId()
+ + ". Only allowing one of the following " + OsAppId.ALLOWED_APP_IDS);
+ }
}
/**
@@ -61,13 +257,13 @@
}
/**
- * OsAppId is the app id as defined in 3GPP TS 24.526 Section 5.2, and it identifies a traffic
- * category. It includes the OS Id component of the field as defined in the specs.
- * @return the OS App ID of this traffic descriptor if one is included by the network, null
- * otherwise.
+ * OsAppId identifies a broader traffic category. Although it names Os/App id, it only includes
+ * OS version with a general/broader category id used as app id.
+ *
+ * @return The id in byte format. {@code null} if not available.
*/
public @Nullable byte[] getOsAppId() {
- return mOsAppId;
+ return mOsAppId != null ? mOsAppId.getBytes() : null;
}
@Override
@@ -77,13 +273,13 @@
@NonNull @Override
public String toString() {
- return "TrafficDescriptor={mDnn=" + mDnn + ", mOsAppId=" + mOsAppId + "}";
+ return "TrafficDescriptor={mDnn=" + mDnn + ", " + mOsAppId + "}";
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mDnn);
- dest.writeByteArray(mOsAppId);
+ dest.writeByteArray(mOsAppId != null ? mOsAppId.getBytes() : null);
}
public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR =
@@ -104,7 +300,7 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrafficDescriptor that = (TrafficDescriptor) o;
- return Objects.equals(mDnn, that.mDnn) && Arrays.equals(mOsAppId, that.mOsAppId);
+ return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId);
}
@Override
@@ -148,7 +344,7 @@
}
/**
- * Set the OS App ID (including OS Id as defind in the specs).
+ * Set the OS App ID (including OS Id as defined in the specs).
*
* @return The same instance of the builder.
*/
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 45022a6..aa514b9 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -16,6 +16,7 @@
package android.telephony.euicc;
import android.Manifest;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -28,6 +29,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyFrameworkInitializer;
@@ -35,11 +37,13 @@
import android.telephony.euicc.EuiccCardManager.ResetOption;
import com.android.internal.telephony.euicc.IEuiccController;
+import com.android.internal.telephony.euicc.IResultCallback;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/**
@@ -215,6 +219,20 @@
"android.telephony.euicc.action.START_EUICC_ACTIVATION";
/**
+ * Result codes passed to the ResultListener by
+ * {@link #switchToSubscription(int, int, Executor, ResultListener)}
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"EMBEDDED_SUBSCRIPTION_RESULT_"}, value = {
+ EMBEDDED_SUBSCRIPTION_RESULT_OK,
+ EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
+ EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
+ })
+ public @interface ResultCode{}
+
+ /**
* Result code for an operation indicating that the operation succeeded.
*/
public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0;
@@ -1125,7 +1143,12 @@
* permission, or the calling app must be authorized to manage the active subscription on
* the target eUICC.
* @param callbackIntent a PendingIntent to launch when the operation completes.
+ *
+ * @deprecated From T, callers should use
+ * {@link #switchToSubscription(int, int, Executor, ResultListener)} instead to specify a port
+ * index on the card to switch to.
*/
+ @Deprecated
@RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
if (!isEnabled()) {
@@ -1141,6 +1164,71 @@
}
/**
+ * Switch to (enable) the given subscription.
+ *
+ * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
+ * or the calling app must be authorized to manage both the currently-active subscription and
+ * the subscription to be enabled according to the subscription metadata. Without the former,
+ * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+ * intent to prompt the user to accept the download.
+ *
+ * <p>On a multi-active SIM device, requires the
+ * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
+ * only if the targeted eUICC does not currently have an active subscription or the calling app
+ * is authorized to manage the active subscription on the target eUICC, and the calling app is
+ * authorized to manage any active subscription on any SIM. Without it, an
+ * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+ * intent to prompt the user to accept the download. The caller should also be authorized to
+ * manage the subscription to be enabled.
+ *
+ * @param subscriptionId the ID of the subscription to enable. May be
+ * {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
+ * current profile without activating another profile to replace it. If it's a disable
+ * operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
+ * permission, or the calling app must be authorized to manage the active subscription on
+ * the target eUICC.
+ * @param portIndex the index of the port to target for the enabled subscription
+ * @param executor an Executor on which to run the callback
+ * @param callback a {@link ResultListener} which will run when the operation completes
+ */
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+ public void switchToSubscription(int subscriptionId, int portIndex,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull ResultListener callback) {
+ if (!isEnabled()) {
+ sendUnavailableErrorToCallback(executor, callback);
+ return;
+ }
+ try {
+ IResultCallback internalCallback = new IResultCallback.Stub() {
+ @Override
+ public void onComplete(int result, Intent resultIntent) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> callback.onComplete(result, resultIntent)));
+ }
+ };
+ getIEuiccController().switchToSubscriptionWithPort(mCardId, portIndex,
+ subscriptionId, mContext.getOpPackageName(), internalCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Callback to receive the result of an EuiccManager API.
+ */
+ public interface ResultListener {
+ /**
+ * Called on completion of some operation.
+ * @param resultCode representing success or specific failure of the operation
+ * (See {@link ResultCode})
+ * @param resultIntent an intent used to start a resolution activity when an error
+ * occurs that can be resolved by the user
+ */
+ void onComplete(@ResultCode int resultCode, @Nullable Intent resultIntent);
+ }
+
+ /**
* Update the nickname for the given subscription.
*
* <p>Requires that the calling app has carrier privileges according to the metadata of the
@@ -1411,6 +1499,13 @@
}
}
+ private static void sendUnavailableErrorToCallback(@NonNull Executor executor,
+ ResultListener callback) {
+ Integer result = EMBEDDED_SUBSCRIPTION_RESULT_ERROR;
+ executor.execute(() ->
+ Binder.withCleanCallingIdentity(() -> callback.onComplete(result, null)));
+ }
+
private static IEuiccController getIEuiccController() {
return IEuiccController.Stub.asInterface(
TelephonyFrameworkInitializer
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 683bb92..82d64ab 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -618,9 +618,9 @@
ITelephony iTelephony = getITelephony();
if (iTelephony == null) {
- throw new RuntimeException("Could not find Telephony Service.");
+ Log.w("ImsMmTelManager", "Could not find Telephony Service.");
+ return;
}
-
try {
iTelephony.unregisterMmTelCapabilityCallback(mSubId, c.getBinder());
} catch (RemoteException e) {
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index b56aa96..f5b158f 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -375,12 +375,16 @@
*/
@SystemApi
public final void setFeatureState(@ImsState int state) {
+ boolean isNotify = false;
synchronized (mLock) {
if (mState != state) {
mState = state;
- notifyFeatureState(state);
+ isNotify = true;
}
}
+ if (isNotify) {
+ notifyFeatureState(state);
+ }
}
/**
@@ -412,14 +416,16 @@
* Internal method called by ImsFeature when setFeatureState has changed.
*/
private void notifyFeatureState(@ImsState int state) {
- mStatusCallbacks.broadcastAction((c) -> {
- try {
- c.notifyImsFeatureStatus(state);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, e + " notifyFeatureState() - Skipping "
- + "callback.");
- }
- });
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.broadcastAction((c) -> {
+ try {
+ c.notifyImsFeatureStatus(state);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, e + " notifyFeatureState() - Skipping "
+ + "callback.");
+ }
+ });
+ }
}
/**
@@ -491,14 +497,19 @@
synchronized (mLock) {
mCapabilityStatus = caps.copy();
}
- mCapabilityCallbacks.broadcastAction((callback) -> {
- try {
- callback.onCapabilitiesStatusChanged(caps.mCapabilities);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, e + " notifyCapabilitiesStatusChanged() - Skipping "
- + "callback.");
- }
- });
+
+ synchronized (mCapabilityCallbacks) {
+ mCapabilityCallbacks.broadcastAction((callback) -> {
+ try {
+ Log.d(LOG_TAG, "ImsFeature notifyCapabilitiesStatusChanged Capabilities = "
+ + caps.mCapabilities);
+ callback.onCapabilitiesStatusChanged(caps.mCapabilities);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, e + " notifyCapabilitiesStatusChanged() - Skipping "
+ + "callback.");
+ }
+ });
+ }
}
/**
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 11fc328..f371ec3 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -587,13 +587,15 @@
if (mCallbacks == null) {
return;
}
- mCallbacks.broadcastAction(c -> {
- try {
- c.onIntConfigChanged(item, value);
- } catch (RemoteException e) {
- Log.w(TAG, "notifyConfigChanged(int): dead binder in notify, skipping.");
- }
- });
+ synchronized (mCallbacks) {
+ mCallbacks.broadcastAction(c -> {
+ try {
+ c.onIntConfigChanged(item, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "notifyConfigChanged(int): dead binder in notify, skipping.");
+ }
+ });
+ }
}
private void notifyConfigChanged(int item, String value) {
@@ -601,13 +603,15 @@
if (mCallbacks == null) {
return;
}
- mCallbacks.broadcastAction(c -> {
- try {
- c.onStringConfigChanged(item, value);
- } catch (RemoteException e) {
- Log.w(TAG, "notifyConfigChanged(string): dead binder in notify, skipping.");
- }
- });
+ synchronized (mCallbacks) {
+ mCallbacks.broadcastAction(c -> {
+ try {
+ c.onStringConfigChanged(item, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "notifyConfigChanged(string): dead binder in notify, skipping.");
+ }
+ });
+ }
}
private void addRcsConfigCallback(IRcsConfigCallback c) {
@@ -635,13 +639,15 @@
// can be null in testing
if (mRcsCallbacks != null) {
- mRcsCallbacks.broadcastAction(c -> {
- try {
- c.onConfigurationChanged(mRcsConfigData);
- } catch (RemoteException e) {
- Log.w(TAG, "dead binder in notifyRcsAutoConfigurationReceived, skipping.");
- }
- });
+ synchronized (mRcsCallbacks) {
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onConfigurationChanged(mRcsConfigData);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyRcsAutoConfigurationReceived, skipping.");
+ }
+ });
+ }
}
notifyRcsAutoConfigurationReceived(config, isCompressed);
}
@@ -649,13 +655,15 @@
private void onNotifyRcsAutoConfigurationRemoved() {
mRcsConfigData = null;
if (mRcsCallbacks != null) {
- mRcsCallbacks.broadcastAction(c -> {
- try {
- c.onConfigurationReset();
- } catch (RemoteException e) {
- Log.w(TAG, "dead binder in notifyRcsAutoConfigurationRemoved, skipping.");
- }
- });
+ synchronized (mRcsCallbacks) {
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onConfigurationReset();
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyRcsAutoConfigurationRemoved, skipping.");
+ }
+ });
+ }
}
notifyRcsAutoConfigurationRemoved();
}
@@ -801,13 +809,15 @@
if (mRcsCallbacks == null) {
return;
}
- mRcsCallbacks.broadcastAction(c -> {
- try {
- c.onAutoConfigurationErrorReceived(errorCode, errorString);
- } catch (RemoteException e) {
- Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping.");
- }
- });
+ synchronized (mRcsCallbacks) {
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onAutoConfigurationErrorReceived(errorCode, errorString);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping.");
+ }
+ });
+ }
}
/**
@@ -825,13 +835,15 @@
if (mRcsCallbacks == null) {
return;
}
- mRcsCallbacks.broadcastAction(c -> {
- try {
- c.onPreProvisioningReceived(configXml);
- } catch (RemoteException e) {
- Log.w(TAG, "dead binder in notifyPreProvisioningReceived, skipping.");
- }
- });
+ synchronized (mRcsCallbacks) {
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onPreProvisioningReceived(configXml);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyPreProvisioningReceived, skipping.");
+ }
+ });
+ }
}
/**
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 2783e29..fb997d1 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -219,22 +219,25 @@
*/
public final void onSmsReceived(int token, @SmsMessage.Format String format, byte[] pdu)
throws RuntimeException {
+ IImsSmsListener listener = null;
synchronized (mLock) {
- if (mListener == null) {
- throw new RuntimeException("Feature not ready.");
- }
- try {
- mListener.onSmsReceived(token, format, pdu);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
- SmsMessage message = SmsMessage.createFromPdu(pdu, format);
- if (message != null && message.mWrappedSmsMessage != null) {
- acknowledgeSms(token, message.mWrappedSmsMessage.mMessageRef,
- DELIVER_STATUS_ERROR_GENERIC);
- } else {
- Log.w(LOG_TAG, "onSmsReceived: Invalid pdu entered.");
- acknowledgeSms(token, 0, DELIVER_STATUS_ERROR_GENERIC);
- }
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onSmsReceived(token, format, pdu);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
+ SmsMessage message = SmsMessage.createFromPdu(pdu, format);
+ if (message != null && message.mWrappedSmsMessage != null) {
+ acknowledgeSms(token, message.mWrappedSmsMessage.mMessageRef,
+ DELIVER_STATUS_ERROR_GENERIC);
+ } else {
+ Log.w(LOG_TAG, "onSmsReceived: Invalid pdu entered.");
+ acknowledgeSms(token, 0, DELIVER_STATUS_ERROR_GENERIC);
}
}
}
@@ -254,16 +257,19 @@
*/
public final void onSendSmsResultSuccess(int token,
@IntRange(from = 0, to = 65535) int messageRef) throws RuntimeException {
+ IImsSmsListener listener = null;
synchronized (mLock) {
- if (mListener == null) {
- throw new RuntimeException("Feature not ready.");
- }
- try {
- mListener.onSendSmsResult(token, messageRef, SEND_STATUS_OK,
- SmsManager.RESULT_ERROR_NONE, RESULT_NO_NETWORK_ERROR);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onSendSmsResult(token, messageRef, SEND_STATUS_OK,
+ SmsManager.RESULT_ERROR_NONE, RESULT_NO_NETWORK_ERROR);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
}
}
@@ -288,16 +294,19 @@
@Deprecated
public final void onSendSmsResult(int token, @IntRange(from = 0, to = 65535) int messageRef,
@SendStatusResult int status, @SmsManager.Result int reason) throws RuntimeException {
+ IImsSmsListener listener = null;
synchronized (mLock) {
- if (mListener == null) {
- throw new RuntimeException("Feature not ready.");
- }
- try {
- mListener.onSendSmsResult(token, messageRef, status, reason,
- RESULT_NO_NETWORK_ERROR);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onSendSmsResult(token, messageRef, status, reason,
+ RESULT_NO_NETWORK_ERROR);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
}
}
@@ -322,15 +331,18 @@
public final void onSendSmsResultError(int token,
@IntRange(from = 0, to = 65535) int messageRef, @SendStatusResult int status,
@SmsManager.Result int reason, int networkErrorCode) throws RuntimeException {
+ IImsSmsListener listener = null;
synchronized (mLock) {
- if (mListener == null) {
- throw new RuntimeException("Feature not ready.");
- }
- try {
- mListener.onSendSmsResult(token, messageRef, status, reason, networkErrorCode);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onSendSmsResult(token, messageRef, status, reason, networkErrorCode);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
}
}
@@ -357,16 +369,19 @@
public final void onSmsStatusReportReceived(int token,
@IntRange(from = 0, to = 65535) int messageRef, @SmsMessage.Format String format,
byte[] pdu) throws RuntimeException {
+ IImsSmsListener listener = null;
synchronized (mLock) {
- if (mListener == null) {
- throw new RuntimeException("Feature not ready.");
- }
- try {
- mListener.onSmsStatusReportReceived(token, format, pdu);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
- acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
- }
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onSmsStatusReportReceived(token, format, pdu);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
+ acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
}
}
@@ -386,24 +401,27 @@
*/
public final void onSmsStatusReportReceived(int token, @SmsMessage.Format String format,
byte[] pdu) throws RuntimeException {
+ IImsSmsListener listener = null;
synchronized (mLock) {
- if (mListener == null) {
- throw new RuntimeException("Feature not ready.");
- }
- try {
- mListener.onSmsStatusReportReceived(token, format, pdu);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
- SmsMessage message = SmsMessage.createFromPdu(pdu, format);
- if (message != null && message.mWrappedSmsMessage != null) {
- acknowledgeSmsReport(
- token,
- message.mWrappedSmsMessage.mMessageRef,
- STATUS_REPORT_STATUS_ERROR);
- } else {
- Log.w(LOG_TAG, "onSmsStatusReportReceived: Invalid pdu entered.");
- acknowledgeSmsReport(token, 0, STATUS_REPORT_STATUS_ERROR);
- }
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onSmsStatusReportReceived(token, format, pdu);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
+ SmsMessage message = SmsMessage.createFromPdu(pdu, format);
+ if (message != null && message.mWrappedSmsMessage != null) {
+ acknowledgeSmsReport(
+ token,
+ message.mWrappedSmsMessage.mMessageRef,
+ STATUS_REPORT_STATUS_ERROR);
+ } else {
+ Log.w(LOG_TAG, "onSmsStatusReportReceived: Invalid pdu entered.");
+ acknowledgeSmsReport(token, 0, STATUS_REPORT_STATUS_ERROR);
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 0ac7cf9..883e2ad 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -68,6 +68,7 @@
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.IBooleanConsumer;
import com.android.internal.telephony.ICallForwardingInfoCallback;
+import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.IImsStateCallback;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
@@ -585,64 +586,32 @@
void setCellInfoListRate(int rateInMillis);
/**
- * Opens a logical channel to the ICC card using the physical slot index.
- *
- * Input parameters equivalent to TS 27.007 AT+CCHO command.
- *
- * @param slotIndex The physical slot index of the target ICC card
- * @param callingPackage the name of the package making the call.
- * @param AID Application id. See ETSI 102.221 and 101.220.
- * @param p2 P2 parameter (described in ISO 7816-4).
- * @return an IccOpenLogicalChannelResponse object.
- */
- IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(
- int slotIndex, String callingPackage, String AID, int p2);
-
- /**
* Opens a logical channel to the ICC card.
*
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
- * @param subId The subscription to use.
- * @param callingPackage the name of the package making the call.
- * @param AID Application id. See ETSI 102.221 and 101.220.
- * @param p2 P2 parameter (described in ISO 7816-4).
+ * @param request the parcelable used to indicate how to open the logical channel.
* @return an IccOpenLogicalChannelResponse object.
*/
- IccOpenLogicalChannelResponse iccOpenLogicalChannel(
- int subId, String callingPackage, String AID, int p2);
-
- /**
- * Closes a previously opened logical channel to the ICC card using the physical slot index.
- *
- * Input parameters equivalent to TS 27.007 AT+CCHC command.
- *
- * @param slotIndex The physical slot index of the target ICC card
- * @param channel is the channel id to be closed as returned by a
- * successful iccOpenLogicalChannel.
- * @return true if the channel was closed successfully.
- */
- boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel);
+ IccOpenLogicalChannelResponse iccOpenLogicalChannel(in IccLogicalChannelRequest request);
/**
* Closes a previously opened logical channel to the ICC card.
*
* Input parameters equivalent to TS 27.007 AT+CCHC command.
*
- * @param subId The subscription to use.
- * @param channel is the channel id to be closed as returned by a
- * successful iccOpenLogicalChannel.
+ * @param request the parcelable used to indicate how to close the logical channel.
* @return true if the channel was closed successfully.
*/
- @UnsupportedAppUsage(trackingBug = 171933273)
- boolean iccCloseLogicalChannel(int subId, int channel);
+ boolean iccCloseLogicalChannel(in IccLogicalChannelRequest request);
/**
- * Transmit an APDU to the ICC card over a logical channel using the physical slot index.
+ * Transmit an APDU to the ICC card over a logical channel using the physical slot index and port index.
*
* Input parameters equivalent to TS 27.007 AT+CGLA command.
*
* @param slotIndex The physical slot index of the target ICC card
+ * @param portIndex The unique index referring to a port belonging to the SIM slot
* @param channel is the channel id to be closed as returned by a
* successful iccOpenLogicalChannel.
* @param cla Class of the APDU command.
@@ -655,7 +624,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
- String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla, int instruction,
+ String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel, int cla, int instruction,
int p1, int p2, int p3, String data);
/**
@@ -681,11 +650,12 @@
int p1, int p2, int p3, String data);
/**
- * Transmit an APDU to the ICC card over the basic channel using the physical slot index.
+ * Transmit an APDU to the ICC card over the basic channel using the physical slot index and port index.
*
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
* @param slotIndex The physical slot index of the target ICC card
+ * @param portIndex The unique index referring to a port belonging to the SIM slot
* @param callingPackage the name of the package making the call.
* @param cla Class of the APDU command.
* @param instruction Instruction of the APDU command.
@@ -697,7 +667,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
- String iccTransmitApduBasicChannelBySlot(int slotIndex, String callingPackage, int cla,
+ String iccTransmitApduBasicChannelByPort(int slotIndex, int portIndex, String callingPackage, int cla,
int instruction, int p1, int p2, int p3, String data);
/**
@@ -2153,9 +2123,9 @@
String callingFeatureId);
/**
- * Get the mapping from logical slots to physical slots.
+ * Get the mapping from logical slots to port index.
*/
- int[] getSlotsMapping(String callingPackage);
+ List<UiccSlotMapping> getSlotsMapping(String callingPackage);
/**
* Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown
@@ -2575,4 +2545,15 @@
* registration technology specified, false if it is not required.
*/
boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech);
+
+ /**
+ * Returns the package name that provides the {@link CarrierService} implementation for the
+ * specified {@code logicalSlotIndex}, or {@code null} if no package with carrier privileges
+ * declares one.
+ *
+ * @param logicalSlotIndex The slot index to fetch the {@link CarrierService} package for
+ * @return The system-selected package that provides the {@link CarrierService} implementation
+ * for the slot, or {@code null} if none is resolved
+ */
+ String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex);
}
diff --git a/telephony/java/com/android/internal/telephony/IccLogicalChannelRequest.aidl b/telephony/java/com/android/internal/telephony/IccLogicalChannelRequest.aidl
new file mode 100644
index 0000000..a84e752
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccLogicalChannelRequest.aidl
@@ -0,0 +1,52 @@
+/*
+** Copyright 2007, 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 com.android.internal.telephony;
+
+import android.os.IBinder;
+
+/**
+ * A request to open or close a logical channel to the ICC card.
+ *
+ * @hide
+ */
+@JavaDerive(toString=true, equals=true)
+parcelable IccLogicalChannelRequest {
+
+ /** Subscription id. */
+ int subId = -1;
+
+ /** Physical slot index of the ICC card. */
+ int slotIndex = -1;
+
+ /** The unique index referring to a port belonging to the ICC card slot. */
+ int portIndex = 0;
+
+ /** Package name for the calling app, used only when open channel. */
+ @nullable String callingPackage;
+
+ /** Application id, used only when open channel. */
+ @nullable String aid;
+
+ /** The P2 parameter described in ISO 7816-4, used only when open channel. */
+ int p2 = 0;
+
+ /** Channel number */
+ int channel = -1;
+
+ /** A IBinder object for server side to check if the request client is still living. */
+ @nullable IBinder binder;
+}
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 944ce348..7f5982f 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -21,6 +21,9 @@
import android.os.Bundle;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
+
+import com.android.internal.telephony.euicc.IResultCallback;
+
import java.util.List;
/** @hide */
@@ -42,6 +45,8 @@
in PendingIntent callbackIntent);
oneway void switchToSubscription(int cardId, int subscriptionId, String callingPackage,
in PendingIntent callbackIntent);
+ oneway void switchToSubscriptionWithPort(int cardId, int portIndex, int subscriptionId,
+ String callingPackage, in IResultCallback callback);
oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
String callingPackage, in PendingIntent callbackIntent);
oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl b/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
similarity index 76%
rename from packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
rename to telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
index debc348..69f479c 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
@@ -13,7 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.telephony.euicc;
- package android.net;
+import android.content.Intent;
- parcelable EthernetNetworkUpdateRequest;
\ No newline at end of file
+/** @hide */
+oneway interface IResultCallback {
+ void onComplete(int resultCode, in Intent resultIntent);
+}
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index 816bc6b..9db19a3 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1 +1,2 @@
include /core/java/android/media/soundtrigger/OWNERS
+mdooley@google.com
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 7b1f7a5..5f606e1 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -60,7 +60,7 @@
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
-import android.telephony.TelephonyManager.CarrierPrivilegesListener;
+import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -174,7 +174,7 @@
private IntentFilter getIntentFilter() {
final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(), captor.capture(), any(), any(), anyInt());
+ verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
return captor.getValue();
}
@@ -187,11 +187,11 @@
return captor.getValue();
}
- private List<CarrierPrivilegesListener> getCarrierPrivilegesListeners() {
- final ArgumentCaptor<CarrierPrivilegesListener> captor =
- ArgumentCaptor.forClass(CarrierPrivilegesListener.class);
+ private List<CarrierPrivilegesCallback> getCarrierPrivilegesCallbacks() {
+ final ArgumentCaptor<CarrierPrivilegesCallback> captor =
+ ArgumentCaptor.forClass(CarrierPrivilegesCallback.class);
verify(mTelephonyManager, atLeastOnce())
- .addCarrierPrivilegesListener(anyInt(), any(), captor.capture());
+ .registerCarrierPrivilegesCallback(anyInt(), any(), captor.capture());
return captor.getAllValues();
}
@@ -258,8 +258,7 @@
eq(mTelephonySubscriptionTracker),
any(IntentFilter.class),
any(),
- eq(mHandler),
- eq(Context.RECEIVER_NOT_EXPORTED));
+ eq(mHandler));
final IntentFilter filter = getIntentFilter();
assertEquals(2, filter.countActions());
assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
@@ -270,12 +269,12 @@
assertNotNull(getOnSubscriptionsChangedListener());
verify(mTelephonyManager, times(2))
- .addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any());
+ .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any());
verify(mTelephonyManager)
- .addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any());
+ .registerCarrierPrivilegesCallback(eq(0), any(HandlerExecutor.class), any());
verify(mTelephonyManager)
- .addCarrierPrivilegesListener(eq(1), any(HandlerExecutor.class), any());
- assertEquals(2, getCarrierPrivilegesListeners().size());
+ .registerCarrierPrivilegesCallback(eq(1), any(HandlerExecutor.class), any());
+ assertEquals(2, getCarrierPrivilegesCallbacks().size());
}
@Test
@@ -287,10 +286,10 @@
final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener));
- for (CarrierPrivilegesListener carrierPrivilegesListener :
- getCarrierPrivilegesListeners()) {
+ for (CarrierPrivilegesCallback carrierPrivilegesCallback :
+ getCarrierPrivilegesCallbacks()) {
verify(mTelephonyManager)
- .removeCarrierPrivilegesListener(eq(carrierPrivilegesListener));
+ .unregisterCarrierPrivilegesCallback(eq(carrierPrivilegesCallback));
}
}
@@ -303,15 +302,15 @@
mTelephonySubscriptionTracker.setReadySubIdsBySlotId(readySubIdsBySlotId);
doReturn(1).when(mTelephonyManager).getActiveModemCount();
- List<CarrierPrivilegesListener> carrierPrivilegesListeners =
- getCarrierPrivilegesListeners();
+ List<CarrierPrivilegesCallback> carrierPrivilegesCallbacks =
+ getCarrierPrivilegesCallbacks();
mTelephonySubscriptionTracker.onReceive(mContext, buildTestMultiSimConfigBroadcastIntent());
mTestLooper.dispatchAll();
- for (CarrierPrivilegesListener carrierPrivilegesListener : carrierPrivilegesListeners) {
+ for (CarrierPrivilegesCallback carrierPrivilegesCallback : carrierPrivilegesCallbacks) {
verify(mTelephonyManager)
- .removeCarrierPrivilegesListener(eq(carrierPrivilegesListener));
+ .unregisterCarrierPrivilegesCallback(eq(carrierPrivilegesCallback));
}
// Expect cache cleared for inactive slots.
@@ -323,9 +322,9 @@
// Expect a new CarrierPrivilegesListener to have been registered for slot 0, and none other
// (2 previously registered during startup, for slots 0 & 1)
verify(mTelephonyManager, times(3))
- .addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any());
+ .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any());
verify(mTelephonyManager, times(2))
- .addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any());
+ .registerCarrierPrivilegesCallback(eq(0), any(HandlerExecutor.class), any());
// Verify that this triggers a re-evaluation
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
@@ -391,8 +390,8 @@
public void testOnCarrierPrivilegesChanged() throws Exception {
setupReadySubIds();
- final CarrierPrivilegesListener listener = getCarrierPrivilegesListeners().get(0);
- listener.onCarrierPrivilegesChanged(Collections.emptyList(), new int[] {});
+ final CarrierPrivilegesCallback callback = getCarrierPrivilegesCallbacks().get(0);
+ callback.onCarrierPrivilegesChanged(Collections.emptySet(), Collections.emptySet());
mTestLooper.dispatchAll();
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
diff --git a/tools/locked_region_code_injection/Android.bp b/tools/locked_region_code_injection/Android.bp
index 3e12971..6efd1f6 100644
--- a/tools/locked_region_code_injection/Android.bp
+++ b/tools/locked_region_code_injection/Android.bp
@@ -12,10 +12,10 @@
manifest: "manifest.txt",
srcs: ["src/**/*.java"],
static_libs: [
- "asm-7.0",
- "asm-commons-7.0",
- "asm-tree-7.0",
- "asm-analysis-7.0",
+ "asm-9.2",
+ "asm-commons-9.2",
+ "asm-tree-9.2",
+ "asm-analysis-9.2",
"guava-21.0",
],
}
diff --git a/tools/sdkparcelables/Android.bp b/tools/sdkparcelables/Android.bp
index ec2bffd..6ebacd8 100644
--- a/tools/sdkparcelables/Android.bp
+++ b/tools/sdkparcelables/Android.bp
@@ -14,7 +14,7 @@
"src/**/*.kt",
],
static_libs: [
- "asm-7.0",
+ "asm-9.2",
],
}
diff --git a/tools/traceinjection/Android.bp b/tools/traceinjection/Android.bp
index 1395c5f..39d1b1c 100644
--- a/tools/traceinjection/Android.bp
+++ b/tools/traceinjection/Android.bp
@@ -12,10 +12,10 @@
manifest: "manifest.txt",
srcs: ["src/**/*.java"],
static_libs: [
- "asm-7.0",
- "asm-commons-7.0",
- "asm-tree-7.0",
- "asm-analysis-7.0",
+ "asm-9.2",
+ "asm-commons-9.2",
+ "asm-tree-9.2",
+ "asm-analysis-9.2",
"guava-21.0",
],
}