summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--StubLibraries.bp17
-rw-r--r--apex/statsd/aidl/android/os/IStatsCompanionService.aidl11
-rw-r--r--apex/statsd/aidl/android/os/IStatsd.aidl7
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java66
-rw-r--r--api/Android.bp15
-rw-r--r--api/current.txt4
-rw-r--r--api/test-current.txt43
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp39
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h26
-rw-r--r--cmds/statsd/src/StatsService.cpp32
-rw-r--r--cmds/statsd/src/StatsService.h5
-rw-r--r--cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp264
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java18
-rw-r--r--core/java/android/app/admin/FreezePeriod.java20
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java22
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--data/keyboards/Vendor_2378_Product_1008.kl5
-rw-r--r--data/keyboards/Vendor_2378_Product_100a.kl5
-rw-r--r--non-updatable-api/current.txt4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java3
-rw-r--r--packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm366
-rw-r--r--packages/InputDevices/res/values/strings.xml3
-rw-r--r--packages/InputDevices/res/xml/keyboard_layouts.xml4
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java215
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/Tethering.java2
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java8
-rw-r--r--packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java104
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java252
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java74
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java16
-rw-r--r--services/core/java/com/android/server/MountServiceIdler.java1
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java10
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java53
-rw-r--r--services/core/java/com/android/server/vcn/OWNERS7
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java98
-rwxr-xr-xtelecomm/java/android/telecom/Call.java26
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java12
-rw-r--r--tests/net/integration/util/com/android/server/NetworkAgentWrapper.java6
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java2
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java81
-rw-r--r--tests/vcn/OWNERS7
43 files changed, 1362 insertions, 599 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 4e1de0ecf9d4..fe84a7ac7715 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -139,12 +139,6 @@ droidstubs {
baseline_file: "api/lint-baseline.txt",
},
},
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/public/api",
- dest: "android.txt",
- },
- jdiff_enabled: true,
}
droidstubs {
@@ -206,12 +200,6 @@ droidstubs {
baseline_file: "api/system-lint-baseline.txt",
},
},
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/system/api",
- dest: "android.txt",
- },
- jdiff_enabled: true,
}
droidstubs {
@@ -291,11 +279,6 @@ droidstubs {
baseline_file: "api/module-lib-lint-baseline.txt",
},
},
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/module-lib/api",
- dest: "android.txt",
- },
}
droidstubs {
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 5cdb3249501b..d56a4bd0a8e5 100644
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
@@ -27,17 +27,6 @@ interface IStatsCompanionService {
oneway void statsdReady();
/**
- * Register an alarm for anomaly detection to fire at the given timestamp (ms since epoch).
- * If anomaly alarm had already been registered, it will be replaced with the new timestamp.
- * Uses AlarmManager.set API, so if the timestamp is in the past, alarm fires immediately, and
- * alarm is inexact.
- */
- oneway void setAnomalyAlarm(long timestampMs);
-
- /** Cancel any anomaly detection alarm. */
- oneway void cancelAnomalyAlarm();
-
- /**
* Register a repeating alarm for pulling to fire at the given timestamp and every
* intervalMs thereafter (in ms since epoch).
* If polling alarm had already been registered, it will be replaced by new one.
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
index 0d3f4208a2ab..066412a9f157 100644
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ b/apex/statsd/aidl/android/os/IStatsd.aidl
@@ -42,13 +42,6 @@ interface IStatsd {
void statsCompanionReady();
/**
- * Tells statsd that an anomaly may have occurred, so statsd can check whether this is so and
- * act accordingly.
- * Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
- */
- void informAnomalyAlarmFired();
-
- /**
* Tells statsd that it is time to poll some stats. Statsd will be responsible for determing
* what stats to poll and initiating the polling.
* Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index cbc8ed636ff2..b5e72247a4a3 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -100,7 +100,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private static IStatsd sStatsd;
private static final Object sStatsdLock = new Object();
- private final OnAlarmListener mAnomalyAlarmListener;
private final OnAlarmListener mPullingAlarmListener;
private final OnAlarmListener mPeriodicAlarmListener;
@@ -124,7 +123,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
handlerThread.start();
mHandler = new CompanionHandler(handlerThread.getLooper());
- mAnomalyAlarmListener = new AnomalyAlarmListener(context);
mPullingAlarmListener = new PullingAlarmListener(context);
mPeriodicAlarmListener = new PeriodicAlarmListener(context);
}
@@ -336,41 +334,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- public static final class AnomalyAlarmListener implements OnAlarmListener {
- private final Context mContext;
-
- AnomalyAlarmListener(Context context) {
- mContext = context;
- }
-
- @Override
- public void onAlarm() {
- if (DEBUG) {
- Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time "
- + System.currentTimeMillis() + "ms.");
- }
- IStatsd statsd = getStatsdNonblocking();
- if (statsd == null) {
- Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
- return;
- }
-
- // Wakelock needs to be retained while calling statsd.
- Thread thread = new WakelockThread(mContext,
- AnomalyAlarmListener.class.getCanonicalName(), new Runnable() {
- @Override
- public void run() {
- try {
- statsd.informAnomalyAlarmFired();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e);
- }
- }
- });
- thread.start();
- }
- }
-
public final static class PullingAlarmListener implements OnAlarmListener {
private final Context mContext;
@@ -469,34 +432,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
@Override // Binder call
- public void setAnomalyAlarm(long timestampMs) {
- StatsCompanion.enforceStatsdCallingUid();
- if (DEBUG) Log.d(TAG, "Setting anomaly alarm for " + timestampMs);
- final long callingToken = Binder.clearCallingIdentity();
- try {
- // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
- // only fire when it awakens.
- // AlarmManager will automatically cancel any previous mAnomalyAlarmListener alarm.
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".anomaly",
- mAnomalyAlarmListener, mHandler);
- } finally {
- Binder.restoreCallingIdentity(callingToken);
- }
- }
-
- @Override // Binder call
- public void cancelAnomalyAlarm() {
- StatsCompanion.enforceStatsdCallingUid();
- if (DEBUG) Log.d(TAG, "Cancelling anomaly alarm");
- final long callingToken = Binder.clearCallingIdentity();
- try {
- mAlarmManager.cancel(mAnomalyAlarmListener);
- } finally {
- Binder.restoreCallingIdentity(callingToken);
- }
- }
-
- @Override // Binder call
public void setAlarmForSubscriberTriggering(long timestampMs) {
StatsCompanion.enforceStatsdCallingUid();
if (DEBUG) {
@@ -666,7 +601,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
// instead of in binder death because statsd can come back and set different alarms, or not
// want to set an alarm when it had been set. This guarantees that when we get a new statsd,
// we cancel any alarms before it is able to set them.
- cancelAnomalyAlarm();
cancelPullingAlarm();
cancelAlarmForSubscriberTriggering();
diff --git a/api/Android.bp b/api/Android.bp
index ffc4a2146594..fd0303b31de9 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -60,6 +60,11 @@ genrule {
out: ["current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/public/api",
+ dest: "android.txt",
+ },
}
genrule {
@@ -95,6 +100,11 @@ genrule {
out: ["system-current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system/api",
+ dest: "android.txt",
+ },
}
genrule {
@@ -129,6 +139,11 @@ genrule {
out: ["module-lib-current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/module-lib/api",
+ dest: "android.txt",
+ },
}
genrule {
diff --git a/api/current.txt b/api/current.txt
index d9239724210f..be3c35c0ff79 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -48279,7 +48279,7 @@ package android.telephony {
method @Deprecated public int getPhoneCount();
method public int getPhoneType();
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
- method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
method @Nullable public android.telephony.SignalStrength getSignalStrength();
method public int getSimCarrierId();
method @Nullable public CharSequence getSimCarrierIdName();
@@ -48302,7 +48302,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getVoiceNetworkType();
- method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
+ method @Nullable public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
method public boolean hasIccCard();
method @Deprecated public boolean iccCloseLogicalChannel(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 2cb106e7fd51..3bf0f03c77f5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19,6 +19,7 @@ package android {
field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
field public static final String OVERRIDE_DISPLAY_MODE_REQUESTS = "android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS";
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
+ field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
@@ -3387,7 +3388,7 @@ package android.security {
package android.security.keystore {
public abstract class AttestationUtils {
- method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
field public static final int ID_TYPE_IMEI = 2; // 0x2
field public static final int ID_TYPE_MEID = 3; // 0x3
field public static final int ID_TYPE_SERIAL = 1; // 0x1
@@ -3923,11 +3924,11 @@ package android.telecom {
public class TelecomManager {
method @NonNull public android.content.Intent createLaunchEmergencyDialerIntent(@Nullable String);
- method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCurrentTtyMode();
- method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
- method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
+ method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
field public static final String ACTION_CURRENT_TTY_MODE_CHANGED = "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
field public static final String ACTION_TTY_PREFERRED_MODE_CHANGED = "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
@@ -4113,7 +4114,7 @@ package android.telephony {
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @Nullable @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public android.content.ComponentName getDefaultRespondViaMessageApplication();
method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getEmergencyNumberDbVersion();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
@@ -4351,14 +4352,14 @@ package android.telephony.ims {
}
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
- method @Deprecated @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting();
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(int, int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(int, int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
- method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
@@ -4367,7 +4368,7 @@ package android.telephony.ims {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
- method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
}
@Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
@@ -4600,17 +4601,17 @@ package android.telephony.ims {
public class ProvisioningManager {
method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public int getProvisioningIntValue(int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
- method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public String getProvisioningStringValue(int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index e7b32c56551a..c10f248f4702 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -120,10 +120,9 @@ static void flushProtoToBuffer(ProtoOutputStream& proto, vector<uint8_t>* outDat
}
}
-void StatsLogProcessor::onAnomalyAlarmFired(
+void StatsLogProcessor::processFiredAnomalyAlarmsLocked(
const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
- std::lock_guard<std::mutex> lock(mMetricsMutex);
for (const auto& itr : mMetricsManagers) {
itr.second->onAnomalyAlarmFired(timestampNs, alarmSet);
}
@@ -431,6 +430,20 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) {
return;
}
+ bool fireAlarm = false;
+ {
+ std::lock_guard<std::mutex> anomalyLock(mAnomalyAlarmMutex);
+ if (mNextAnomalyAlarmTime != 0 &&
+ MillisToNano(mNextAnomalyAlarmTime) <= elapsedRealtimeNs) {
+ mNextAnomalyAlarmTime = 0;
+ VLOG("informing anomaly alarm at time %lld", (long long)elapsedRealtimeNs);
+ fireAlarm = true;
+ }
+ }
+ if (fireAlarm) {
+ informAnomalyAlarmFiredLocked(NanoToMillis(elapsedRealtimeNs));
+ }
+
int64_t curTimeSec = getElapsedRealtimeSec();
if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
mPullerManager->ClearPullerCacheIfNecessary(curTimeSec * NS_PER_SEC);
@@ -1092,6 +1105,28 @@ void StatsLogProcessor::noteOnDiskData(const ConfigKey& key) {
mOnDiskDataConfigs.insert(key);
}
+void StatsLogProcessor::setAnomalyAlarm(const int64_t elapsedTimeMillis) {
+ std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
+ mNextAnomalyAlarmTime = elapsedTimeMillis;
+}
+
+void StatsLogProcessor::cancelAnomalyAlarm() {
+ std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
+ mNextAnomalyAlarmTime = 0;
+}
+
+void StatsLogProcessor::informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis) {
+ VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
+ std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
+ mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(elapsedTimeMillis / 1000));
+ if (alarmSet.size() > 0) {
+ VLOG("Found periodic alarm fired.");
+ processFiredAnomalyAlarmsLocked(MillisToNano(elapsedTimeMillis), alarmSet);
+ } else {
+ ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
+ }
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 23f2584655b0..08f46688bbba 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -66,11 +66,6 @@ public:
const DumpLatency dumpLatency,
ProtoOutputStream* proto);
- /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
- void onAnomalyAlarmFired(
- const int64_t& timestampNs,
- unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
-
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */
void onPeriodicAlarmFired(
const int64_t& timestampNs,
@@ -148,6 +143,10 @@ public:
// Add a specific config key to the possible configs to dump ASAP.
void noteOnDiskData(const ConfigKey& key);
+ void setAnomalyAlarm(const int64_t timeMillis);
+
+ void cancelAnomalyAlarm();
+
private:
// For testing only.
inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const {
@@ -160,6 +159,11 @@ private:
mutable mutex mMetricsMutex;
+ // Guards mNextAnomalyAlarmTime. A separate mutex is needed because alarms are set/cancelled
+ // in the onLogEvent code path, which is locked by mMetricsMutex.
+ // DO NOT acquire mMetricsMutex while holding mAnomalyAlarmMutex. This can lead to a deadlock.
+ mutable mutex mAnomalyAlarmMutex;
+
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes;
@@ -250,6 +254,15 @@ private:
// Reset the specified configs.
void resetConfigsLocked(const int64_t timestampNs, const std::vector<ConfigKey>& configs);
+ // An anomaly alarm should have fired.
+ // Check with anomaly alarm manager to find the alarms and process the result.
+ void informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis);
+
+ /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
+ void processFiredAnomalyAlarmsLocked(
+ const int64_t& timestampNs,
+ unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
+
// Function used to send a broadcast so that receiver for the config key can call getData
// to retrieve the stored data.
std::function<bool(const ConfigKey& key)> mSendBroadcast;
@@ -276,6 +289,9 @@ private:
//Last time we wrote metadata to disk.
int64_t mLastMetadataWriteNs = 0;
+ // The time for the next anomaly alarm for alerts.
+ int64_t mNextAnomalyAlarmTime = 0;
+
#ifdef VERY_VERBOSE_PRINTING
bool mPrintAllLogs = false;
#endif
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 322648229d0e..368a6c40c746 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -91,17 +91,13 @@ Status checkUid(uid_t expectedUid) {
StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue)
: mAnomalyAlarmMonitor(new AlarmMonitor(
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
- [](const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) {
- if (sc != nullptr) {
- sc->setAnomalyAlarm(timeMillis);
- StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
- }
+ [this](const shared_ptr<IStatsCompanionService>& /*sc*/, int64_t timeMillis) {
+ mProcessor->setAnomalyAlarm(timeMillis);
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
},
- [](const shared_ptr<IStatsCompanionService>& sc) {
- if (sc != nullptr) {
- sc->cancelAnomalyAlarm();
- StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
- }
+ [this](const shared_ptr<IStatsCompanionService>& /*sc*/) {
+ mProcessor->cancelAnomalyAlarm();
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
})),
mPeriodicAlarmMonitor(new AlarmMonitor(
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
@@ -975,22 +971,6 @@ Status StatsService::informOnePackageRemoved(const string& app, int32_t uid) {
return Status::ok();
}
-Status StatsService::informAnomalyAlarmFired() {
- ENFORCE_UID(AID_SYSTEM);
-
- VLOG("StatsService::informAnomalyAlarmFired was called");
- int64_t currentTimeSec = getElapsedRealtimeSec();
- std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
- mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
- if (alarmSet.size() > 0) {
- VLOG("Found an anomaly alarm that fired.");
- mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
- } else {
- VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
- }
- return Status::ok();
-}
-
Status StatsService::informAlarmForSubscriberTriggeringFired() {
ENFORCE_UID(AID_SYSTEM);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 324ffbd65e51..479f4e87ec96 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -66,7 +66,6 @@ public:
virtual Status systemRunning();
virtual Status statsCompanionReady();
virtual Status bootCompleted();
- virtual Status informAnomalyAlarmFired();
virtual Status informPollAlarmFired();
virtual Status informAlarmForSubscriberTriggeringFired();
@@ -404,6 +403,10 @@ private:
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket);
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket);
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket);
+
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
};
} // namespace statsd
diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 95e301002a1b..70e7365ec238 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -12,14 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
#include <gtest/gtest.h>
-#include "src/anomaly/DurationAnomalyTracker.h"
+#include <vector>
+
#include "src/StatsLogProcessor.h"
+#include "src/StatsService.h"
+#include "src/anomaly/DurationAnomalyTracker.h"
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
-#include <vector>
+using ::ndk::SharedRefBase;
namespace android {
namespace os {
@@ -29,6 +34,9 @@ namespace statsd {
namespace {
+const int kConfigKey = 789130124;
+const int kCallingUid = 0;
+
StatsdConfig CreateStatsdConfig(int num_buckets,
uint64_t threshold_ns,
DurationMetric::AggregationType aggregationType,
@@ -89,6 +97,13 @@ MetricDimensionKey dimensionKey2(
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
+void sendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
+ string str;
+ config.SerializeToString(&str);
+ std::vector<uint8_t> configAsVec(str.begin(), str.end());
+ service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
+}
+
} // namespace
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
@@ -98,16 +113,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -158,12 +175,13 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
(uint32_t)alarmFiredTimestampSec0);
+ EXPECT_EQ(alarmFiredTimestampSec0,
+ processor->getAnomalyAlarmMonitor()->getRegisteredAlarmTimeSec());
// Anomaly alarm fired.
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(alarmFiredTimestampSec0));
- ASSERT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
+ auto alarmTriggerEvent = CreateBatterySaverOnEvent(alarmFiredTimestampSec0 * NS_PER_SEC);
+ processor->OnLogEvent(alarmTriggerEvent.get(), alarmFiredTimestampSec0 * NS_PER_SEC);
+
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
@@ -179,39 +197,39 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock wl1.
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11,
- attributionUids2, attributionTags2, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11, attributionUids2,
+ attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
(uint64_t)alarmFiredTimestampSec1);
// Release wakelock wl1.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+ auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec1));
ASSERT_EQ(0u, alarmSet.size());
// Acquire wakelock wl1 near the end of bucket #0.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 2,
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 2,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Release the event at early bucket #1.
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Anomaly detected when stopping the alarm. The refractory period does not change.
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
@@ -236,17 +254,17 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
// Condition turns true.
screen_off_event =
- CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
+ CreateScreenStateChangedEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Condition turns to false.
- screen_on_event =
- CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1,
- android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- processor->OnLogEvent(screen_on_event.get());
+ int64_t condition_false_time = bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1;
+ screen_on_event = CreateScreenStateChangedEvent(
+ condition_false_time, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+ processor->OnLogEvent(screen_on_event.get(), condition_false_time);
// Condition turns to false. Cancelled the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Detected one anomaly.
@@ -262,12 +280,11 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC,
- attributionUids2, attributionTags2, "wl1");
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
@@ -279,16 +296,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -298,96 +317,97 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #0.
- auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 1;
+ auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc1" in bucket #1.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1,
- attributionUids2, attributionTags2, "wl1");
+ acquire_event =
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 1,
+ attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + 100,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 100;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc2" in bucket #2.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
- attributionUids3, attributionTags3, "wl2");
+ acquire_event =
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + 1,
+ attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
+ EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Release wakelock "wc2" in bucket #2.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
- attributionUids3, attributionTags3, "wl2");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
+ attributionTags3, "wl2");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Acquire wakelock "wc1" in bucket #2.
acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #2.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3.5 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ(refractory_period_sec +
- (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) /
- NS_PER_SEC +
- 1,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4,
- attributionUids3, attributionTags3, "wl2");
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 4,
+ attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 5,
+ attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 2,
- attributionUids3, attributionTags3, "wl2");
- processor->OnLogEvent(release_event.get());
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 6,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC + 2;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
+ attributionTags3, "wl2");
+ processor->OnLogEvent(release_event.get(), release_event_time);
+ release_event = CreateReleaseWakelockEvent(release_event_time + 4, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time + 4);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
- EXPECT_EQ(refractory_period_sec + (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC +
+ EXPECT_EQ(refractory_period_sec +
+ (int64_t)(roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC) /
+ NS_PER_SEC +
1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
@@ -396,20 +416,22 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const int num_buckets = 2;
const uint64_t threshold_ns = 3 * NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
-
const uint64_t alert_id = config.alert(0).id();
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
+
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -418,81 +440,81 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
- auto acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 100,
+ auto acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire the wakelock "wc1" again.
acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
// The alarm does not change.
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Anomaly alarm fired late.
- const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
- ASSERT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
+ const int64_t firedAlarmTimestampNs = roundedBucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
+ auto alarmTriggerEvent = CreateBatterySaverOnEvent(firedAlarmTimestampNs);
+ processor->OnLogEvent(alarmTriggerEvent.get(), firedAlarmTimestampNs);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = bucketStartTimeNs + 2 * bucketSizeNs + 1;
+ auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Within the refractory period. No anomaly.
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// A new wakelock, but still within refractory period.
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
- attributionUids1, attributionTags1, "wl1");
+ release_event =
+ CreateReleaseWakelockEvent(roundedBucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
+ attributionUids1, attributionTags1, "wl1");
// Still in the refractory period. No anomaly.
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 5, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+ EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 4;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 3, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+ EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1fce990e01c0..237175d42dd1 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5718,8 +5718,8 @@ public class DevicePolicyManager {
* System apps can always bypass VPN.
* <p> Note that the system doesn't update the allowlist when packages are installed or
* uninstalled, the admin app must call this method to keep the list up to date.
- * <p> When {@code lockdownEnabled} is false {@code lockdownWhitelist} is ignored . When
- * {@code lockdownEnabled} is {@code true} and {@code lockdownWhitelist} is {@code null} or
+ * <p> When {@code lockdownEnabled} is false {@code lockdownAllowlist} is ignored . When
+ * {@code lockdownEnabled} is {@code true} and {@code lockdownAllowlist} is {@code null} or
* empty, only system apps can bypass VPN.
* <p> Setting always-on VPN package to {@code null} or using
* {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)} clears lockdown allowlist.
@@ -5728,24 +5728,24 @@ public class DevicePolicyManager {
* to remove an existing always-on VPN configuration
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
* {@code false} otherwise. This has no effect when clearing.
- * @param lockdownWhitelist Packages that will be able to access the network directly when VPN
+ * @param lockdownAllowlist Packages that will be able to access the network directly when VPN
* is in lockdown mode but not connected. Has no effect when clearing.
* @throws SecurityException if {@code admin} is not a device or a profile
* owner.
* @throws NameNotFoundException if {@code vpnPackage} or one of
- * {@code lockdownWhitelist} is not installed.
+ * {@code lockdownAllowlist} is not installed.
* @throws UnsupportedOperationException if {@code vpnPackage} exists but does
* not support being set as always-on, or if always-on VPN is not
* available.
*/
public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
- boolean lockdownEnabled, @Nullable Set<String> lockdownWhitelist)
+ boolean lockdownEnabled, @Nullable Set<String> lockdownAllowlist)
throws NameNotFoundException {
throwIfParentInstance("setAlwaysOnVpnPackage");
if (mService != null) {
try {
mService.setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled,
- lockdownWhitelist == null ? null : new ArrayList<>(lockdownWhitelist));
+ lockdownAllowlist == null ? null : new ArrayList<>(lockdownAllowlist));
} catch (ServiceSpecificException e) {
switch (e.errorCode) {
case ERROR_VPN_PACKAGE_NOT_FOUND:
@@ -5820,9 +5820,9 @@ public class DevicePolicyManager {
throwIfParentInstance("getAlwaysOnVpnLockdownWhitelist");
if (mService != null) {
try {
- final List<String> whitelist =
- mService.getAlwaysOnVpnLockdownWhitelist(admin);
- return whitelist == null ? null : new HashSet<>(whitelist);
+ final List<String> allowlist =
+ mService.getAlwaysOnVpnLockdownAllowlist(admin);
+ return allowlist == null ? null : new HashSet<>(allowlist);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/FreezePeriod.java b/core/java/android/app/admin/FreezePeriod.java
index 657f0177097e..eb6efec1c330 100644
--- a/core/java/android/app/admin/FreezePeriod.java
+++ b/core/java/android/app/admin/FreezePeriod.java
@@ -39,8 +39,8 @@ import java.util.List;
public class FreezePeriod {
private static final String TAG = "FreezePeriod";
- private static final int DUMMY_YEAR = 2001;
- static final int DAYS_IN_YEAR = 365; // 365 since DUMMY_YEAR is not a leap year
+ private static final int SENTINEL_YEAR = 2001;
+ static final int DAYS_IN_YEAR = 365; // 365 since SENTINEL_YEAR is not a leap year
private final MonthDay mStart;
private final MonthDay mEnd;
@@ -60,9 +60,9 @@ public class FreezePeriod {
*/
public FreezePeriod(MonthDay start, MonthDay end) {
mStart = start;
- mStartDay = mStart.atYear(DUMMY_YEAR).getDayOfYear();
+ mStartDay = mStart.atYear(SENTINEL_YEAR).getDayOfYear();
mEnd = end;
- mEndDay = mEnd.atYear(DUMMY_YEAR).getDayOfYear();
+ mEndDay = mEnd.atYear(SENTINEL_YEAR).getDayOfYear();
}
/**
@@ -166,9 +166,9 @@ public class FreezePeriod {
endYearAdjustment = 1;
}
}
- final LocalDate startDate = LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).withYear(
+ final LocalDate startDate = LocalDate.ofYearDay(SENTINEL_YEAR, mStartDay).withYear(
now.getYear() + startYearAdjustment);
- final LocalDate endDate = LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).withYear(
+ final LocalDate endDate = LocalDate.ofYearDay(SENTINEL_YEAR, mEndDay).withYear(
now.getYear() + endYearAdjustment);
return new Pair<>(startDate, endDate);
}
@@ -176,13 +176,13 @@ public class FreezePeriod {
@Override
public String toString() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd");
- return LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).format(formatter) + " - "
- + LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).format(formatter);
+ return LocalDate.ofYearDay(SENTINEL_YEAR, mStartDay).format(formatter) + " - "
+ + LocalDate.ofYearDay(SENTINEL_YEAR, mEndDay).format(formatter);
}
/** @hide */
private static MonthDay dayOfYearToMonthDay(int dayOfYear) {
- LocalDate date = LocalDate.ofYearDay(DUMMY_YEAR, dayOfYear);
+ LocalDate date = LocalDate.ofYearDay(SENTINEL_YEAR, dayOfYear);
return MonthDay.of(date.getMonth(), date.getDayOfMonth());
}
@@ -191,7 +191,7 @@ public class FreezePeriod {
* @hide
*/
private static int dayOfYearDisregardLeapYear(LocalDate date) {
- return date.withYear(DUMMY_YEAR).getDayOfYear();
+ return date.withYear(SENTINEL_YEAR).getDayOfYear();
}
/**
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9c6a274ccf8c..3ad8b4b5294f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -197,12 +197,12 @@ interface IDevicePolicyManager {
void setCertInstallerPackage(in ComponentName who, String installerPackage);
String getCertInstallerPackage(in ComponentName who);
- boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownWhitelist);
+ boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownAllowlist);
String getAlwaysOnVpnPackage(in ComponentName who);
String getAlwaysOnVpnPackageForUser(int userHandle);
boolean isAlwaysOnVpnLockdownEnabled(in ComponentName who);
boolean isAlwaysOnVpnLockdownEnabledForUser(int userHandle);
- List<String> getAlwaysOnVpnLockdownWhitelist(in ComponentName who);
+ List<String> getAlwaysOnVpnLockdownAllowlist(in ComponentName who);
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 4b661ca3ab80..236e67a1ea70 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -951,7 +951,7 @@ public class ChooserActivity extends ResolverActivity implements
updateStickyContentPreview();
if (shouldShowStickyContentPreview()
|| mChooserMultiProfilePagerAdapter
- .getCurrentRootAdapter().getContentPreviewRowCount() != 0) {
+ .getCurrentRootAdapter().getSystemRowCount() != 0) {
logActionShareWithPreview();
}
return postRebuildListInternal(rebuildCompleted);
@@ -1316,13 +1316,14 @@ public class ChooserActivity extends ResolverActivity implements
ViewGroup parent) {
ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
R.layout.chooser_grid_preview_image, parent, false);
+ ViewGroup imagePreview = contentPreviewLayout.findViewById(R.id.content_preview_image_area);
final ViewGroup actionRow =
(ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row);
//TODO: addActionButton(actionRow, createCopyButton());
addActionButton(actionRow, createNearbyButton(targetIntent));
- mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, true);
+ mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
@@ -1342,7 +1343,7 @@ public class ChooserActivity extends ResolverActivity implements
if (imageUris.size() == 0) {
Log.i(TAG, "Attempted to display image preview area with zero"
+ " available images detected in EXTRA_STREAM list");
- contentPreviewLayout.setVisibility(View.GONE);
+ imagePreview.setVisibility(View.GONE);
return contentPreviewLayout;
}
@@ -2680,7 +2681,7 @@ public class ChooserActivity extends ResolverActivity implements
final int bottomInset = mSystemWindowInsets != null
? mSystemWindowInsets.bottom : 0;
int offset = bottomInset;
- int rowsToShow = gridAdapter.getContentPreviewRowCount()
+ int rowsToShow = gridAdapter.getSystemRowCount()
+ gridAdapter.getProfileRowCount()
+ gridAdapter.getServiceTargetRowCount()
+ gridAdapter.getCallerAndRankedTargetRowCount();
@@ -3273,7 +3274,7 @@ public class ChooserActivity extends ResolverActivity implements
public int getRowCount() {
return (int) (
- getContentPreviewRowCount()
+ getSystemRowCount()
+ getProfileRowCount()
+ getServiceTargetRowCount()
+ getCallerAndRankedTargetRowCount()
@@ -3289,7 +3290,7 @@ public class ChooserActivity extends ResolverActivity implements
* content preview. Not to be confused with the sticky content preview which is above the
* personal and work tabs.
*/
- public int getContentPreviewRowCount() {
+ public int getSystemRowCount() {
// For the tabbed case we show the sticky content preview above the tabs,
// please refer to shouldShowStickyContentPreview
if (shouldShowTabs()) {
@@ -3299,8 +3300,7 @@ public class ChooserActivity extends ResolverActivity implements
return 0;
}
- if (mHideContentPreview || mChooserListAdapter == null
- || mChooserListAdapter.getCount() == 0) {
+ if (mChooserListAdapter == null || mChooserListAdapter.getCount() == 0) {
return 0;
}
@@ -3342,7 +3342,7 @@ public class ChooserActivity extends ResolverActivity implements
@Override
public int getItemCount() {
return (int) (
- getContentPreviewRowCount()
+ getSystemRowCount()
+ getProfileRowCount()
+ getServiceTargetRowCount()
+ getCallerAndRankedTargetRowCount()
@@ -3397,7 +3397,7 @@ public class ChooserActivity extends ResolverActivity implements
public int getItemViewType(int position) {
int count;
- int countSum = (count = getContentPreviewRowCount());
+ int countSum = (count = getSystemRowCount());
if (count > 0 && position < countSum) return VIEW_TYPE_CONTENT_PREVIEW;
countSum += (count = getProfileRowCount());
@@ -3621,7 +3621,7 @@ public class ChooserActivity extends ResolverActivity implements
}
int getListPosition(int position) {
- position -= getContentPreviewRowCount() + getProfileRowCount();
+ position -= getSystemRowCount() + getProfileRowCount();
final int serviceCount = mChooserListAdapter.getServiceTargetCount();
final int serviceRows = (int) Math.ceil((float) serviceCount
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9b90b0a24922..48275f656b2f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2151,7 +2151,7 @@
<permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
android:protectionLevel="signature|privileged" />
- <!-- @SystemApi Allows read access to privileged phone state.
+ <!-- @SystemApi @TestApi Allows read access to privileged phone state.
@hide Used internally. -->
<permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
android:protectionLevel="signature|privileged" />
diff --git a/data/keyboards/Vendor_2378_Product_1008.kl b/data/keyboards/Vendor_2378_Product_1008.kl
index 478da03b9a78..7b19469ab6b4 100644
--- a/data/keyboards/Vendor_2378_Product_1008.kl
+++ b/data/keyboards/Vendor_2378_Product_1008.kl
@@ -14,6 +14,10 @@
# OnLive, Inc. OnLive Wireless Controller, USB adapter
+key 164 MEDIA_PLAY_PAUSE
+key 167 MEDIA_RECORD
+key 168 MEDIA_REWIND
+key 208 MEDIA_FAST_FORWARD
key 304 BUTTON_A
key 305 BUTTON_B
key 307 BUTTON_X
@@ -22,6 +26,7 @@ key 310 BUTTON_L1
key 311 BUTTON_R1
key 315 BUTTON_START
key 314 BUTTON_SELECT
+key 316 BUTTON_MODE
key 317 BUTTON_THUMBL
key 318 BUTTON_THUMBR
diff --git a/data/keyboards/Vendor_2378_Product_100a.kl b/data/keyboards/Vendor_2378_Product_100a.kl
index d9cd17120464..cb2b73afee3d 100644
--- a/data/keyboards/Vendor_2378_Product_100a.kl
+++ b/data/keyboards/Vendor_2378_Product_100a.kl
@@ -14,6 +14,10 @@
# OnLive, Inc. OnLive Wireless Controller
+key 164 MEDIA_PLAY_PAUSE
+key 167 MEDIA_RECORD
+key 168 MEDIA_REWIND
+key 208 MEDIA_FAST_FORWARD
key 304 BUTTON_A
key 305 BUTTON_B
key 307 BUTTON_X
@@ -22,6 +26,7 @@ key 310 BUTTON_L1
key 311 BUTTON_R1
key 315 BUTTON_START
key 314 BUTTON_SELECT
+key 316 BUTTON_MODE
key 317 BUTTON_THUMBL
key 318 BUTTON_THUMBR
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index bbd5b23471d7..64d3d92a0b8a 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -46447,7 +46447,7 @@ package android.telephony {
method @Deprecated public int getPhoneCount();
method public int getPhoneType();
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
- method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
method @Nullable public android.telephony.SignalStrength getSignalStrength();
method public int getSimCarrierId();
method @Nullable public CharSequence getSimCarrierIdName();
@@ -46470,7 +46470,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getVoiceNetworkType();
- method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
+ method @Nullable public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
method public boolean hasIccCard();
method @Deprecated public boolean iccCloseLogicalChannel(int);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
index 2ff667093e58..a526e6943004 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
@@ -478,6 +478,9 @@ public class UserGridRecyclerView extends RecyclerView {
if (user != null) {
mCarUserManagerHelper.switchToUser(user);
}
+ if (mAddUserView != null) {
+ mAddUserView.setEnabled(true);
+ }
}
}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm b/packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm
new file mode 100644
index 000000000000..5b96da027be7
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_turkish_f.kcm
@@ -0,0 +1,366 @@
+# 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.
+
+#
+# Turkish F keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 13 MINUS
+map key 43 COMMA
+map key 51 EQUALS
+map key 52 BACKSLASH
+map key 53 PERIOD
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '+'
+ base: '+'
+ shift: '*'
+ ralt: '\u00ac'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '\u00b9'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '\u00b2'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '^'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u00bc'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ ralt: '\u00bd'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+ ralt: '\u00be'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '\''
+ ralt: '{'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+ ralt: '['
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+ ralt: ']'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+ ralt: '}'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+ ralt: '\\'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '|'
+}
+
+### ROW 2
+
+key Q {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+ ralt: '@'
+}
+
+key W {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key E {
+ label: '\u011f'
+ base: '\u011f'
+ shift, capslock: '\u011e'
+}
+
+key R {
+ label: '\u0131'
+ base: '\u0131'
+ shift, capslock: 'I'
+ ralt: '\u00b6'
+ ralt+shift, ralt+capslock: '\u00ae'
+}
+
+key T {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key Y {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+ ralt: '\u00a5'
+}
+
+key U {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key I {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key O {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+ ralt: '\u00f8'
+ ralt+shift, ralt+capslock: '\u00d8'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+ ralt: '\u00a3'
+}
+
+key LEFT_BRACKET {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+ ralt: '"'
+}
+
+key RIGHT_BRACKET {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+ ralt: '~'
+}
+
+### ROW 3
+
+key A {
+ label: '\u0075'
+ base: '\u0075'
+ shift, capslock: '\u0055'
+ ralt: '\u00e6'
+ ralt+shift, ralt+capslock: '\u00c6'
+}
+
+key S {
+ label: 'i'
+ base: 'i'
+ shift, capslock: '\u0130'
+ ralt: '\u00df'
+ ralt+shift, ralt+capslock: '\u00a7'
+}
+
+key D {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key F {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+ ralt: '\u00aa'
+}
+
+key G {
+ label: '\u00fc'
+ base: '\u00fc'
+ shift, capslock: '\u00dc'
+}
+
+key H {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+ ralt: '\u20ba'
+}
+
+key J {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key K {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+ ralt: '\u00b4'
+}
+
+key APOSTROPHE {
+ label: '\u015f'
+ base: '\u015f'
+ shift, capslock: '\u015e'
+}
+
+key COMMA {
+ label: 'X'
+ base: 'x'
+ shift: 'X'
+ ralt: '\u0060'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+ ralt: '|'
+ ralt+shift, ralt+capslock: '\u00a6'
+}
+
+key Z {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+ ralt: '\u00ab'
+ ralt+shift, ralt+capslock: '<'
+}
+
+key X {
+ label: '\u00f6'
+ base: '\u00f6'
+ shift, capslock: '\u00d6'
+ ralt: '\u00bb'
+ ralt+shift, ralt+capslock: '>'
+}
+
+key C {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+ ralt: '\u00a2'
+ ralt+shift, ralt+capslock: '\u00a9'
+}
+
+key V {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key B {
+ label: '\u00e7'
+ base: '\u00e7'
+ shift, capslock: '\u00c7'
+}
+
+key N {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key M {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+ ralt: '\u00b5'
+ ralt+shift, ralt+capslock: '\u00ba'
+}
+
+key EQUALS {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+ ralt: '\u00d7'
+}
+
+key BACKSLASH {
+ label: '.'
+ base: '.'
+ shift, capslock: ':'
+ ralt: '\u00f7'
+}
+
+key PERIOD {
+ label: ','
+ base: ','
+ shift: ';'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index e95a15912397..c2585ff49a11 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -102,6 +102,9 @@
<!-- Turkish keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_turkish">Turkish</string>
+ <!-- Turkish keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_turkish_f">Turkish F</string>
+
<!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_ukrainian">Ukrainian</string>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index aa599ae7f2d0..d3c421da9055 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -128,6 +128,10 @@
android:label="@string/keyboard_layout_turkish"
android:keyboardLayout="@raw/keyboard_layout_turkish" />
+ <keyboard-layout android:name="keyboard_layout_turkish_f"
+ android:label="@string/keyboard_layout_turkish_f"
+ android:keyboardLayout="@raw/keyboard_layout_turkish_f" />
+
<keyboard-layout android:name="keyboard_layout_ukrainian"
android:label="@string/keyboard_layout_ukrainian"
android:keyboardLayout="@raw/keyboard_layout_ukrainian" />
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index 6276c4e2aa7d..0cf14e3f868c 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -20,6 +20,10 @@ import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static android.net.util.PrefixUtils.asIpPrefix;
+import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
+import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
+import static com.android.net.module.util.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH;
+
import static java.util.Arrays.asList;
import android.content.Context;
@@ -37,9 +41,10 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import java.net.Inet4Address;
import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
@@ -58,10 +63,6 @@ import java.util.Set;
public class PrivateAddressCoordinator {
public static final int PREFIX_LENGTH = 24;
- private static final int MAX_UBYTE = 256;
- private static final int BYTE_MASK = 0xff;
- private static final byte DEFAULT_ID = (byte) 42;
-
// Upstream monitor would be stopped when tethering is down. When tethering restart, downstream
// address may be requested before coordinator get current upstream notification. To ensure
// coordinator do not select conflict downstream prefix, mUpstreamPrefixMap would not be cleared
@@ -69,22 +70,22 @@ public class PrivateAddressCoordinator {
// mUpstreamPrefixMap when tethering is starting. See #maybeRemoveDeprecatedUpstreams().
private final ArrayMap<Network, List<IpPrefix>> mUpstreamPrefixMap;
private final ArraySet<IpServer> mDownstreams;
- // IANA has reserved the following three blocks of the IP address space for private intranets:
- // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
- // Tethering use 192.168.0.0/16 that has 256 contiguous class C network numbers.
- private static final String DEFAULT_TETHERING_PREFIX = "192.168.0.0/16";
private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24";
private static final String LEGACY_BLUETOOTH_IFACE_ADDRESS = "192.168.44.1/24";
- private final IpPrefix mTetheringPrefix;
+ private final List<IpPrefix> mTetheringPrefixes;
private final ConnectivityManager mConnectivityMgr;
private final TetheringConfiguration mConfig;
// keyed by downstream type(TetheringManager.TETHERING_*).
private final SparseArray<LinkAddress> mCachedAddresses;
public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
+ this(context, config, new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"))));
+ }
+
+ public PrivateAddressCoordinator(Context context, TetheringConfiguration config,
+ List<IpPrefix> prefixPools) {
mDownstreams = new ArraySet<>();
mUpstreamPrefixMap = new ArrayMap<>();
- mTetheringPrefix = new IpPrefix(DEFAULT_TETHERING_PREFIX);
mConnectivityMgr = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
mConfig = config;
@@ -92,6 +93,8 @@ public class PrivateAddressCoordinator {
// Reserved static addresses for bluetooth and wifi p2p.
mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
+
+ mTetheringPrefixes = prefixPools;
}
/**
@@ -179,52 +182,148 @@ public class PrivateAddressCoordinator {
return cachedAddress;
}
- // Address would be 192.168.[subAddress]/24.
- final byte[] bytes = mTetheringPrefix.getRawAddress();
- final int subAddress = getRandomSubAddr();
- final int subNet = (subAddress >> 8) & BYTE_MASK;
- bytes[3] = getSanitizedAddressSuffix(subAddress, (byte) 0, (byte) 1, (byte) 0xff);
- for (int i = 0; i < MAX_UBYTE; i++) {
- final int newSubNet = (subNet + i) & BYTE_MASK;
- bytes[2] = (byte) newSubNet;
-
- final InetAddress addr;
- try {
- addr = InetAddress.getByAddress(bytes);
- } catch (UnknownHostException e) {
- throw new IllegalStateException("Invalid address, shouldn't happen.", e);
+ for (IpPrefix prefixRange : mTetheringPrefixes) {
+ final LinkAddress newAddress = chooseDownstreamAddress(prefixRange);
+ if (newAddress != null) {
+ mDownstreams.add(ipServer);
+ mCachedAddresses.put(ipServer.interfaceType(), newAddress);
+ return newAddress;
}
-
- if (isConflict(new IpPrefix(addr, PREFIX_LENGTH))) continue;
-
- mDownstreams.add(ipServer);
- final LinkAddress newAddress = new LinkAddress(addr, PREFIX_LENGTH);
- mCachedAddresses.put(ipServer.interfaceType(), newAddress);
- return newAddress;
}
// No available address.
return null;
}
- private boolean isConflict(final IpPrefix prefix) {
- // Check whether this prefix is in use or conflict with any current upstream network.
- return isDownstreamPrefixInUse(prefix) || isConflictWithUpstream(prefix);
+ private int getPrefixBaseAddress(final IpPrefix prefix) {
+ return inet4AddressToIntHTH((Inet4Address) prefix.getAddress());
+ }
+
+ /**
+ * Check whether input prefix conflict with upstream prefixes or in-use downstream prefixes.
+ * If yes, return one of them.
+ */
+ private IpPrefix getConflictPrefix(final IpPrefix prefix) {
+ final IpPrefix upstream = getConflictWithUpstream(prefix);
+ if (upstream != null) return upstream;
+
+ return getInUseDownstreamPrefix(prefix);
+ }
+
+ // Get the next non-conflict sub prefix. E.g: To get next sub prefix from 10.0.0.0/8, if the
+ // previously selected prefix is 10.20.42.0/24(subPrefix: 0.20.42.0) and the conflicting prefix
+ // is 10.16.0.0/20 (10.16.0.0 ~ 10.16.15.255), then the max address under subPrefix is
+ // 0.16.15.255 and the next subPrefix is 0.16.16.255/24 (0.16.15.255 + 0.0.1.0).
+ // Note: the sub address 0.0.0.255 here is fine to be any value that it will be replaced as
+ // selected random sub address later.
+ private int getNextSubPrefix(final IpPrefix conflictPrefix, final int prefixRangeMask) {
+ final int suffixMask = ~prefixLengthToV4NetmaskIntHTH(conflictPrefix.getPrefixLength());
+ // The largest offset within the prefix assignment block that still conflicts with
+ // conflictPrefix.
+ final int maxConflict =
+ (getPrefixBaseAddress(conflictPrefix) | suffixMask) & ~prefixRangeMask;
+
+ final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH);
+ // Pick a sub prefix a full prefix (1 << (32 - PREFIX_LENGTH) addresses) greater than
+ // maxConflict. This ensures that the selected prefix never overlaps with conflictPrefix.
+ // There is no need to mask the result with PREFIX_LENGTH bits because this is done by
+ // findAvailablePrefixFromRange when it constructs the prefix.
+ return maxConflict + (1 << (32 - PREFIX_LENGTH));
}
- /** Get random sub address value. Return value is in 0 ~ 0xffff. */
+ private LinkAddress chooseDownstreamAddress(final IpPrefix prefixRange) {
+ // The netmask of the prefix assignment block (e.g., 0xfff00000 for 172.16.0.0/12).
+ final int prefixRangeMask = prefixLengthToV4NetmaskIntHTH(prefixRange.getPrefixLength());
+
+ // The zero address in the block (e.g., 0xac100000 for 172.16.0.0/12).
+ final int baseAddress = getPrefixBaseAddress(prefixRange);
+
+ // The subnet mask corresponding to PREFIX_LENGTH.
+ final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH);
+
+ // The offset within prefixRange of a randomly-selected prefix of length PREFIX_LENGTH.
+ // This may not be the prefix of the address returned by this method:
+ // - If it is already in use, the method will return an address in another prefix.
+ // - If all prefixes within prefixRange are in use, the method will return null. For
+ // example, for a /24 prefix within 172.26.0.0/12, this will be a multiple of 256 in
+ // [0, 1048576). In other words, a random 32-bit number with mask 0x000fff00.
+ //
+ // prefixRangeMask is required to ensure no wrapping. For example, consider:
+ // - prefixRange 127.0.0.0/8
+ // - randomPrefixStart 127.255.255.0
+ // - A conflicting prefix of 127.255.254.0/23
+ // In this case without prefixRangeMask, getNextSubPrefix would return 128.0.0.0, which
+ // means the "start < end" check in findAvailablePrefixFromRange would not reject the prefix
+ // because Java doesn't have unsigned integers, so 128.0.0.0 = 0x80000000 = -2147483648
+ // is less than 127.0.0.0 = 0x7f000000 = 2130706432.
+ //
+ // Additionally, it makes debug output easier to read by making the numbers smaller.
+ final int randomPrefixStart = getRandomInt() & ~prefixRangeMask & prefixMask;
+
+ // A random offset within the prefix. Used to determine the local address once the prefix
+ // is selected. It does not result in an IPv4 address ending in .0, .1, or .255
+ // For a PREFIX_LENGTH of 255, this is a number between 2 and 254.
+ final int subAddress = getSanitizedSubAddr(~prefixMask);
+
+ // Find a prefix length PREFIX_LENGTH between randomPrefixStart and the end of the block,
+ // such that the prefix does not conflict with any upstream.
+ IpPrefix downstreamPrefix = findAvailablePrefixFromRange(
+ randomPrefixStart, (~prefixRangeMask) + 1, baseAddress, prefixRangeMask);
+ if (downstreamPrefix != null) return getLinkAddress(downstreamPrefix, subAddress);
+
+ // If that failed, do the same, but between 0 and randomPrefixStart.
+ downstreamPrefix = findAvailablePrefixFromRange(
+ 0, randomPrefixStart, baseAddress, prefixRangeMask);
+
+ return getLinkAddress(downstreamPrefix, subAddress);
+ }
+
+ private LinkAddress getLinkAddress(final IpPrefix prefix, final int subAddress) {
+ if (prefix == null) return null;
+
+ final InetAddress address = intToInet4AddressHTH(getPrefixBaseAddress(prefix) | subAddress);
+ return new LinkAddress(address, PREFIX_LENGTH);
+ }
+
+ private IpPrefix findAvailablePrefixFromRange(final int start, final int end,
+ final int baseAddress, final int prefixRangeMask) {
+ int newSubPrefix = start;
+ while (newSubPrefix < end) {
+ final InetAddress address = intToInet4AddressHTH(baseAddress | newSubPrefix);
+ final IpPrefix prefix = new IpPrefix(address, PREFIX_LENGTH);
+
+ final IpPrefix conflictPrefix = getConflictPrefix(prefix);
+
+ if (conflictPrefix == null) return prefix;
+
+ newSubPrefix = getNextSubPrefix(conflictPrefix, prefixRangeMask);
+ }
+
+ return null;
+ }
+
+ /** Get random int which could be used to generate random address. */
@VisibleForTesting
- public int getRandomSubAddr() {
- return ((new Random()).nextInt()) & 0xffff; // subNet is in 0 ~ 0xffff.
+ public int getRandomInt() {
+ return (new Random()).nextInt();
}
- private byte getSanitizedAddressSuffix(final int source, byte... excluded) {
- final byte subId = (byte) (source & BYTE_MASK);
- for (byte value : excluded) {
- if (subId == value) return DEFAULT_ID;
+ /** Get random subAddress and avoid selecting x.x.x.0, x.x.x.1 and x.x.x.255 address. */
+ private int getSanitizedSubAddr(final int subAddrMask) {
+ final int randomSubAddr = getRandomInt() & subAddrMask;
+ // If prefix length > 30, the selecting speace would be less than 4 which may be hard to
+ // avoid 3 consecutive address.
+ if (PREFIX_LENGTH > 30) return randomSubAddr;
+
+ // TODO: maybe it is not necessary to avoid .0, .1 and .255 address because tethering
+ // address would not be conflicted. This code only works because PREFIX_LENGTH is not longer
+ // than 24
+ final int candidate = randomSubAddr & 0xff;
+ if (candidate == 0 || candidate == 1 || candidate == 255) {
+ return (randomSubAddr & 0xfffffffc) + 2;
}
- return subId;
+ return randomSubAddr;
}
/** Release downstream record for IpServer. */
@@ -237,14 +336,18 @@ public class PrivateAddressCoordinator {
mUpstreamPrefixMap.clear();
}
- private boolean isConflictWithUpstream(final IpPrefix source) {
+ private IpPrefix getConflictWithUpstream(final IpPrefix prefix) {
for (int i = 0; i < mUpstreamPrefixMap.size(); i++) {
final List<IpPrefix> list = mUpstreamPrefixMap.valueAt(i);
- for (IpPrefix target : list) {
- if (isConflictPrefix(source, target)) return true;
+ for (IpPrefix upstream : list) {
+ if (isConflictPrefix(prefix, upstream)) return upstream;
}
}
- return false;
+ return null;
+ }
+
+ private boolean isConflictWithUpstream(final IpPrefix prefix) {
+ return getConflictWithUpstream(prefix) != null;
}
private boolean isConflictPrefix(final IpPrefix prefix1, final IpPrefix prefix2) {
@@ -257,11 +360,10 @@ public class PrivateAddressCoordinator {
// InUse Prefixes are prefixes of mCachedAddresses which are active downstream addresses, last
// downstream addresses(reserved for next time) and static addresses(e.g. bluetooth, wifi p2p).
- private boolean isDownstreamPrefixInUse(final IpPrefix prefix) {
- // This class always generates downstream prefixes with the same prefix length, so
- // prefixes cannot be contained in each other. They can only be equal to each other.
+ private IpPrefix getInUseDownstreamPrefix(final IpPrefix prefix) {
for (int i = 0; i < mCachedAddresses.size(); i++) {
- if (prefix.equals(asIpPrefix(mCachedAddresses.valueAt(i)))) return true;
+ final IpPrefix downstream = asIpPrefix(mCachedAddresses.valueAt(i));
+ if (isConflictPrefix(prefix, downstream)) return downstream;
}
// IpServer may use manually-defined address (mStaticIpv4ServerAddr) which does not include
@@ -270,10 +372,10 @@ public class PrivateAddressCoordinator {
final IpPrefix target = getDownstreamPrefix(downstream);
if (target == null) continue;
- if (isConflictPrefix(prefix, target)) return true;
+ if (isConflictPrefix(prefix, target)) return target;
}
- return false;
+ return null;
}
private IpPrefix getDownstreamPrefix(final IpServer downstream) {
@@ -284,6 +386,13 @@ public class PrivateAddressCoordinator {
}
void dump(final IndentingPrintWriter pw) {
+ pw.println("mTetheringPrefixes:");
+ pw.increaseIndent();
+ for (IpPrefix prefix : mTetheringPrefixes) {
+ pw.println(prefix);
+ }
+ pw.decreaseIndent();
+
pw.println("mUpstreamPrefixMap:");
pw.increaseIndent();
for (int i = 0; i < mUpstreamPrefixMap.size(); i++) {
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 474f4e8b603a..5a0c5b0cff5f 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -326,7 +326,7 @@ public class Tethering {
// It is OK for the configuration to be passed to the PrivateAddressCoordinator at
// construction time because the only part of the configuration it uses is
// shouldEnableWifiP2pDedicatedIp(), and currently do not support changing that.
- mPrivateAddressCoordinator = new PrivateAddressCoordinator(mContext, mConfig);
+ mPrivateAddressCoordinator = mDeps.getPrivateAddressCoordinator(mContext, mConfig);
// Must be initialized after tethering configuration is loaded because BpfCoordinator
// constructor needs to use the configuration.
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 131a5fbf2abe..45b914178e97 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -156,4 +156,12 @@ public abstract class TetheringDependencies {
public boolean isTetheringDenied() {
return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true");
}
+
+ /**
+ * Get a reference to PrivateAddressCoordinator to be used by Tethering.
+ */
+ public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
+ TetheringConfiguration cfg) {
+ return new PrivateAddressCoordinator(ctx, cfg);
+ }
}
diff --git a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
index 95e36fa18f42..42a91aa9acd5 100644
--- a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
+++ b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
@@ -17,9 +17,9 @@
package android.net.ip;
import static android.system.OsConstants.IPPROTO_ICMPV6;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static com.android.internal.util.BitUtils.uint16;
+import static com.android.net.module.util.IpUtils.icmpv6Checksum;
+import static com.android.net.module.util.NetworkStackConstants.ETHER_SRC_ADDR_OFFSET;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -30,34 +30,29 @@ import android.content.Context;
import android.net.INetd;
import android.net.InetAddresses;
import android.net.MacAddress;
-import android.net.TestNetworkInterface;
-import android.net.TestNetworkManager;
import android.net.util.InterfaceParams;
import android.net.util.TetheringUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
-import android.system.ErrnoException;
-import android.system.Os;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.net.module.util.IpUtils;
import com.android.testutils.TapPacketReader;
+import com.android.testutils.TapPacketReaderRule;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
-import java.io.FileDescriptor;
import java.nio.ByteBuffer;
-import java.util.concurrent.atomic.AtomicReference;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -65,16 +60,18 @@ public class DadProxyTest {
private static final int DATA_BUFFER_LEN = 4096;
private static final int PACKET_TIMEOUT_MS = 5_000;
- // TODO: make NetworkStackConstants accessible to this test and use the constant from there.
- private static final int ETHER_SRC_ADDR_OFFSET = 6;
+ // Start the readers manually on a common handler shared with DadProxy, for simplicity
+ @Rule
+ public final TapPacketReaderRule mUpstreamReader = new TapPacketReaderRule(
+ DATA_BUFFER_LEN, false /* autoStart */);
+ @Rule
+ public final TapPacketReaderRule mTetheredReader = new TapPacketReaderRule(
+ DATA_BUFFER_LEN, false /* autoStart */);
- private DadProxy mProxy;
- TestNetworkInterface mUpstreamTestIface, mTetheredTestIface;
private InterfaceParams mUpstreamParams, mTetheredParams;
private HandlerThread mHandlerThread;
private Handler mHandler;
private TapPacketReader mUpstreamPacketReader, mTetheredPacketReader;
- private FileDescriptor mUpstreamTapFd, mTetheredTapFd;
private static INetd sNetd;
@@ -106,12 +103,12 @@ public class DadProxyTest {
@After
public void tearDown() throws Exception {
+ mUpstreamReader.stop();
+ mTetheredReader.stop();
+
if (mHandlerThread != null) {
- mHandler.post(mUpstreamPacketReader::stop); // Also closes the socket
- mHandler.post(mTetheredPacketReader::stop); // Also closes the socket
- mUpstreamTapFd = null;
- mTetheredTapFd = null;
mHandlerThread.quitSafely();
+ mHandlerThread.join(PACKET_TIMEOUT_MS);
}
if (mTetheredParams != null) {
@@ -120,54 +117,20 @@ public class DadProxyTest {
if (mUpstreamParams != null) {
sNetd.networkRemoveInterface(INetd.LOCAL_NET_ID, mUpstreamParams.name);
}
-
- if (mUpstreamTestIface != null) {
- try {
- Os.close(mUpstreamTestIface.getFileDescriptor().getFileDescriptor());
- } catch (ErrnoException e) { }
- }
-
- if (mTetheredTestIface != null) {
- try {
- Os.close(mTetheredTestIface.getFileDescriptor().getFileDescriptor());
- } catch (ErrnoException e) { }
- }
- }
-
- private TestNetworkInterface setupTapInterface() {
- final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
- AtomicReference<TestNetworkInterface> iface = new AtomicReference<>();
-
- inst.getUiAutomation().adoptShellPermissionIdentity();
- try {
- final TestNetworkManager tnm = (TestNetworkManager) inst.getContext().getSystemService(
- Context.TEST_NETWORK_SERVICE);
- iface.set(tnm.createTapInterface());
- } finally {
- inst.getUiAutomation().dropShellPermissionIdentity();
- }
-
- return iface.get();
}
private void setupTapInterfaces() {
// Create upstream test iface.
- mUpstreamTestIface = setupTapInterface();
- mUpstreamParams = InterfaceParams.getByName(mUpstreamTestIface.getInterfaceName());
+ mUpstreamReader.start(mHandler);
+ mUpstreamParams = InterfaceParams.getByName(mUpstreamReader.iface.getInterfaceName());
assertNotNull(mUpstreamParams);
- mUpstreamTapFd = mUpstreamTestIface.getFileDescriptor().getFileDescriptor();
- mUpstreamPacketReader = new TapPacketReader(mHandler, mUpstreamTapFd,
- DATA_BUFFER_LEN);
- mHandler.post(mUpstreamPacketReader::start);
+ mUpstreamPacketReader = mUpstreamReader.getReader();
// Create tethered test iface.
- mTetheredTestIface = setupTapInterface();
- mTetheredParams = InterfaceParams.getByName(mTetheredTestIface.getInterfaceName());
+ mTetheredReader.start(mHandler);
+ mTetheredParams = InterfaceParams.getByName(mTetheredReader.getIface().getInterfaceName());
assertNotNull(mTetheredParams);
- mTetheredTapFd = mTetheredTestIface.getFileDescriptor().getFileDescriptor();
- mTetheredPacketReader = new TapPacketReader(mHandler, mTetheredTapFd,
- DATA_BUFFER_LEN);
- mHandler.post(mTetheredPacketReader::start);
+ mTetheredPacketReader = mTetheredReader.getReader();
}
private static final int IPV6_HEADER_LEN = 40;
@@ -177,31 +140,6 @@ public class DadProxyTest {
private static final int ICMPV6_CHECKSUM_OFFSET = 2;
private static final int ETHER_TYPE_IPV6 = 0x86dd;
- // TODO: move the IpUtils code to frameworks/lib/net and link it statically.
- private static int checksumFold(int sum) {
- while (sum > 0xffff) {
- sum = (sum >> 16) + (sum & 0xffff);
- }
- return sum;
- }
-
- // TODO: move the IpUtils code to frameworks/lib/net and link it statically.
- private static short checksumAdjust(short checksum, short oldWord, short newWord) {
- checksum = (short) ~checksum;
- int tempSum = checksumFold(uint16(checksum) + uint16(newWord) + 0xffff - uint16(oldWord));
- return (short) ~tempSum;
- }
-
- // TODO: move the IpUtils code to frameworks/lib/net and link it statically.
- private static short icmpv6Checksum(ByteBuffer buf, int ipOffset, int transportOffset,
- int transportLen) {
- // The ICMPv6 checksum is the same as the TCP checksum, except the pseudo-header uses
- // 58 (ICMPv6) instead of 6 (TCP). Calculate the TCP checksum, and then do an incremental
- // checksum adjustment for the change in the next header byte.
- short checksum = IpUtils.tcpChecksum(buf, ipOffset, transportOffset, transportLen);
- return checksumAdjust(checksum, (short) IPPROTO_TCP, (short) IPPROTO_ICMPV6);
- }
-
private static ByteBuffer createDadPacket(int type) {
// Refer to buildArpPacket()
int icmpLen = ICMPV6_NA_NS_LEN
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index 191eb6e71149..86e6f11659c6 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -51,6 +51,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public final class PrivateAddressCoordinatorTest {
@@ -70,7 +73,17 @@ public final class PrivateAddressCoordinatorTest {
private final Network mWifiNetwork = new Network(1);
private final Network mMobileNetwork = new Network(2);
private final Network mVpnNetwork = new Network(3);
- private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork};
+ private final Network mMobileNetwork2 = new Network(4);
+ private final Network mMobileNetwork3 = new Network(5);
+ private final Network mMobileNetwork4 = new Network(6);
+ private final Network mMobileNetwork5 = new Network(7);
+ private final Network mMobileNetwork6 = new Network(8);
+ private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork,
+ mMobileNetwork2, mMobileNetwork3, mMobileNetwork4, mMobileNetwork5, mMobileNetwork6};
+ private final ArrayList<IpPrefix> mTetheringPrefixes = new ArrayList<>(Arrays.asList(
+ new IpPrefix("192.168.0.0/16"),
+ new IpPrefix("172.16.0.0/12"),
+ new IpPrefix("10.0.0.0/8")));
private void setUpIpServers() throws Exception {
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
@@ -87,7 +100,8 @@ public final class PrivateAddressCoordinatorTest {
when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
setUpIpServers();
- mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
+ mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig,
+ mTetheringPrefixes));
}
@Test
@@ -117,28 +131,28 @@ public final class PrivateAddressCoordinatorTest {
@Test
public void testSanitizedAddress() throws Exception {
int fakeSubAddr = 0x2b00; // 43.0.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
LinkAddress actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.43.42/24"), actualAddress);
+ assertEquals(new LinkAddress("192.168.43.2/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
fakeSubAddr = 0x2d01; // 45.1.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.45.42/24"), actualAddress);
+ assertEquals(new LinkAddress("192.168.45.2/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
fakeSubAddr = 0x2eff; // 46.255.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, false /* useLastAddress */);
- assertEquals(new LinkAddress("192.168.46.42/24"), actualAddress);
+ assertEquals(new LinkAddress("192.168.46.254/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
fakeSubAddr = 0x2f05; // 47.5.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, false /* useLastAddress */);
assertEquals(new LinkAddress("192.168.47.5/24"), actualAddress);
@@ -148,7 +162,7 @@ public final class PrivateAddressCoordinatorTest {
@Test
public void testReservedPrefix() throws Exception {
// - Test bluetooth prefix is reserved.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
getSubAddress(mBluetoothAddress.getAddress().getAddress()));
final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, false /* useLastAddress */);
@@ -157,7 +171,7 @@ public final class PrivateAddressCoordinatorTest {
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
// - Test previous enabled hotspot prefix(cached prefix) is reserved.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
getSubAddress(hotspotAddress.getAddress().getAddress()));
final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mUsbIpServer, false /* useLastAddress */);
@@ -167,7 +181,7 @@ public final class PrivateAddressCoordinatorTest {
mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
// - Test wifi p2p prefix is reserved.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
final LinkAddress etherAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mEthernetIpServer, false /* useLastAddress */);
@@ -182,7 +196,7 @@ public final class PrivateAddressCoordinatorTest {
public void testRequestLastDownstreamAddress() throws Exception {
final int fakeHotspotSubAddr = 0x2b05;
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, true /* useLastAddress */);
assertEquals("Wrong wifi prefix: ", predefinedPrefix, asIpPrefix(hotspotAddress));
@@ -196,7 +210,7 @@ public final class PrivateAddressCoordinatorTest {
mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
final int newFakeSubAddr = 0x3c05;
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
final LinkAddress newHotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, true /* useLastAddress */);
@@ -229,11 +243,10 @@ public final class PrivateAddressCoordinatorTest {
@Test
public void testNoConflictUpstreamPrefix() throws Exception {
- final int fakeHotspotSubId = 43;
- final int fakeHotspotSubAddr = 0x2b05;
+ final int fakeHotspotSubAddr = 0x2b05; // 43.5
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
// Force always get subAddress "43.5" for conflict testing.
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
// - Enable hotspot with prefix 192.168.43.0/24
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer, true /* useLastAddress */);
@@ -312,6 +325,209 @@ public final class PrivateAddressCoordinatorTest {
assertEquals(predefinedPrefix, ethPrefix);
}
+ @Test
+ public void testChooseAvailablePrefix() throws Exception {
+ final int randomAddress = 0x8605; // 134.5
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress);
+ final LinkAddress addr0 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.134.5.
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.134.5/24"), addr0);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr0);
+ final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
+ new LinkAddress("192.168.134.13/26"), null,
+ makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
+
+ // Check whether return address is next prefix of 192.168.134.0/24.
+ final LinkAddress addr1 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.135.5/24"), addr1);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr1);
+ final UpstreamNetworkState wifiUpstream2 = buildUpstreamNetworkState(mWifiNetwork,
+ new LinkAddress("192.168.149.16/19"), null,
+ makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream2);
+
+
+ // The conflict range is 128 ~ 159, so the address is 192.168.160.5/24.
+ final LinkAddress addr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.160.5/24"), addr2);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr2);
+ final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("192.168.129.53/18"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ // Update another conflict upstream which is covered by the previous one (but not the first
+ // one) and verify whether this would affect the result.
+ final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2,
+ new LinkAddress("192.168.170.7/19"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2);
+
+ // The conflict range are 128 ~ 159 and 159 ~ 191, so the address is 192.168.192.5/24.
+ final LinkAddress addr3 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.192.5/24"), addr3);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr3);
+ final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3,
+ new LinkAddress("192.168.188.133/17"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3);
+
+ // Conflict range: 128 ~ 255. The next available address is 192.168.0.5 because
+ // 192.168.134/24 ~ 192.168.255.255/24 is not available.
+ final LinkAddress addr4 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.0.5/24"), addr4);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr4);
+ final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4,
+ new LinkAddress("192.168.3.59/21"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4);
+
+ // Conflict ranges: 128 ~ 255 and 0 ~ 7, so the address is 192.168.8.5/24.
+ final LinkAddress addr5 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr5);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr5);
+ final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5,
+ new LinkAddress("192.168.68.43/21"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5);
+
+ // Update an upstream that does *not* conflict, check whether return the same address
+ // 192.168.5/24.
+ final LinkAddress addr6 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr6);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr6);
+ final UpstreamNetworkState mobileUpstream6 = buildUpstreamNetworkState(mMobileNetwork6,
+ new LinkAddress("192.168.10.97/21"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream6);
+
+ // Conflict ranges: 0 ~ 15 and 128 ~ 255, so the address is 192.168.16.5/24.
+ final LinkAddress addr7 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.16.5/24"), addr7);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr7);
+ final UpstreamNetworkState mobileUpstream7 = buildUpstreamNetworkState(mMobileNetwork6,
+ new LinkAddress("192.168.0.0/17"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream7);
+
+ // Choose prefix from next range(172.16.0.0/12) when no available prefix in 192.168.0.0/16.
+ final LinkAddress addr8 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.16.134.5/24"), addr8);
+ when(mHotspotIpServer.getAddress()).thenReturn(addr6);
+ }
+
+ @Test
+ public void testChoosePrefixFromDifferentRanges() throws Exception {
+ final int randomAddress = 0x1f2b2a; // 31.43.42
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress);
+ final LinkAddress classC1 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.43.42.
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.43.42/24"), classC1);
+ when(mHotspotIpServer.getAddress()).thenReturn(classC1);
+ final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
+ new LinkAddress("192.168.88.23/17"), null,
+ makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
+ verifyNotifyConflictAndRelease(mHotspotIpServer);
+
+ // Check whether return address is next address of prefix 192.168.128.0/17.
+ final LinkAddress classC2 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("192.168.128.42/24"), classC2);
+ when(mHotspotIpServer.getAddress()).thenReturn(classC2);
+ final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("192.1.2.3/8"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream);
+ verifyNotifyConflictAndRelease(mHotspotIpServer);
+
+ // Check whether return address is under prefix 172.16.0.0/12.
+ final LinkAddress classB1 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.31.43.42/24"), classB1);
+ when(mHotspotIpServer.getAddress()).thenReturn(classB1);
+ final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2,
+ new LinkAddress("172.28.123.100/14"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2);
+ verifyNotifyConflictAndRelease(mHotspotIpServer);
+
+ // 172.28.0.0 ~ 172.31.255.255 is not available.
+ // Check whether return address is next address of prefix 172.16.0.0/14.
+ final LinkAddress classB2 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.16.0.42/24"), classB2);
+ when(mHotspotIpServer.getAddress()).thenReturn(classB2);
+
+ // Check whether new downstream is next address of address 172.16.0.42/24.
+ final LinkAddress classB3 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.16.1.42/24"), classB3);
+ when(mUsbIpServer.getAddress()).thenReturn(classB3);
+ final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3,
+ new LinkAddress("172.16.0.1/24"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3);
+ verifyNotifyConflictAndRelease(mHotspotIpServer);
+ verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+
+ // Check whether return address is next address of prefix 172.16.1.42/24.
+ final LinkAddress classB4 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.16.2.42/24"), classB4);
+ when(mHotspotIpServer.getAddress()).thenReturn(classB4);
+ final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4,
+ new LinkAddress("172.16.0.1/13"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4);
+ verifyNotifyConflictAndRelease(mHotspotIpServer);
+ verifyNotifyConflictAndRelease(mUsbIpServer);
+
+ // Check whether return address is next address of prefix 172.16.0.1/13.
+ final LinkAddress classB5 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.24.0.42/24"), classB5);
+ when(mHotspotIpServer.getAddress()).thenReturn(classB5);
+ // Check whether return address is next address of prefix 172.24.0.42/24.
+ final LinkAddress classB6 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("172.24.1.42/24"), classB6);
+ when(mUsbIpServer.getAddress()).thenReturn(classB6);
+ final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5,
+ new LinkAddress("172.24.0.1/12"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5);
+ verifyNotifyConflictAndRelease(mHotspotIpServer);
+ verifyNotifyConflictAndRelease(mUsbIpServer);
+
+ // Check whether return address is prefix 10.0.0.0/8 + subAddress 0.31.43.42.
+ final LinkAddress classA1 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("10.31.43.42/24"), classA1);
+ when(mHotspotIpServer.getAddress()).thenReturn(classA1);
+ // Check whether new downstream is next address of address 10.31.43.42/24.
+ final LinkAddress classA2 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, true/* useLastAddress */);
+ assertEquals("Wrong prefix: ", new LinkAddress("10.31.44.42/24"), classA2);
+ }
+
+ private void verifyNotifyConflictAndRelease(final IpServer ipServer) throws Exception {
+ verify(ipServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ mPrivateAddressCoordinator.releaseDownstream(ipServer);
+ reset(ipServer);
+ setUpIpServers();
+ }
+
private int getSubAddress(final byte... ipv4Address) {
assertEquals(4, ipv4Address.length);
@@ -330,7 +546,7 @@ public final class PrivateAddressCoordinatorTest {
@Test
public void testEnableLegacyWifiP2PAddress() throws Exception {
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
// No matter #shouldEnableWifiP2pDedicatedIp() is enabled or not, legacy wifi p2p prefix
// is resevered.
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index df570206e389..20e94b256ad1 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -24,6 +24,9 @@ import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
+import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
@@ -179,6 +182,7 @@ public class TetheringTest {
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
private static final String TEST_NCM_IFNAME = "test_ncm0";
private static final String TEST_ETH_IFNAME = "test_eth0";
+ private static final String TEST_BT_IFNAME = "test_pan0";
private static final String TETHERING_NAME = "Tethering";
private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
@@ -230,6 +234,7 @@ public class TetheringTest {
private TetheringConfiguration mConfig;
private EntitlementManager mEntitleMgr;
private OffloadController mOffloadCtrl;
+ private PrivateAddressCoordinator mPrivateAddressCoordinator;
private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) {
@@ -446,6 +451,18 @@ public class TetheringTest {
public boolean isTetheringDenied() {
return false;
}
+
+
+ @Override
+ public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
+ TetheringConfiguration cfg) {
+ final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
+ new IpPrefix("192.168.0.0/16"),
+ new IpPrefix("172.16.0.0/12"),
+ new IpPrefix("10.0.0.0/8")));
+ mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(ctx, cfg, prefixPool));
+ return mPrivateAddressCoordinator;
+ }
}
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
@@ -1875,27 +1892,36 @@ public class TetheringTest {
sendConfigurationChanged();
}
- private static UpstreamNetworkState buildV4WifiUpstreamState(final String ipv4Address,
- final int prefixLength, final Network network) {
+ private static UpstreamNetworkState buildV4UpstreamState(final LinkAddress address,
+ final Network network, final String iface, final int transportType) {
final LinkProperties prop = new LinkProperties();
- prop.setInterfaceName(TEST_WIFI_IFNAME);
+ prop.setInterfaceName(iface);
- prop.addLinkAddress(
- new LinkAddress(InetAddresses.parseNumericAddress(ipv4Address),
- prefixLength));
+ prop.addLinkAddress(address);
final NetworkCapabilities capabilities = new NetworkCapabilities()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ .addTransportType(transportType);
return new UpstreamNetworkState(prop, capabilities, network);
}
+ private void updateV4Upstream(final LinkAddress ipv4Address, final Network network,
+ final String iface, final int transportType) {
+ final UpstreamNetworkState upstream = buildV4UpstreamState(ipv4Address, network, iface,
+ transportType);
+ mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
+ Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
+ UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
+ 0,
+ upstream);
+ mLooper.dispatchAll();
+ }
+
@Test
public void testHandleIpConflict() throws Exception {
final Network wifiNetwork = new Network(200);
final Network[] allNetworks = { wifiNetwork };
when(mCm.getAllNetworks()).thenReturn(allNetworks);
- UpstreamNetworkState upstreamNetwork = null;
- runUsbTethering(upstreamNetwork);
+ runUsbTethering(null);
final ArgumentCaptor<InterfaceConfigurationParcel> ifaceConfigCaptor =
ArgumentCaptor.forClass(InterfaceConfigurationParcel.class);
verify(mNetd).interfaceSetCfg(ifaceConfigCaptor.capture());
@@ -1903,13 +1929,10 @@ public class TetheringTest {
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
any(), any());
reset(mNetd, mUsbManager);
- upstreamNetwork = buildV4WifiUpstreamState(ipv4Address, 30, wifiNetwork);
- mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
- Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- 0,
- upstreamNetwork);
- mLooper.dispatchAll();
+
+ // Cause a prefix conflict by assigning a /30 out of the downstream's /24 to the upstream.
+ updateV4Upstream(new LinkAddress(InetAddresses.parseNumericAddress(ipv4Address), 30),
+ wifiNetwork, TEST_WIFI_IFNAME, TRANSPORT_WIFI);
// verify turn off usb tethering
verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
mTethering.interfaceRemoved(TEST_USB_IFNAME);
@@ -1921,9 +1944,10 @@ public class TetheringTest {
@Test
public void testNoAddressAvailable() throws Exception {
final Network wifiNetwork = new Network(200);
- final Network[] allNetworks = { wifiNetwork };
+ final Network btNetwork = new Network(201);
+ final Network mobileNetwork = new Network(202);
+ final Network[] allNetworks = { wifiNetwork, btNetwork, mobileNetwork };
when(mCm.getAllNetworks()).thenReturn(allNetworks);
- final String upstreamAddress = "192.168.0.100";
runUsbTethering(null);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
any(), any());
@@ -1940,13 +1964,13 @@ public class TetheringTest {
mLooper.dispatchAll();
reset(mUsbManager, mEm);
- final UpstreamNetworkState upstreamNetwork = buildV4WifiUpstreamState(
- upstreamAddress, 16, wifiNetwork);
- mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
- Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- 0,
- upstreamNetwork);
+ updateV4Upstream(new LinkAddress("192.168.0.100/16"), wifiNetwork, TEST_WIFI_IFNAME,
+ TRANSPORT_WIFI);
+ updateV4Upstream(new LinkAddress("172.16.0.0/12"), btNetwork, TEST_BT_IFNAME,
+ TRANSPORT_BLUETOOTH);
+ updateV4Upstream(new LinkAddress("10.0.0.0/8"), mobileNetwork, TEST_MOBILE_IFNAME,
+ TRANSPORT_CELLULAR);
+
mLooper.dispatchAll();
// verify turn off usb tethering
verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b59f7645445d..bb9f6d2c8354 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -140,6 +140,7 @@ import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
import android.net.util.LinkPropertiesUtils.CompareResult;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
+import android.os.BasicShellCommandHandler;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -156,11 +157,8 @@ import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
-import android.os.ShellCallback;
-import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -7658,14 +7656,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
- public void onShellCommand(@NonNull FileDescriptor in, @NonNull FileDescriptor out,
- FileDescriptor err, @NonNull String[] args, ShellCallback callback,
- @NonNull ResultReceiver resultReceiver) {
- (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
+ public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ return new ShellCmd().exec(this, in.getFileDescriptor(), out.getFileDescriptor(),
+ err.getFileDescriptor(), args);
}
- private class ShellCmd extends ShellCommand {
-
+ private class ShellCmd extends BasicShellCommandHandler {
@Override
public int onCommand(String cmd) {
if (cmd == null) {
diff --git a/services/core/java/com/android/server/MountServiceIdler.java b/services/core/java/com/android/server/MountServiceIdler.java
index 6bc1a570b7c0..0f4c94bc8d4f 100644
--- a/services/core/java/com/android/server/MountServiceIdler.java
+++ b/services/core/java/com/android/server/MountServiceIdler.java
@@ -113,6 +113,7 @@ public class MountServiceIdler extends JobService {
JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService);
builder.setRequiresDeviceIdle(true);
builder.setRequiresBatteryNotLow(true);
+ builder.setRequiresCharging(true);
builder.setMinimumLatency(nextScheduleTime);
tm.schedule(builder.build());
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2f15918d3064..6c7f235dec6f 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -2152,7 +2152,11 @@ public class Vpn {
break;
}
- // Prepare arguments for mtpd.
+ // Prepare arguments for mtpd. MTU/MRU calculated conservatively. Only IPv4 supported
+ // because LegacyVpn.
+ // 1500 - 60 (Carrier-internal IPv6 + UDP + GTP) - 10 (PPP) - 16 (L2TP) - 8 (UDP)
+ // - 77 (IPsec w/ SHA-2 512, 256b trunc-len, AES-CBC) - 8 (UDP encap) - 20 (IPv4)
+ // - 28 (464xlat)
String[] mtpd = null;
switch (profile.type) {
case VpnProfile.TYPE_PPTP:
@@ -2160,7 +2164,7 @@ public class Vpn {
iface, "pptp", profile.server, "1723",
"name", profile.username, "password", profile.password,
"linkname", "vpn", "refuse-eap", "nodefaultroute",
- "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
+ "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270",
(profile.mppe ? "+mppe" : "nomppe"),
};
break;
@@ -2170,7 +2174,7 @@ public class Vpn {
iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
"name", profile.username, "password", profile.password,
"linkname", "vpn", "refuse-eap", "nodefaultroute",
- "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
+ "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270",
};
break;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2d7e79a7073c..a31aacbde46f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -3867,7 +3867,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// quick check: if this uid doesn't have INTERNET permission, it
// doesn't have network access anyway, so it is a waste to mess
// with it here.
- if (hasInternetPermissionUL(uid)) {
+ if (hasInternetPermissionUL(uid) && !isUidForegroundOnRestrictPowerUL(uid)) {
uidRules.put(uid, FIREWALL_RULE_DENY);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index d202a2a60738..5646c752fc90 100644
--- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -30,6 +30,7 @@ import android.telephony.SubscriptionManager;
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.internal.util.CollectionUtils;
@@ -94,39 +95,41 @@ public class NetworkStatsSubscriptionsMonitor extends
// also needed to track CBRS.
final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
- for (final int subId : newSubs) {
- final RatTypeListener match = CollectionUtils.find(mRatListeners,
- it -> it.mSubId == subId);
- if (match != null) continue;
-
- // Create listener for every newly added sub. Also store subscriberId into it to
- // prevent binder call to telephony when querying RAT. If the subscriberId is empty
- // for any reason, such as SIM PIN locked, skip registration.
- // SubscriberId will be unavailable again if 1. modem crashed 2. reboot
- // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized
- // with active sub list once all subscriberIds are ready.
- final String subscriberId = mTeleManager.getSubscriberId(subId);
- if (TextUtils.isEmpty(subscriberId)) {
- Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub "
- + subId + ", skip listener registration");
+ // 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 =
+ CollectionUtils.mapNotNull(newSubs, subId -> {
+ final String subscriberId = mTeleManager.getSubscriberId(subId);
+ return TextUtils.isEmpty(subscriberId) ? null : new Pair(subId, subscriberId);
+ });
+
+ for (final Pair<Integer, String> sub : filteredNewSubs) {
+ // Fully match listener with subId and IMSI, since in some rare cases, IMSI might be
+ // suddenly change regardless of subId, such as switch IMSI feature in modem side.
+ // If that happens, register new listener with new IMSI and remove old one later.
+ if (CollectionUtils.find(mRatListeners,
+ it -> it.equalsKey(sub.first, sub.second)) != null) {
continue;
}
+
final RatTypeListener listener =
- new RatTypeListener(mExecutor, this, subId, subscriberId);
+ new RatTypeListener(mExecutor, this, sub.first, sub.second);
mRatListeners.add(listener);
// Register listener to the telephony manager that associated with specific sub.
- mTeleManager.createForSubscriptionId(subId)
+ mTeleManager.createForSubscriptionId(sub.first)
.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
- Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId);
+ Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
}
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
- // If the new list contains the subId of the listener, keeps it.
- final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId);
- if (match != null) continue;
-
- handleRemoveRatTypeListener(listener);
+ // If there is no subId and IMSI matched the listener, removes it.
+ if (CollectionUtils.find(filteredNewSubs,
+ it -> listener.equalsKey(it.first, it.second)) == null) {
+ handleRemoveRatTypeListener(listener);
+ }
}
}
@@ -232,5 +235,9 @@ public class NetworkStatsSubscriptionsMonitor extends
public int getSubId() {
return mSubId;
}
+
+ boolean equalsKey(int subId, @NonNull String subscriberId) {
+ return mSubId == subId && TextUtils.equals(mSubscriberId, subscriberId);
+ }
}
}
diff --git a/services/core/java/com/android/server/vcn/OWNERS b/services/core/java/com/android/server/vcn/OWNERS
new file mode 100644
index 000000000000..33b9f0f75f81
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+benedictwong@google.com
+ckesting@google.com
+evitayan@google.com
+nharold@google.com
+jchalard@google.com \ No newline at end of file
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c6b93d6ca4f4..0da47ca90f5e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -480,38 +480,38 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final int STATUS_BAR_DISABLE2_MASK =
StatusBarManager.DISABLE2_QUICK_SETTINGS;
- private static final Set<String> SECURE_SETTINGS_WHITELIST;
- private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST;
- private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
+ private static final Set<String> SECURE_SETTINGS_ALLOWLIST;
+ private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST;
+ private static final Set<String> GLOBAL_SETTINGS_ALLOWLIST;
private static final Set<String> GLOBAL_SETTINGS_DEPRECATED;
- private static final Set<String> SYSTEM_SETTINGS_WHITELIST;
+ private static final Set<String> SYSTEM_SETTINGS_ALLOWLIST;
private static final Set<Integer> DA_DISALLOWED_POLICIES;
// A collection of user restrictions that are deprecated and should simply be ignored.
private static final Set<String> DEPRECATED_USER_RESTRICTIONS;
private static final String AB_DEVICE_KEY = "ro.build.ab_update";
static {
- SECURE_SETTINGS_WHITELIST = new ArraySet<>();
- SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
- SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
- SECURE_SETTINGS_WHITELIST.add(Settings.Secure.INSTALL_NON_MARKET_APPS);
-
- SECURE_SETTINGS_DEVICEOWNER_WHITELIST = new ArraySet<>();
- SECURE_SETTINGS_DEVICEOWNER_WHITELIST.addAll(SECURE_SETTINGS_WHITELIST);
- SECURE_SETTINGS_DEVICEOWNER_WHITELIST.add(Settings.Secure.LOCATION_MODE);
-
- GLOBAL_SETTINGS_WHITELIST = new ArraySet<>();
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_WIFI_ENABLED);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME_ZONE);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DATA_ROAMING);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_SLEEP_POLICY);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.PRIVATE_DNS_MODE);
- GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.PRIVATE_DNS_SPECIFIER);
+ SECURE_SETTINGS_ALLOWLIST = new ArraySet<>();
+ SECURE_SETTINGS_ALLOWLIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
+ SECURE_SETTINGS_ALLOWLIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
+ SECURE_SETTINGS_ALLOWLIST.add(Settings.Secure.INSTALL_NON_MARKET_APPS);
+
+ SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST = new ArraySet<>();
+ SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.addAll(SECURE_SETTINGS_ALLOWLIST);
+ SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.add(Settings.Secure.LOCATION_MODE);
+
+ GLOBAL_SETTINGS_ALLOWLIST = new ArraySet<>();
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.ADB_ENABLED);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.ADB_WIFI_ENABLED);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.AUTO_TIME);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.AUTO_TIME_ZONE);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.DATA_ROAMING);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.WIFI_SLEEP_POLICY);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.PRIVATE_DNS_MODE);
+ GLOBAL_SETTINGS_ALLOWLIST.add(Settings.Global.PRIVATE_DNS_SPECIFIER);
GLOBAL_SETTINGS_DEPRECATED = new ArraySet<>();
GLOBAL_SETTINGS_DEPRECATED.add(Settings.Global.BLUETOOTH_ON);
@@ -520,11 +520,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
GLOBAL_SETTINGS_DEPRECATED.add(Settings.Global.NETWORK_PREFERENCE);
GLOBAL_SETTINGS_DEPRECATED.add(Settings.Global.WIFI_ON);
- SYSTEM_SETTINGS_WHITELIST = new ArraySet<>();
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS);
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
- SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_OFF_TIMEOUT);
+ SYSTEM_SETTINGS_ALLOWLIST = new ArraySet<>();
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_BRIGHTNESS);
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
+ SYSTEM_SETTINGS_ALLOWLIST.add(Settings.System.SCREEN_OFF_TIMEOUT);
DA_DISALLOWED_POLICIES = new ArraySet<>();
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
@@ -1231,13 +1231,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String startUserSessionMessage = null;
String endUserSessionMessage = null;
- // The whitelist of packages that can access cross profile calendar APIs.
- // This whitelist should be in default an empty list, which indicates that no package
- // is whitelisted.
+ // The allowlist of packages that can access cross profile calendar APIs.
+ // This allowlist should be in default an empty list, which indicates that no package
+ // is allowed.
List<String> mCrossProfileCalendarPackages = Collections.emptyList();
- // The whitelist of packages that the admin has enabled to be able to request consent from
- // the user to communicate cross-profile. By default, no packages are whitelisted, which is
+ // The allowlist of packages that the admin has enabled to be able to request consent from
+ // the user to communicate cross-profile. By default, no packages are allowed, which is
// represented as an empty list.
List<String> mCrossProfilePackages = Collections.emptyList();
@@ -2818,7 +2818,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
- public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+ public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
final int status = intent.getIntExtra(
PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
@@ -7067,7 +7067,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
*/
@Override
public boolean setAlwaysOnVpnPackage(ComponentName who, String vpnPackage, boolean lockdown,
- List<String> lockdownWhitelist)
+ List<String> lockdownAllowlist)
throws SecurityException {
enforceProfileOrDeviceOwner(who);
@@ -7079,10 +7079,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, vpnPackage);
}
- if (vpnPackage != null && lockdown && lockdownWhitelist != null) {
- for (String packageName : lockdownWhitelist) {
+ if (vpnPackage != null && lockdown && lockdownAllowlist != null) {
+ for (String packageName : lockdownAllowlist) {
if (!isPackageInstalledForUser(packageName, userId)) {
- Slog.w(LOG_TAG, "Non-existent package in VPN whitelist: " + packageName);
+ Slog.w(LOG_TAG, "Non-existent package in VPN allowlist: " + packageName);
throw new ServiceSpecificException(
DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, packageName);
}
@@ -7090,7 +7090,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
// If some package is uninstalled after the check above, it will be ignored by CM.
if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser(
- userId, vpnPackage, lockdown, lockdownWhitelist)) {
+ userId, vpnPackage, lockdown, lockdownAllowlist)) {
throw new UnsupportedOperationException();
}
DevicePolicyEventLogger
@@ -7098,7 +7098,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setAdmin(who)
.setStrings(vpnPackage)
.setBoolean(lockdown)
- .setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
+ .setInt(lockdownAllowlist != null ? lockdownAllowlist.size() : 0)
.write();
});
synchronized (getLockObject()) {
@@ -7151,7 +7151,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin)
+ public List<String> getAlwaysOnVpnLockdownAllowlist(ComponentName admin)
throws SecurityException {
enforceProfileOrDeviceOwner(admin);
@@ -11911,7 +11911,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
- if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)
+ if (!GLOBAL_SETTINGS_ALLOWLIST.contains(setting)
&& !UserManager.isDeviceInDemoMode(mContext)) {
throw new SecurityException(String.format(
"Permission denial: device owners cannot update %1$s", setting));
@@ -11939,7 +11939,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!SYSTEM_SETTINGS_WHITELIST.contains(setting)) {
+ if (!SYSTEM_SETTINGS_ALLOWLIST.contains(setting)) {
throw new SecurityException(String.format(
"Permission denial: device owners cannot update %1$s", setting));
}
@@ -12083,12 +12083,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (isDeviceOwner(who, callingUserId)) {
- if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)
+ if (!SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.contains(setting)
&& !isCurrentUserDemo()) {
throw new SecurityException(String.format(
"Permission denial: Device owners cannot update %1$s", setting));
}
- } else if (!SECURE_SETTINGS_WHITELIST.contains(setting) && !isCurrentUserDemo()) {
+ } else if (!SECURE_SETTINGS_ALLOWLIST.contains(setting) && !isCurrentUserDemo()) {
throw new SecurityException(String.format(
"Permission denial: Profile owners cannot update %1$s", setting));
}
@@ -13859,7 +13859,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) {
// As the caller is the system, it must specify the component name of the profile owner
- // as a sanity / safety check.
+ // as a safety check.
Objects.requireNonNull(who);
if (!mHasFeature) {
@@ -13895,7 +13895,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@GuardedBy("getLockObject()")
private void markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(
ComponentName who, int userId) {
- // Sanity check: Make sure that the user has a profile owner and that the specified
+ // Make sure that the user has a profile owner and that the specified
// component is the profile owner of that user.
if (!isProfileOwner(who, userId)) {
throw new IllegalArgumentException(String.format(
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a6d72450156f..9f16543c410e 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -966,6 +966,32 @@ public final class Call {
/**
* Gets the verification status for the phone number of an incoming call as identified in
* ATIS-1000082.
+ * <p>
+ * For incoming calls, the number verification status indicates whether the device was
+ * able to verify the authenticity of the calling number using the STIR process outlined
+ * in ATIS-1000082. {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
+ * the network was not able to use STIR to verify the caller's number (i.e. nothing is
+ * known regarding the authenticity of the number.
+ * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
+ * use STIR to verify the caller's number. This indicates that the network has a high
+ * degree of confidence that the incoming call actually originated from the indicated
+ * number. {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
+ * STIR verification did not pass. This indicates that the incoming call may not
+ * actually be from the indicated number. This could occur if, for example, the caller
+ * is using an impersonated phone number.
+ * <p>
+ * A {@link CallScreeningService} can use this information to help determine if an
+ * incoming call is potentially an unwanted call. A verification status of
+ * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
+ * actually be from the number indicated on the call (i.e. impersonated number) and that it
+ * should potentially be blocked. Likewise,
+ * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
+ * help clarify that the incoming call is originating from the indicated number and it
+ * is less likely to be an undesirable call.
+ * <p>
+ * An {@link InCallService} can use this information to provide a visual indicator to the
+ * user regarding the verification status of a call and to help identify calls from
+ * potentially impersonated numbers.
* @return the verification status.
*/
public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 26b669a70cf8..e7af0534b7c9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10326,19 +10326,25 @@ public class TelephonyManager {
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
* and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+ *
+ * May return {@code null} when the subscription is inactive or when there was an error
+ * communicating with the phone process.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION
})
- public ServiceState getServiceState() {
+ public @Nullable ServiceState getServiceState() {
return getServiceStateForSubscriber(getSubId());
}
/**
* Returns the service state information on specified subscription. Callers require
* either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
+ *
+ * May return {@code null} when the subscription is inactive or when there was an error
+ * communicating with the phone process.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -10365,9 +10371,9 @@ public class TelephonyManager {
* @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
* voicemail ringtone.
* @return The URI for the ringtone to play when receiving a voicemail from a specific
- * PhoneAccount.
+ * PhoneAccount. May be {@code null} if no ringtone is set.
*/
- public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
+ public @Nullable Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
try {
ITelephony service = getITelephony();
if (service != null) {
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index c895420157d7..85704d033634 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -213,7 +213,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
public void connect() {
assertNotEquals("MockNetworkAgents can only be connected once",
- getNetworkInfo().getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
+ mNetworkInfo.getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
@@ -268,10 +268,6 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
return mNetworkAgent;
}
- public NetworkInfo getNetworkInfo() {
- return mNetworkInfo;
- }
-
public NetworkCapabilities getNetworkCapabilities() {
return mNetworkCapabilities;
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 1df510987d25..daa2627d64cf 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -1155,7 +1155,7 @@ public class VpnTest {
new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret,
"name", profile.username, "password", profile.password,
"linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns",
- "idle", "1800", "mtu", "1400", "mru", "1400" },
+ "idle", "1800", "mtu", "1270", "mru", "1270" },
deps.mtpdArgs.get(10, TimeUnit.SECONDS));
// Now wait for the runner to be ready before testing for the route.
legacyRunnerReady.block(10_000);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
index 8f093779da11..6d2c7dc39ffd 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -150,7 +151,7 @@ public final class NetworkStatsSubscriptionsMonitorTest {
}
private void assertRatTypeChangedForSub(String subscriberId, int ratType) {
- assertEquals(mMonitor.getRatTypeForSubscriberId(subscriberId), ratType);
+ assertEquals(ratType, mMonitor.getRatTypeForSubscriberId(subscriberId));
final ArgumentCaptor<Integer> typeCaptor = ArgumentCaptor.forClass(Integer.class);
// Verify callback with the subscriberId and the RAT type should be as expected.
// It will fail if get a callback with an unexpected RAT type.
@@ -302,26 +303,84 @@ public final class NetworkStatsSubscriptionsMonitorTest {
reset(mDelegate);
// Set IMSI to null again to simulate somehow IMSI is not available, such as
- // modem crash. Verify service should not unregister listener.
+ // modem crash. Verify service should unregister listener.
updateSubscriberIdForTestSub(TEST_SUBID1, null);
- verify(mTelephonyManager, never()).listen(any(), anyInt());
- assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
+ verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
+ eq(PhoneStateListener.LISTEN_NONE));
+ assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
reset(mDelegate);
+ clearInvocations(mTelephonyManager);
- // Set RAT type of sim1 to LTE. Verify RAT type of sim1 is still changed even if the IMSI
- // is not available. The monitor keeps the listener even if the IMSI disappears because
- // the IMSI can never change for any given subId, therefore even if the IMSI is updated
- // to null, the monitor should continue accepting updates of the RAT type. However,
- // telephony is never actually supposed to do this, if the IMSI disappears there should
- // not be updates, but it's still the right thing to do theoretically.
- setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
+ // Simulate somehow IMSI is back. Verify service will register with
+ // another listener and fire callback accordingly.
+ final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor2 =
+ ArgumentCaptor.forClass(RatTypeListener.class);
+ updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
+ verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(),
+ eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+ assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ reset(mDelegate);
+ clearInvocations(mTelephonyManager);
+
+ // Set RAT type of sim1 to LTE. Verify RAT type of sim1 still works.
+ setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1,
TelephonyManager.NETWORK_TYPE_LTE);
assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
reset(mDelegate);
mMonitor.stop();
+ verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor2.getValue()),
+ eq(PhoneStateListener.LISTEN_NONE));
+ assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ }
+
+ /**
+ * Verify that when IMSI suddenly changed for a given subId, the service will register a new
+ * listener and unregister the old one, and report changes on updated IMSI. This is for modem
+ * feature that may be enabled for certain carrier, which changes to use a different IMSI while
+ * roaming on certain networks for multi-IMSI SIM cards, but the subId stays the same.
+ */
+ @Test
+ public void testSubscriberIdChanged() {
+ mMonitor.start();
+ // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
+ // before changing RAT type.
+ addTestSub(TEST_SUBID1, TEST_IMSI1);
+ final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
+ ArgumentCaptor.forClass(RatTypeListener.class);
+ verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
+ eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+ assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+
+ // Set RAT type of sim1 to UMTS.
+ // Verify RAT type of sim1 changes accordingly.
+ setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
+ TelephonyManager.NETWORK_TYPE_UMTS);
+ assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
+ reset(mDelegate);
+ clearInvocations(mTelephonyManager);
+
+ // Simulate IMSI of sim1 changed to IMSI2. Verify the service will register with
+ // another listener and remove the old one. The RAT type of new IMSI stays at
+ // NETWORK_TYPE_UNKNOWN until received initial callback from telephony.
+ final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor2 =
+ ArgumentCaptor.forClass(RatTypeListener.class);
+ updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI2);
+ verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(),
+ eq(PhoneStateListener.LISTEN_SERVICE_STATE));
verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
eq(PhoneStateListener.LISTEN_NONE));
assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ reset(mDelegate);
+
+ // Set RAT type of sim1 to UMTS for new listener to simulate the initial callback received
+ // from telephony after registration. Verify RAT type of sim1 changes with IMSI2
+ // accordingly.
+ setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1,
+ TelephonyManager.NETWORK_TYPE_UMTS);
+ assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UMTS);
+ reset(mDelegate);
}
}
diff --git a/tests/vcn/OWNERS b/tests/vcn/OWNERS
new file mode 100644
index 000000000000..33b9f0f75f81
--- /dev/null
+++ b/tests/vcn/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+benedictwong@google.com
+ckesting@google.com
+evitayan@google.com
+nharold@google.com
+jchalard@google.com \ No newline at end of file