summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--StubLibraries.bp33
-rw-r--r--api/Android.bp66
-rw-r--r--api/current.txt3
-rwxr-xr-xapi/gen_combined_removed_dex.sh11
-rwxr-xr-xapi/system-current.txt1
-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/android/bluetooth/BluetoothAdapter.java4
-rw-r--r--core/java/android/bluetooth/le/AdvertiseData.java54
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java27
-rw-r--r--core/java/android/net/KeepalivePacketData.java3
-rw-r--r--core/java/android/net/NattKeepalivePacketData.java3
-rw-r--r--core/java/android/net/NetworkSpecifier.java8
-rw-r--r--core/java/android/net/util/IpUtils.java151
-rw-r--r--core/java/android/uwb/UwbManager.java269
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresCmdID.aidl (renamed from core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl)0
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java22
-rw-r--r--core/jni/android_os_HwParcel.cpp2
-rw-r--r--core/jni/android_os_Parcel.cpp93
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/xsd/vts/Android.bp4
-rw-r--r--core/xsd/vts/AndroidTest.xml30
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp1
-rw-r--r--non-updatable-api/Android.bp18
-rw-r--r--non-updatable-api/current.txt3
-rw-r--r--non-updatable-api/system-current.txt1
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java8
-rw-r--r--packages/Tethering/Android.bp1
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java8
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java94
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/Tethering.java12
-rw-r--r--packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java2
-rw-r--r--packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java18
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java276
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java1
-rw-r--r--services/core/java/com/android/server/MountServiceIdler.java1
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/core/java/com/android/server/connectivity/KeepaliveTracker.java2
-rw-r--r--services/core/java/com/android/server/connectivity/PacManager.java2
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java21
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java12
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java27
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/core/java/com/android/server/pm/Settings.java4
-rw-r--r--services/core/java/com/android/server/pm/permission/OWNERS2
-rw-r--r--services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java9
-rw-r--r--services/core/xsd/vts/Android.mk22
-rw-r--r--services/core/xsd/vts/AndroidTest.xml30
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java98
-rw-r--r--services/net/java/android/net/TcpKeepalivePacketData.java3
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java90
-rwxr-xr-xtelecomm/java/android/telecom/Call.java8
-rw-r--r--telecomm/java/android/telecom/CallScreeningService.java52
-rw-r--r--telephony/java/android/telephony/BinderCacheManager.java197
-rw-r--r--telephony/java/android/telephony/SmsManager.java26
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java77
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java3
-rw-r--r--telephony/java/android/telephony/ims/ImsService.java58
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl7
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl6
-rw-r--r--telephony/java/com/android/ims/ImsFeatureContainer.aidl19
-rw-r--r--telephony/java/com/android/ims/ImsFeatureContainer.java172
-rw-r--r--telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl15
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl16
-rw-r--r--tests/RollbackTest/Android.bp9
-rw-r--r--tests/StagedInstallTest/Android.bp1
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java21
-rw-r--r--tests/net/integration/util/com/android/server/NetworkAgentWrapper.java6
-rw-r--r--tests/net/java/android/net/util/IpUtilsTest.java166
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java2
-rw-r--r--tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java (renamed from tests/RollbackTest/lib/src/com/android/tests/rollback/host/AbandonSessionsRule.java)0
-rw-r--r--wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl2
-rw-r--r--wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl2
-rw-r--r--wifi/jarjar-rules.txt1
79 files changed, 1618 insertions, 865 deletions
diff --git a/Android.bp b/Android.bp
index 92f79d1fbef4..8e17f5524a38 100644
--- a/Android.bp
+++ b/Android.bp
@@ -769,7 +769,6 @@ filegroup {
name: "framework-services-net-module-wifi-shared-srcs",
srcs: [
"core/java/android/net/DhcpResults.java",
- "core/java/android/net/util/IpUtils.java",
"core/java/android/util/LocalLog.java",
],
}
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 9e087f020246..4e1de0ecf9d4 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -55,7 +55,24 @@ stubs_defaults {
aidl: {
local_include_dirs: ["telephony/java"],
},
- libs: ["framework-internal-utils"],
+ // These are libs from framework-internal-utils that are required (i.e. being referenced)
+ // from framework-non-updatable-sources. Add more here when there's a need.
+ // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular
+ // dependencies gets bigger.
+ libs: [
+ "android.hardware.cas-V1.2-java",
+ "android.hardware.health-V1.0-java-constants",
+ "android.hardware.radio-V1.5-java",
+ "android.hardware.thermal-V1.0-java-constants",
+ "android.hardware.thermal-V2.0-java",
+ "android.hardware.tv.input-V1.0-java-constants",
+ "android.hardware.tv.tuner-V1.0-java-constants",
+ "android.hardware.usb-V1.0-java-constants",
+ "android.hardware.usb-V1.1-java-constants",
+ "android.hardware.usb.gadget-V1.0-java",
+ "android.hardware.vibrator-V1.3-java",
+ "framework-protos",
+ ],
installable: false,
annotations_enabled: true,
previous_api: ":android.api.public.latest",
@@ -140,6 +157,11 @@ droidstubs {
api_file: "non-updatable-api/current.txt",
removed_api_file: "non-updatable-api/removed.txt",
},
+ last_released: {
+ api_file: ":android-non-updatable.api.public.latest",
+ removed_api_file: ":android-non-updatable-removed.api.public.latest",
+ baseline_file: ":public-api-incompatibilities-with-last-released",
+ },
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.public.latest",
@@ -202,6 +224,11 @@ droidstubs {
api_file: "non-updatable-api/system-current.txt",
removed_api_file: "non-updatable-api/system-removed.txt",
},
+ last_released: {
+ api_file: ":android-non-updatable.api.system.latest",
+ removed_api_file: ":android-non-updatable-removed.api.system.latest",
+ baseline_file: ":system-api-incompatibilities-with-last-released"
+ },
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.system.latest",
@@ -281,6 +308,10 @@ droidstubs {
api_file: "non-updatable-api/module-lib-current.txt",
removed_api_file: "non-updatable-api/module-lib-removed.txt",
},
+ last_released: {
+ api_file: ":android-non-updatable.api.module-lib.latest",
+ removed_api_file: ":android-non-updatable-removed.api.module-lib.latest",
+ },
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.module-lib.latest",
diff --git a/api/Android.bp b/api/Android.bp
index cb6d448caf63..ffc4a2146594 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -63,6 +63,24 @@ genrule {
}
genrule {
+ name: "frameworks-base-api-removed-merged.txt",
+ srcs: [
+ ":conscrypt.module.public.api{.public.removed-api.txt}",
+ ":framework-media{.public.removed-api.txt}",
+ ":framework-mediaprovider{.public.removed-api.txt}",
+ ":framework-permission{.public.removed-api.txt}",
+ ":framework-sdkextensions{.public.removed-api.txt}",
+ ":framework-statsd{.public.removed-api.txt}",
+ ":framework-tethering{.public.removed-api.txt}",
+ ":framework-wifi{.public.removed-api.txt}",
+ ":non-updatable-removed.txt",
+ ],
+ out: ["removed.txt"],
+ tools: ["metalava"],
+ cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+}
+
+genrule {
name: "frameworks-base-api-system-current-merged.txt",
srcs: [
":framework-media{.system.api.txt}",
@@ -80,6 +98,23 @@ genrule {
}
genrule {
+ name: "frameworks-base-api-system-removed-merged.txt",
+ srcs: [
+ ":framework-media{.system.removed-api.txt}",
+ ":framework-mediaprovider{.system.removed-api.txt}",
+ ":framework-permission{.system.removed-api.txt}",
+ ":framework-sdkextensions{.system.removed-api.txt}",
+ ":framework-statsd{.system.removed-api.txt}",
+ ":framework-tethering{.system.removed-api.txt}",
+ ":framework-wifi{.system.removed-api.txt}",
+ ":non-updatable-system-removed.txt",
+ ],
+ out: ["system-removed.txt"],
+ tools: ["metalava"],
+ cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+}
+
+genrule {
name: "frameworks-base-api-module-lib-current-merged.txt",
srcs: [
":framework-media{.module-lib.api.txt}",
@@ -95,3 +130,34 @@ genrule {
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
}
+
+genrule {
+ name: "frameworks-base-api-module-lib-removed-merged.txt",
+ srcs: [
+ ":framework-media{.module-lib.removed-api.txt}",
+ ":framework-mediaprovider{.module-lib.removed-api.txt}",
+ ":framework-permission{.module-lib.removed-api.txt}",
+ ":framework-sdkextensions{.module-lib.removed-api.txt}",
+ ":framework-statsd{.module-lib.removed-api.txt}",
+ ":framework-tethering{.module-lib.removed-api.txt}",
+ ":framework-wifi{.module-lib.removed-api.txt}",
+ ":non-updatable-module-lib-removed.txt",
+ ],
+ out: ["module-lib-removed.txt"],
+ tools: ["metalava"],
+ cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+}
+
+genrule {
+ name: "combined-removed-dex",
+ srcs: [
+ ":frameworks-base-api-removed-merged.txt",
+ ":frameworks-base-api-system-removed-merged.txt",
+ ":android.car-stubs-docs{.removed-api.txt}",
+ ":android.car-system-stubs-docs{.removed-api.txt}",
+ ],
+ tool_files: ["gen_combined_removed_dex.sh"],
+ tools: ["metalava"],
+ out: ["combined-removed-dex.txt"],
+ cmd: "$(location gen_combined_removed_dex.sh) $(location metalava) $(genDir) $(in) > $(out)",
+}
diff --git a/api/current.txt b/api/current.txt
index e16876e45c87..27a035e3474a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9126,6 +9126,7 @@ package android.bluetooth.le {
method public boolean getIncludeTxPowerLevel();
method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
+ method @Nullable public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
method public java.util.List<android.os.ParcelUuid> getServiceUuids();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR;
@@ -9135,6 +9136,7 @@ package android.bluetooth.le {
ctor public AdvertiseData.Builder();
method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]);
method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
+ method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid);
method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
method public android.bluetooth.le.AdvertiseData build();
method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
@@ -47910,6 +47912,7 @@ package android.telephony {
method @NonNull public android.os.Bundle getCarrierConfigValues();
method public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSmsCapacityOnIcc();
method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
diff --git a/api/gen_combined_removed_dex.sh b/api/gen_combined_removed_dex.sh
new file mode 100755
index 000000000000..9225fe8dfe85
--- /dev/null
+++ b/api/gen_combined_removed_dex.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+metalava_path="$1"
+tmp_dir="$2"
+shift 2
+
+# Convert each removed.txt to the "dex format" equivalent, and print all output.
+for f in "$@"; do
+ "$metalava_path" --no-banner "$f" --dex-api "${tmp_dir}/tmp"
+ cat "${tmp_dir}/tmp"
+done
diff --git a/api/system-current.txt b/api/system-current.txt
index ddf9c4d97e6f..e163e7d79255 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11075,7 +11075,6 @@ package android.telephony {
method public boolean disableCellBroadcastRange(int, int, int);
method public boolean enableCellBroadcastRange(int, int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
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/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 3c7d8fca20a4..872c37771128 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2529,7 +2529,7 @@ public final class BluetoothAdapter {
* Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
* <p>The link key is not required to be authenticated, i.e the communication may be
* vulnerable to Person In the Middle attacks. For Bluetooth 2.1 devices,
- * the link will be encrypted, as encryption is mandartory.
+ * the link will be encrypted, as encryption is mandatory.
* For legacy devices (pre Bluetooth 2.1 devices) the link will not
* be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
* encrypted and authenticated communication channel is desired.
@@ -2568,7 +2568,7 @@ public final class BluetoothAdapter {
* an input and output capability or just has the ability to display a numeric key,
* a secure socket connection is not possible and this socket can be used.
* Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
- * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
+ * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandatory.
* For more details, refer to the Security Model section 5.2 (vol 3) of
* Bluetooth Core Specification version 2.1 + EDR.
* <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
index 5fd825837647..573b93232642 100644
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.ParcelUuid;
@@ -43,17 +44,22 @@ public final class AdvertiseData implements Parcelable {
@Nullable
private final List<ParcelUuid> mServiceUuids;
+ @Nullable
+ private final List<ParcelUuid> mServiceSolicitationUuids;
+
private final SparseArray<byte[]> mManufacturerSpecificData;
private final Map<ParcelUuid, byte[]> mServiceData;
private final boolean mIncludeTxPowerLevel;
private final boolean mIncludeDeviceName;
private AdvertiseData(List<ParcelUuid> serviceUuids,
+ List<ParcelUuid> serviceSolicitationUuids,
SparseArray<byte[]> manufacturerData,
Map<ParcelUuid, byte[]> serviceData,
boolean includeTxPowerLevel,
boolean includeDeviceName) {
mServiceUuids = serviceUuids;
+ mServiceSolicitationUuids = serviceSolicitationUuids;
mManufacturerSpecificData = manufacturerData;
mServiceData = serviceData;
mIncludeTxPowerLevel = includeTxPowerLevel;
@@ -69,6 +75,14 @@ public final class AdvertiseData implements Parcelable {
}
/**
+ * Returns a list of service solicitation UUIDs within the advertisement that we invite to connect.
+ */
+ @Nullable
+ public List<ParcelUuid> getServiceSolicitationUuids() {
+ return mServiceSolicitationUuids;
+ }
+
+ /**
* Returns an array of manufacturer Id and the corresponding manufacturer specific data. The
* manufacturer id is a non-negative number assigned by Bluetooth SIG.
*/
@@ -102,8 +116,8 @@ public final class AdvertiseData implements Parcelable {
*/
@Override
public int hashCode() {
- return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData,
- mIncludeDeviceName, mIncludeTxPowerLevel);
+ return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData,
+ mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
}
/**
@@ -119,6 +133,7 @@ public final class AdvertiseData implements Parcelable {
}
AdvertiseData other = (AdvertiseData) obj;
return Objects.equals(mServiceUuids, other.mServiceUuids)
+ && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids)
&& BluetoothLeUtils.equals(mManufacturerSpecificData,
other.mManufacturerSpecificData)
&& BluetoothLeUtils.equals(mServiceData, other.mServiceData)
@@ -128,7 +143,8 @@ public final class AdvertiseData implements Parcelable {
@Override
public String toString() {
- return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData="
+ return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids="
+ + mServiceSolicitationUuids + ", mManufacturerSpecificData="
+ BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData="
+ BluetoothLeUtils.toString(mServiceData)
+ ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
@@ -143,6 +159,8 @@ public final class AdvertiseData implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArray(mServiceUuids.toArray(new ParcelUuid[mServiceUuids.size()]), flags);
+ dest.writeTypedArray(mServiceSolicitationUuids.toArray(
+ new ParcelUuid[mServiceSolicitationUuids.size()]), flags);
// mManufacturerSpecificData could not be null.
dest.writeInt(mManufacturerSpecificData.size());
@@ -174,6 +192,11 @@ public final class AdvertiseData implements Parcelable {
builder.addServiceUuid(uuid);
}
+ ArrayList<ParcelUuid> solicitationUuids = in.createTypedArrayList(ParcelUuid.CREATOR);
+ for (ParcelUuid uuid : solicitationUuids) {
+ builder.addServiceSolicitationUuid(uuid);
+ }
+
int manufacturerSize = in.readInt();
for (int i = 0; i < manufacturerSize; ++i) {
int manufacturerId = in.readInt();
@@ -198,6 +221,8 @@ public final class AdvertiseData implements Parcelable {
public static final class Builder {
@Nullable
private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
+ @Nullable
+ private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>();
private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>();
private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>();
private boolean mIncludeTxPowerLevel;
@@ -207,17 +232,31 @@ public final class AdvertiseData implements Parcelable {
* Add a service UUID to advertise data.
*
* @param serviceUuid A service UUID to be advertised.
- * @throws IllegalArgumentException If the {@code serviceUuids} are null.
+ * @throws IllegalArgumentException If the {@code serviceUuid} is null.
*/
public Builder addServiceUuid(ParcelUuid serviceUuid) {
if (serviceUuid == null) {
- throw new IllegalArgumentException("serivceUuids are null");
+ throw new IllegalArgumentException("serviceUuid is null");
}
mServiceUuids.add(serviceUuid);
return this;
}
/**
+ * Add a service solicitation UUID to advertise data.
+ *
+ * @param serviceSolicitationUuid A service solicitation UUID to be advertised.
+ * @throws IllegalArgumentException If the {@code serviceSolicitationUuid} is null.
+ */
+ @NonNull
+ public Builder addServiceSolicitationUuid(@NonNull ParcelUuid serviceSolicitationUuid) {
+ if (serviceSolicitationUuid == null) {
+ throw new IllegalArgumentException("serviceSolicitationUuid is null");
+ }
+ mServiceSolicitationUuids.add(serviceSolicitationUuid);
+ return this;
+ }
+ /**
* Add service data to advertise data.
*
* @param serviceDataUuid 16-bit UUID of the service the data is associated with
@@ -279,8 +318,9 @@ public final class AdvertiseData implements Parcelable {
* Build the {@link AdvertiseData}.
*/
public AdvertiseData build() {
- return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData,
- mIncludeTxPowerLevel, mIncludeDeviceName);
+ return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids,
+ mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel,
+ mIncludeDeviceName);
}
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 13c5ff690973..5f166f4a41da 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -507,6 +507,33 @@ public final class BluetoothLeAdvertiser {
+ num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
}
}
+ if (data.getServiceSolicitationUuids() != null) {
+ int num16BitUuids = 0;
+ int num32BitUuids = 0;
+ int num128BitUuids = 0;
+ for (ParcelUuid uuid : data.getServiceSolicitationUuids()) {
+ if (BluetoothUuid.is16BitUuid(uuid)) {
+ ++num16BitUuids;
+ } else if (BluetoothUuid.is32BitUuid(uuid)) {
+ ++num32BitUuids;
+ } else {
+ ++num128BitUuids;
+ }
+ }
+ // 16 bit service uuids are grouped into one field when doing advertising.
+ if (num16BitUuids != 0) {
+ size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
+ }
+ // 32 bit service uuids are grouped into one field when doing advertising.
+ if (num32BitUuids != 0) {
+ size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
+ }
+ // 128 bit service uuids are grouped into one field when doing advertising.
+ if (num128BitUuids != 0) {
+ size += OVERHEAD_BYTES_PER_FIELD
+ + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
+ }
+ }
for (ParcelUuid uuid : data.getServiceData().keySet()) {
int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
size += OVERHEAD_BYTES_PER_FIELD + uuidLen
diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java
index e21cb44f72d8..5877f1f4e269 100644
--- a/core/java/android/net/KeepalivePacketData.java
+++ b/core/java/android/net/KeepalivePacketData.java
@@ -22,9 +22,10 @@ import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.net.util.IpUtils;
import android.util.Log;
+import com.android.net.module.util.IpUtils;
+
import java.net.InetAddress;
/**
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java
index 22288b6205d7..c4f8fc281f25 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/core/java/android/net/NattKeepalivePacketData.java
@@ -22,11 +22,12 @@ import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.system.OsConstants;
+import com.android.net.module.util.IpUtils;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 160259e39813..6ef496b1f6fe 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -22,10 +22,14 @@ import android.annotation.SystemApi;
/**
* Describes specific properties of a requested network for use in a {@link NetworkRequest}.
*
- * Applications cannot instantiate this class by themselves, but can obtain instances of
- * subclasses of this class via other APIs.
+ * This as an abstract class. Applications shouldn't instantiate this class by themselves, but can
+ * obtain instances of subclasses of this class via other APIs.
*/
public abstract class NetworkSpecifier {
+ /**
+ * Create a placeholder object. Please use subclasses of this class in a {@link NetworkRequest}
+ * to request a network.
+ */
public NetworkSpecifier() {}
/**
diff --git a/core/java/android/net/util/IpUtils.java b/core/java/android/net/util/IpUtils.java
deleted file mode 100644
index e037c4035aca..000000000000
--- a/core/java/android/net/util/IpUtils.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ShortBuffer;
-
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-
-/**
- * @hide
- */
-public class IpUtils {
- /**
- * Converts a signed short value to an unsigned int value. Needed
- * because Java does not have unsigned types.
- */
- private static int intAbs(short v) {
- return v & 0xFFFF;
- }
-
- /**
- * Performs an IP checksum (used in IP header and across UDP
- * payload) on the specified portion of a ByteBuffer. The seed
- * allows the checksum to commence with a specified value.
- */
- private static int checksum(ByteBuffer buf, int seed, int start, int end) {
- int sum = seed;
- final int bufPosition = buf.position();
-
- // set position of original ByteBuffer, so that the ShortBuffer
- // will be correctly initialized
- buf.position(start);
- ShortBuffer shortBuf = buf.asShortBuffer();
-
- // re-set ByteBuffer position
- buf.position(bufPosition);
-
- final int numShorts = (end - start) / 2;
- for (int i = 0; i < numShorts; i++) {
- sum += intAbs(shortBuf.get(i));
- }
- start += numShorts * 2;
-
- // see if a singleton byte remains
- if (end != start) {
- short b = buf.get(start);
-
- // make it unsigned
- if (b < 0) {
- b += 256;
- }
-
- sum += b * 256;
- }
-
- sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF);
- sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF);
- int negated = ~sum;
- return intAbs((short) negated);
- }
-
- private static int pseudoChecksumIPv4(
- ByteBuffer buf, int headerOffset, int protocol, int transportLen) {
- int partial = protocol + transportLen;
- partial += intAbs(buf.getShort(headerOffset + 12));
- partial += intAbs(buf.getShort(headerOffset + 14));
- partial += intAbs(buf.getShort(headerOffset + 16));
- partial += intAbs(buf.getShort(headerOffset + 18));
- return partial;
- }
-
- private static int pseudoChecksumIPv6(
- ByteBuffer buf, int headerOffset, int protocol, int transportLen) {
- int partial = protocol + transportLen;
- for (int offset = 8; offset < 40; offset += 2) {
- partial += intAbs(buf.getShort(headerOffset + offset));
- }
- return partial;
- }
-
- private static byte ipversion(ByteBuffer buf, int headerOffset) {
- return (byte) ((buf.get(headerOffset) & (byte) 0xf0) >> 4);
- }
-
- public static short ipChecksum(ByteBuffer buf, int headerOffset) {
- byte ihl = (byte) (buf.get(headerOffset) & 0x0f);
- return (short) checksum(buf, 0, headerOffset, headerOffset + ihl * 4);
- }
-
- private static short transportChecksum(ByteBuffer buf, int protocol,
- int ipOffset, int transportOffset, int transportLen) {
- if (transportLen < 0) {
- throw new IllegalArgumentException("Transport length < 0: " + transportLen);
- }
- int sum;
- byte ver = ipversion(buf, ipOffset);
- if (ver == 4) {
- sum = pseudoChecksumIPv4(buf, ipOffset, protocol, transportLen);
- } else if (ver == 6) {
- sum = pseudoChecksumIPv6(buf, ipOffset, protocol, transportLen);
- } else {
- throw new UnsupportedOperationException("Checksum must be IPv4 or IPv6");
- }
-
- sum = checksum(buf, sum, transportOffset, transportOffset + transportLen);
- if (protocol == IPPROTO_UDP && sum == 0) {
- sum = (short) 0xffff;
- }
- return (short) sum;
- }
-
- public static short udpChecksum(ByteBuffer buf, int ipOffset, int transportOffset) {
- int transportLen = intAbs(buf.getShort(transportOffset + 4));
- return transportChecksum(buf, IPPROTO_UDP, ipOffset, transportOffset, transportLen);
- }
-
- public static short tcpChecksum(ByteBuffer buf, int ipOffset, int transportOffset,
- int transportLen) {
- return transportChecksum(buf, IPPROTO_TCP, ipOffset, transportOffset, transportLen);
- }
-
- public static String addressAndPortToString(InetAddress address, int port) {
- return String.format(
- (address instanceof Inet6Address) ? "[%s]:%d" : "%s:%d",
- address.getHostAddress(), port);
- }
-
- public static boolean isValidUdpOrTcpPort(int port) {
- return port > 0 && port < 65536;
- }
-}
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
new file mode 100644
index 000000000000..8097dc6dca11
--- /dev/null
+++ b/core/java/android/uwb/UwbManager.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uwb;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides a way to perform Ultra Wideband (UWB) operations such as querying the
+ * device's capabilities and determining the distance and angle between the local device and a
+ * remote device.
+ *
+ * <p>To get a {@link UwbManager}, call the <code>Context.getSystemService(UwbManager.class)</code>.
+ *
+ * @hide
+ */
+public final class UwbManager {
+ /**
+ * Interface for receiving UWB adapter state changes
+ */
+ public interface AdapterStateCallback {
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ STATE_CHANGED_REASON_SESSION_STARTED,
+ STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED,
+ STATE_CHANGED_REASON_SYSTEM_POLICY,
+ STATE_CHANGED_REASON_SYSTEM_BOOT,
+ STATE_CHANGED_REASON_ERROR_UNKNOWN})
+ @interface StateChangedReason {}
+
+ /**
+ * Indicates that the state change was due to opening of first UWB session
+ */
+ int STATE_CHANGED_REASON_SESSION_STARTED = 0;
+
+ /**
+ * Indicates that the state change was due to closure of all UWB sessions
+ */
+ int STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED = 1;
+
+ /**
+ * Indicates that the state change was due to changes in system policy
+ */
+ int STATE_CHANGED_REASON_SYSTEM_POLICY = 2;
+
+ /**
+ * Indicates that the current state is due to a system boot
+ */
+ int STATE_CHANGED_REASON_SYSTEM_BOOT = 3;
+
+ /**
+ * Indicates that the state change was due to some unknown error
+ */
+ int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4;
+
+ /**
+ * Invoked when underlying UWB adapter's state is changed
+ * <p>Invoked with the adapter's current state after registering an
+ * {@link AdapterStateCallback} using
+ * {@link UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback)}.
+ *
+ * <p>Possible values for the state to change are
+ * {@link #STATE_CHANGED_REASON_SESSION_STARTED},
+ * {@link #STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED},
+ * {@link #STATE_CHANGED_REASON_SYSTEM_POLICY},
+ * {@link #STATE_CHANGED_REASON_SYSTEM_BOOT},
+ * {@link #STATE_CHANGED_REASON_ERROR_UNKNOWN}.
+ *
+ * @param isEnabled true when UWB adapter is enabled, false when it is disabled
+ * @param reason the reason for the state change
+ */
+ void onStateChanged(boolean isEnabled, @StateChangedReason int reason);
+ }
+
+ /**
+ * Use <code>Context.getSystemService(UwbManager.class)</code> to get an instance.
+ */
+ private UwbManager() {
+ throw new UnsupportedOperationException();
+ }
+ /**
+ * Register an {@link AdapterStateCallback} to listen for UWB adapter state changes
+ * <p>The provided callback will be invoked by the given {@link Executor}.
+ *
+ * <p>When first registering a callback, the callbacks's
+ * {@link AdapterStateCallback#onStateChanged(boolean, int)} is immediately invoked to indicate
+ * the current state of the underlying UWB adapter with the most recent
+ * {@link AdapterStateCallback.StateChangedReason} that caused the change.
+ *
+ * @param executor an {@link Executor} to execute given callback
+ * @param callback user implementation of the {@link AdapterStateCallback}
+ */
+ public void registerAdapterStateCallback(Executor executor, AdapterStateCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unregister the specified {@link AdapterStateCallback}
+ * <p>The same {@link AdapterStateCallback} object used when calling
+ * {@link #registerAdapterStateCallback(Executor, AdapterStateCallback)} must be used.
+ *
+ * <p>Callbacks are automatically unregistered when application process goes away
+ *
+ * @param callback user implementation of the {@link AdapterStateCallback}
+ */
+ public void unregisterAdapterStateCallback(AdapterStateCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get a {@link PersistableBundle} with the supported UWB protocols and parameters.
+ * <p>The {@link PersistableBundle} should be parsed using a support library
+ *
+ * <p>Android reserves the '^android.*' namespace</p>
+ *
+ * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters
+ */
+ @NonNull
+ public PersistableBundle getSpecificationInfo() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Check if ranging is supported, regardless of ranging method
+ *
+ * @return true if ranging is supported
+ */
+ public boolean isRangingSupported() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE,
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D,
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL,
+ ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL})
+ public @interface AngleOfArrivalSupportType {}
+
+ /**
+ * Indicate absence of support for angle of arrival measurement
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE = 1;
+
+ /**
+ * Indicate support for planar angle of arrival measurement, due to antenna
+ * limitation. Typically requires at least two antennas.
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2;
+
+ /**
+ * Indicate support for three dimensional angle of arrival measurement.
+ * Typically requires at least three antennas. However, due to antenna
+ * arrangement, a platform may only support hemi-spherical azimuth angles
+ * ranging from -pi/2 to pi/2
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 2;
+
+ /**
+ * Indicate support for three dimensional angle of arrival measurement.
+ * Typically requires at least three antennas. This mode supports full
+ * azimuth angles ranging from -pi to pi.
+ */
+ public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 3;
+
+
+ /**
+ * Gets the {@link AngleOfArrivalSupportType} supported on this platform
+ * <p>Possible return values are
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE},
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D},
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL},
+ * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL}.
+ *
+ * @return angle of arrival type supported
+ */
+ @AngleOfArrivalSupportType
+ public int getAngleOfArrivalSupport() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get a {@link List} of supported channel numbers based on the device's current location
+ * <p>The returned values are ordered by the system's desired ordered of use, with the first
+ * entry being the most preferred.
+ *
+ * <p>Channel numbers are defined based on the IEEE 802.15.4z standard for UWB.
+ *
+ * @return {@link List} of supported channel numbers ordered by preference
+ */
+ @NonNull
+ public List<Integer> getSupportedChannelNumbers() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get a {@link List} of supported preamble code indices
+ * <p> Preamble code indices are defined based on the IEEE 802.15.4z standard for UWB.
+ *
+ * @return {@link List} of supported preamble code indices
+ */
+ @NonNull
+ public Set<Integer> getSupportedPreambleCodeIndices() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the timestamp resolution for events in nanoseconds
+ * <p>This value defines the maximum error of all timestamps for events reported to
+ * {@link RangingSession.Callback}.
+ *
+ * @return the timestamp resolution in nanoseconds
+ */
+ @SuppressLint("MethodNameUnits")
+ public long elapsedRealtimeResolutionNanos() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the number of simultaneous sessions allowed in the system
+ *
+ * @return the maximum allowed number of simultaneously open {@link RangingSession} instances.
+ */
+ public int getMaxSimultaneousSessions() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the maximum number of remote devices in a {@link RangingSession} when the local device
+ * is the initiator.
+ *
+ * @return the maximum number of remote devices per {@link RangingSession}
+ */
+ public int getMaxRemoteDevicesPerInitiatorSession() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the maximum number of remote devices in a {@link RangingSession} when the local device
+ * is a responder.
+ *
+ * @return the maximum number of remote devices per {@link RangingSession}
+ */
+ public int getMaxRemoteDevicesPerResponderSession() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl b/core/java/com/android/ims/internal/uce/presence/PresCmdID.aidl
index 6ece045ffcf7..6ece045ffcf7 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
+++ b/core/java/com/android/ims/internal/uce/presence/PresCmdID.aidl
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/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index ff336ee64b54..4c4443fc29c3 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -990,6 +990,8 @@ static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
}
if (!validateCanUseHwBinder(binder)) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Local binder is not supported in Java");
return nullptr;
}
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 9ae3d160be98..9c7ee0c641a6 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -638,50 +638,77 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
return ret;
}
+// String tries to allocate itself on the stack, within a known size, but will
+// make a heap allocation if not.
+template <size_t StackReserve>
+class StackString {
+public:
+ StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
+ LOG_ALWAYS_FATAL_IF(str == nullptr);
+ mSize = env->GetStringLength(str);
+ if (mSize > StackReserve) {
+ mStr = new jchar[mSize];
+ } else {
+ mStr = &mBuffer[0];
+ }
+ mEnv->GetStringRegion(str, 0, mSize, mStr);
+ }
+ ~StackString() {
+ if (mStr != &mBuffer[0]) {
+ delete[] mStr;
+ }
+ }
+ const jchar* str() { return mStr; }
+ jsize size() { return mSize; }
+
+private:
+ JNIEnv* mEnv;
+ jstring mJStr;
+
+ jchar mBuffer[StackReserve];
+ // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
+ jchar* mStr;
+ jsize mSize;
+};
+
+// This size is chosen to be longer than most interface descriptors.
+// Ones longer than this will be allocated on the heap.
+typedef StackString<64> InterfaceDescriptorString;
+
static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- // In the current implementation, the token is just the serialized interface name that
- // the caller expects to be invoking
- const jchar* str = env->GetStringCritical(name, 0);
- if (str != NULL) {
- parcel->writeInterfaceToken(String16(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name)));
- env->ReleaseStringCritical(name, str);
- }
+ if (parcel != nullptr) {
+ InterfaceDescriptorString descriptor(env, name);
+ parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
+ descriptor.size());
}
}
static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- const jchar* str = env->GetStringCritical(name, 0);
- if (str) {
- IPCThreadState* threadState = IPCThreadState::self();
- const int32_t oldPolicy = threadState->getStrictModePolicy();
- const bool isValid = parcel->enforceInterface(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name),
- threadState);
- env->ReleaseStringCritical(name, str);
- if (isValid) {
- const int32_t newPolicy = threadState->getStrictModePolicy();
- if (oldPolicy != newPolicy) {
- // Need to keep the Java-level thread-local strict
- // mode policy in sync for the libcore
- // enforcements, which involves an upcall back
- // into Java. (We can't modify the
- // Parcel.enforceInterface signature, as it's
- // pseudo-public, and used via AIDL
- // auto-generation...)
- set_dalvik_blockguard_policy(env, newPolicy);
- }
- return; // everything was correct -> return silently
+ if (parcel != nullptr) {
+ InterfaceDescriptorString descriptor(env, name);
+ IPCThreadState* threadState = IPCThreadState::self();
+ const int32_t oldPolicy = threadState->getStrictModePolicy();
+ const bool isValid =
+ parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
+ descriptor.size(), threadState);
+ if (isValid) {
+ const int32_t newPolicy = threadState->getStrictModePolicy();
+ if (oldPolicy != newPolicy) {
+ // Need to keep the Java-level thread-local strict
+ // mode policy in sync for the libcore
+ // enforcements, which involves an upcall back
+ // into Java. (We can't modify the
+ // Parcel.enforceInterface signature, as it's
+ // pseudo-public, and used via AIDL
+ // auto-generation...)
+ set_dalvik_blockguard_policy(env, newPolicy);
}
+ return; // everything was correct -> return silently
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 80f73f043068..9b90b0a24922 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -511,6 +511,7 @@
<protected-broadcast android:name="android.telecom.action.NUISANCE_CALL_STATUS_CHANGED" />
<protected-broadcast android:name="android.telecom.action.PHONE_ACCOUNT_REGISTERED" />
<protected-broadcast android:name="android.telecom.action.PHONE_ACCOUNT_UNREGISTERED" />
+ <protected-broadcast android:name="android.telecom.action.POST_CALL" />
<protected-broadcast android:name="android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION" />
<protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
<protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" />
diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp
index 4b43b4136076..ca655f18149c 100644
--- a/core/xsd/vts/Android.bp
+++ b/core/xsd/vts/Android.bp
@@ -40,7 +40,3 @@ cc_test {
],
test_config: "vts_permission_validate_test.xml",
}
-
-vts_config {
- name: "VtsValidatePermission",
-}
diff --git a/core/xsd/vts/AndroidTest.xml b/core/xsd/vts/AndroidTest.xml
deleted file mode 100644
index e5cc9a0f74ee..000000000000
--- a/core/xsd/vts/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Config for VTS VtsValidatePermission.">
- <option name="config-descriptor:metadata" key="plan" value="vts-treble" />
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
- <option name="abort-on-push-failure" value="false"/>
- <option name="push-group" value="HostDrivenTest.push"/>
- <option name="push" value="DATA/etc/permission.xsd->/data/local/tmp/permission.xsd"/>
- </target_preparer>
- <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
- <option name="test-module-name" value="VtsValidatePermission"/>
- <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_permission_validate_test/vts_permission_validate_test" />
- <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_permission_validate_test/vts_permission_validate_test" />
- <option name="binary-test-type" value="gtest"/>
- <option name="test-timeout" value="30s"/>
- </test>
-</configuration>
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 644d5fbd5bf9..e4198017aee0 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -559,6 +559,7 @@ void GraphicsStatsService::finishDumpInMemory(Dump* dump, AStatsEventList* data,
AStatsEvent_writeBool(event, !lastFullDay);
AStatsEvent_build(event);
}
+ delete dump;
}
diff --git a/non-updatable-api/Android.bp b/non-updatable-api/Android.bp
index 4037781c1844..00b901992b90 100644
--- a/non-updatable-api/Android.bp
+++ b/non-updatable-api/Android.bp
@@ -23,13 +23,31 @@ filegroup {
}
filegroup {
+ name: "non-updatable-removed.txt",
+ srcs: ["removed.txt"],
+ visibility: ["//frameworks/base/api"],
+}
+
+filegroup {
name: "non-updatable-system-current.txt",
srcs: ["system-current.txt"],
visibility: ["//frameworks/base/api"],
}
filegroup {
+ name: "non-updatable-system-removed.txt",
+ srcs: ["system-removed.txt"],
+ visibility: ["//frameworks/base/api"],
+}
+
+filegroup {
name: "non-updatable-module-lib-current.txt",
srcs: ["module-lib-current.txt"],
visibility: ["//frameworks/base/api"],
}
+
+filegroup {
+ name: "non-updatable-module-lib-removed.txt",
+ srcs: ["module-lib-removed.txt"],
+ visibility: ["//frameworks/base/api"],
+}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 8a36837d10d5..1aa5a5dd2ad7 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -9126,6 +9126,7 @@ package android.bluetooth.le {
method public boolean getIncludeTxPowerLevel();
method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
+ method @Nullable public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
method public java.util.List<android.os.ParcelUuid> getServiceUuids();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR;
@@ -9135,6 +9136,7 @@ package android.bluetooth.le {
ctor public AdvertiseData.Builder();
method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]);
method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
+ method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid);
method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
method public android.bluetooth.le.AdvertiseData build();
method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
@@ -46078,6 +46080,7 @@ package android.telephony {
method @NonNull public android.os.Bundle getCarrierConfigValues();
method public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSmsCapacityOnIcc();
method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index b67c22c27cb8..2b3e7815d060 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -9957,7 +9957,6 @@ package android.telephony {
method public boolean disableCellBroadcastRange(int, int, int);
method public boolean enableCellBroadcastRange(int, int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 9ff868467531..f7f3cbb7d332 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -321,6 +321,9 @@ public class DynamicSystemInstallationService extends Service
if (!isDynamicSystemInstalled() && (getStatus() != STATUS_READY)) {
Log.e(TAG, "Trying to discard AOT while there is no complete installation");
+ // Stop foreground state and dismiss stale notification.
+ stopForeground(STOP_FOREGROUND_REMOVE);
+ resetTaskAndStop();
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
index fbcd6ba0ff47..42dde4064a97 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
@@ -205,7 +205,8 @@ public class ScreenshotNotificationsController {
mPublicNotificationBuilder
.setContentTitle(mResources.getString(R.string.screenshot_saved_title))
.setContentText(mResources.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0))
+ .setContentIntent(PendingIntent
+ .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE))
.setWhen(now)
.setAutoCancel(true)
.setColor(mContext.getColor(
@@ -213,7 +214,8 @@ public class ScreenshotNotificationsController {
mNotificationBuilder
.setContentTitle(mResources.getString(R.string.screenshot_saved_title))
.setContentText(mResources.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0))
+ .setContentIntent(PendingIntent
+ .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE))
.setWhen(now)
.setAutoCancel(true)
.setColor(mContext.getColor(
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index b25df5f9c07f..5e7280840bb9 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -104,9 +104,13 @@ public class LeakReporter {
.setContentText(String.format(
"SystemUI has detected %d leaked objects. Tap to send", garbageCount))
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
- .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+ .setContentIntent(PendingIntent.getActivityAsUser(
+ mContext,
+ 0,
getIntent(hprofFile, dumpFile),
- PendingIntent.FLAG_UPDATE_CURRENT, null, UserHandle.CURRENT));
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ null,
+ UserHandle.CURRENT));
notiMan.notify(TAG, 0, builder.build());
} catch (IOException e) {
Log.e(TAG, "Couldn't dump heap for leak", e);
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 257538d6216d..5526c657b874 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -101,6 +101,7 @@ java_defaults {
],
libs: [
"framework-tethering",
+ "framework-wifi",
],
jarjar_rules: "jarjar-rules.txt",
optimize: {
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 336124dc1b90..52d59fcdc19b 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -616,7 +616,7 @@ public class IpServer extends StateMachine {
if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
if (enabled) {
- mIpv4Address = requestIpv4Address();
+ mIpv4Address = requestIpv4Address(true /* useLastAddress */);
}
if (mIpv4Address == null) {
@@ -661,14 +661,14 @@ public class IpServer extends StateMachine {
return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr);
}
- private LinkAddress requestIpv4Address() {
+ private LinkAddress requestIpv4Address(final boolean useLastAddress) {
if (mStaticIpv4ServerAddr != null) return mStaticIpv4ServerAddr;
if (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) {
return new LinkAddress(BLUETOOTH_IFACE_ADDR);
}
- return mPrivateAddressCoordinator.requestDownstreamAddress(this);
+ return mPrivateAddressCoordinator.requestDownstreamAddress(this, useLastAddress);
}
private boolean startIPv6() {
@@ -957,7 +957,7 @@ public class IpServer extends StateMachine {
}
final LinkAddress deprecatedLinkAddress = mIpv4Address;
- mIpv4Address = requestIpv4Address();
+ mIpv4Address = requestIpv4Address(false);
if (mIpv4Address == null) {
mLog.e("Fail to request a new downstream prefix");
return;
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index fd9e36080c80..6276c4e2aa7d 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -15,7 +15,10 @@
*/
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.util.PrefixUtils.asIpPrefix;
import static java.util.Arrays.asList;
@@ -23,12 +26,11 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.net.Network;
import android.net.ip.IpServer;
-import android.net.util.PrefixUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.SparseArray;
import androidx.annotation.Nullable;
@@ -58,9 +60,6 @@ public class PrivateAddressCoordinator {
private static final int MAX_UBYTE = 256;
private static final int BYTE_MASK = 0xff;
- // reserved for bluetooth tethering.
- private static final int BLUETOOTH_RESERVED = 44;
- private static final int WIFI_P2P_RESERVED = 49;
private static final byte DEFAULT_ID = (byte) 42;
// Upstream monitor would be stopped when tethering is down. When tethering restart, downstream
@@ -75,9 +74,12 @@ public class PrivateAddressCoordinator {
// 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 ConnectivityManager mConnectivityMgr;
private final TetheringConfiguration mConfig;
+ // keyed by downstream type(TetheringManager.TETHERING_*).
+ private final SparseArray<LinkAddress> mCachedAddresses;
public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
mDownstreams = new ArraySet<>();
@@ -86,20 +88,33 @@ public class PrivateAddressCoordinator {
mConnectivityMgr = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
mConfig = config;
+ mCachedAddresses = new SparseArray<>();
+ // 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));
}
/**
* Record a new upstream IpPrefix which may conflict with tethering downstreams.
- * The downstreams will be notified if a conflict is found.
+ * The downstreams will be notified if a conflict is found. When updateUpstreamPrefix is called,
+ * UpstreamNetworkState must have an already populated LinkProperties.
*/
- public void updateUpstreamPrefix(final Network network, final LinkProperties lp) {
- final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(lp.getAllLinkAddresses());
+ public void updateUpstreamPrefix(final UpstreamNetworkState ns) {
+ // Do not support VPN as upstream. Normally, networkCapabilities is not expected to be null,
+ // but just checking to be sure.
+ if (ns.networkCapabilities != null && ns.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
+ removeUpstreamPrefix(ns.network);
+ return;
+ }
+
+ final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(
+ ns.linkProperties.getAllLinkAddresses());
if (ipv4Prefixes.isEmpty()) {
- removeUpstreamPrefix(network);
+ removeUpstreamPrefix(ns.network);
return;
}
- mUpstreamPrefixMap.put(network, ipv4Prefixes);
+ mUpstreamPrefixMap.put(ns.network, ipv4Prefixes);
handleMaybePrefixConflict(ipv4Prefixes);
}
@@ -108,7 +123,7 @@ public class PrivateAddressCoordinator {
for (LinkAddress address : linkAddresses) {
if (!address.isIpv4()) continue;
- list.add(PrefixUtils.asIpPrefix(address));
+ list.add(asIpPrefix(address));
}
return list;
@@ -147,21 +162,23 @@ public class PrivateAddressCoordinator {
mUpstreamPrefixMap.removeAll(toBeRemoved);
}
- private boolean isReservedSubnet(final int subnet) {
- return subnet == BLUETOOTH_RESERVED || subnet == WIFI_P2P_RESERVED;
- }
-
/**
* Pick a random available address and mark its prefix as in use for the provided IpServer,
* returns null if there is no available address.
*/
@Nullable
- public LinkAddress requestDownstreamAddress(final IpServer ipServer) {
+ public LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) {
if (mConfig.shouldEnableWifiP2pDedicatedIp()
&& ipServer.interfaceType() == TETHERING_WIFI_P2P) {
return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS);
}
+ final LinkAddress cachedAddress = mCachedAddresses.get(ipServer.interfaceType());
+ if (useLastAddress && cachedAddress != null
+ && !isConflictWithUpstream(asIpPrefix(cachedAddress))) {
+ return cachedAddress;
+ }
+
// Address would be 192.168.[subAddress]/24.
final byte[] bytes = mTetheringPrefix.getRawAddress();
final int subAddress = getRandomSubAddr();
@@ -169,9 +186,8 @@ public class PrivateAddressCoordinator {
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;
- if (isReservedSubnet(newSubNet)) continue;
-
bytes[2] = (byte) newSubNet;
+
final InetAddress addr;
try {
addr = InetAddress.getByAddress(bytes);
@@ -179,20 +195,23 @@ public class PrivateAddressCoordinator {
throw new IllegalStateException("Invalid address, shouldn't happen.", e);
}
- final IpPrefix prefix = new IpPrefix(addr, PREFIX_LENGTH);
- // Check whether this prefix is in use.
- if (isDownstreamPrefixInUse(prefix)) continue;
- // Check whether this prefix is conflict with any current upstream network.
- if (isConflictWithUpstream(prefix)) continue;
+ if (isConflict(new IpPrefix(addr, PREFIX_LENGTH))) continue;
mDownstreams.add(ipServer);
- return new LinkAddress(addr, PREFIX_LENGTH);
+ 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);
+ }
+
/** Get random sub address value. Return value is in 0 ~ 0xffff. */
@VisibleForTesting
public int getRandomSubAddr() {
@@ -236,13 +255,24 @@ public class PrivateAddressCoordinator {
return prefix1.contains(prefix2.getAddress());
}
- private boolean isDownstreamPrefixInUse(final IpPrefix source) {
+ // 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.
+ for (int i = 0; i < mCachedAddresses.size(); i++) {
+ if (prefix.equals(asIpPrefix(mCachedAddresses.valueAt(i)))) return true;
+ }
+
+ // IpServer may use manually-defined address (mStaticIpv4ServerAddr) which does not include
+ // in mCachedAddresses.
for (IpServer downstream : mDownstreams) {
- final IpPrefix prefix = getDownstreamPrefix(downstream);
- if (source.equals(prefix)) return true;
+ final IpPrefix target = getDownstreamPrefix(downstream);
+ if (target == null) continue;
+
+ if (isConflictPrefix(prefix, target)) return true;
}
+
return false;
}
@@ -250,7 +280,7 @@ public class PrivateAddressCoordinator {
final LinkAddress address = downstream.getAddress();
if (address == null) return null;
- return PrefixUtils.asIpPrefix(address);
+ return asIpPrefix(address);
}
void dump(final IndentingPrintWriter pw) {
@@ -260,11 +290,19 @@ public class PrivateAddressCoordinator {
pw.println(mUpstreamPrefixMap.keyAt(i) + " - " + mUpstreamPrefixMap.valueAt(i));
}
pw.decreaseIndent();
+
pw.println("mDownstreams:");
pw.increaseIndent();
for (IpServer ipServer : mDownstreams) {
pw.println(ipServer.interfaceType() + " - " + ipServer.getAddress());
}
pw.decreaseIndent();
+
+ pw.println("mCachedAddresses:");
+ pw.increaseIndent();
+ for (int i = 0; i < mCachedAddresses.size(); i++) {
+ pw.println(mCachedAddresses.keyAt(i) + " - " + mCachedAddresses.valueAt(i));
+ }
+ pw.decreaseIndent();
}
}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 64d5025807e7..474f4e8b603a 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -1678,14 +1678,6 @@ public class Tethering {
}
}
- private void addUpstreamPrefixes(final UpstreamNetworkState ns) {
- mPrivateAddressCoordinator.updateUpstreamPrefix(ns.network, ns.linkProperties);
- }
-
- private void removeUpstreamPrefixes(final UpstreamNetworkState ns) {
- mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
- }
-
@VisibleForTesting
void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
@@ -1696,10 +1688,10 @@ public class Tethering {
final UpstreamNetworkState ns = (UpstreamNetworkState) o;
switch (arg1) {
case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
- addUpstreamPrefixes(ns);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(ns);
break;
case UpstreamNetworkMonitor.EVENT_ON_LOST:
- removeUpstreamPrefixes(ns);
+ mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
break;
}
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 747d3e803026..95e36fa18f42 100644
--- a/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
+++ b/packages/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
@@ -33,7 +33,6 @@ import android.net.MacAddress;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
import android.net.util.InterfaceParams;
-import android.net.util.IpUtils;
import android.net.util.TetheringUtils;
import android.os.Handler;
import android.os.HandlerThread;
@@ -46,6 +45,7 @@ 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 org.junit.After;
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 1a976adc60e0..2eb75895ac3e 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -47,6 +47,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -230,7 +231,8 @@ public class IpServerTest {
dispatchTetherConnectionChanged(upstreamIface, lp, 0);
}
reset(mNetd, mCallback, mAddressCoordinator);
- when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(mTestAddress);
+ when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
+ mTestAddress);
}
private void setUpDhcpServer() throws Exception {
@@ -250,7 +252,8 @@ public class IpServerTest {
@Before public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
- when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(mTestAddress);
+ when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
+ mTestAddress);
when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */);
mBpfCoordinator = spy(new BpfCoordinator(
@@ -372,7 +375,7 @@ public class IpServerTest {
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any());
+ inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
@@ -393,7 +396,7 @@ public class IpServerTest {
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any());
+ inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
@@ -607,7 +610,7 @@ public class IpServerTest {
final ArgumentCaptor<LinkProperties> lpCaptor =
ArgumentCaptor.forClass(LinkProperties.class);
InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator);
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any());
+ inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
// One for ipv4 route, one for ipv6 link local route.
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
@@ -620,11 +623,12 @@ public class IpServerTest {
// Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals
// onNewPrefixRequest callback.
final LinkAddress newAddress = new LinkAddress("192.168.100.125/24");
- when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(newAddress);
+ when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
+ newAddress);
eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24"));
mLooper.dispatchAll();
- inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any());
+ inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(false));
inOrder.verify(mNetd).tetherApplyDnsInterfaces();
inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
verifyNoMoreInteractions(mCallback);
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 8e93c2e447b3..191eb6e71149 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
@@ -15,10 +15,15 @@
*/
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.util.PrefixUtils.asIpPrefix;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -30,14 +35,12 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.ip.IpServer;
-import android.net.util.NetworkConstants;
-import android.net.util.PrefixUtils;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -48,13 +51,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.List;
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public final class PrivateAddressCoordinatorTest {
- private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
- private static final String TEST_WIFI_IFNAME = "test_wlan0";
+ private static final String TEST_IFNAME = "test0";
@Mock private IpServer mHotspotIpServer;
@Mock private IpServer mUsbIpServer;
@@ -65,11 +65,12 @@ public final class PrivateAddressCoordinatorTest {
@Mock private TetheringConfiguration mConfig;
private PrivateAddressCoordinator mPrivateAddressCoordinator;
- private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24");
+ private final LinkAddress mBluetoothAddress = new LinkAddress("192.168.44.1/24");
private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24");
private final Network mWifiNetwork = new Network(1);
private final Network mMobileNetwork = new Network(2);
- private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork};
+ private final Network mVpnNetwork = new Network(3);
+ private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork};
private void setUpIpServers() throws Exception {
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
@@ -90,127 +91,140 @@ public final class PrivateAddressCoordinatorTest {
}
@Test
- public void testDownstreamPrefixRequest() throws Exception {
- LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(address);
- assertNotEquals(hotspotPrefix, mBluetoothPrefix);
+ public void testRequestDownstreamAddressWithoutUsingLastAddress() throws Exception {
+ final IpPrefix bluetoothPrefix = asIpPrefix(mBluetoothAddress);
+ final LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, false /* useLastAddress */);
+ final IpPrefix hotspotPrefix = asIpPrefix(address);
+ assertNotEquals(hotspotPrefix, bluetoothPrefix);
+ when(mHotspotIpServer.getAddress()).thenReturn(address);
- address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix testDupRequest = PrefixUtils.asIpPrefix(address);
+ final LinkAddress newAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, false /* useLastAddress */);
+ final IpPrefix testDupRequest = asIpPrefix(newAddress);
assertNotEquals(hotspotPrefix, testDupRequest);
- assertNotEquals(mBluetoothPrefix, testDupRequest);
+ assertNotEquals(bluetoothPrefix, testDupRequest);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mUsbIpServer);
- final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(address);
- assertNotEquals(usbPrefix, mBluetoothPrefix);
+ final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, false /* useLastAddress */);
+ final IpPrefix usbPrefix = asIpPrefix(usbAddress);
+ assertNotEquals(usbPrefix, bluetoothPrefix);
assertNotEquals(usbPrefix, hotspotPrefix);
mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
}
@Test
- public void testRequestDownstreamAddress() throws Exception {
- LinkAddress expectedAddress = new LinkAddress("192.168.43.42/24");
- int fakeSubAddr = 0x2b00;
+ public void testSanitizedAddress() throws Exception {
+ int fakeSubAddr = 0x2b00; // 43.0.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
LinkAddress actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- assertEquals(actualAddress, expectedAddress);
+ mHotspotIpServer, false /* useLastAddress */);
+ assertEquals(new LinkAddress("192.168.43.42/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- fakeSubAddr = 0x2b01;
+ fakeSubAddr = 0x2d01; // 45.1.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- assertEquals(actualAddress, expectedAddress);
+ mHotspotIpServer, false /* useLastAddress */);
+ assertEquals(new LinkAddress("192.168.45.42/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- fakeSubAddr = 0x2bff;
+ fakeSubAddr = 0x2eff; // 46.255.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- assertEquals(actualAddress, expectedAddress);
+ mHotspotIpServer, false /* useLastAddress */);
+ assertEquals(new LinkAddress("192.168.46.42/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
- expectedAddress = new LinkAddress("192.168.43.5/24");
- fakeSubAddr = 0x2b05;
+ fakeSubAddr = 0x2f05; // 47.5.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- assertEquals(actualAddress, expectedAddress);
+ mHotspotIpServer, false /* useLastAddress */);
+ assertEquals(new LinkAddress("192.168.47.5/24"), actualAddress);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
}
- private int getBluetoothSubAddress() {
- final byte[] rawAddress = mBluetoothPrefix.getRawAddress();
- int bluetoothSubNet = rawAddress[2] & 0xff;
- return (bluetoothSubNet << 8) + 0x5;
- }
-
@Test
- public void testReserveBluetoothPrefix() throws Exception {
- when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(getBluetoothSubAddress());
- LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(address);
- assertNotEquals("Should not get reserved prefix: ", mBluetoothPrefix, hotspotPrefix);
+ public void testReservedPrefix() throws Exception {
+ // - Test bluetooth prefix is reserved.
+ when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ getSubAddress(mBluetoothAddress.getAddress().getAddress()));
+ final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, false /* useLastAddress */);
+ final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddress);
+ assertNotEquals(asIpPrefix(mBluetoothAddress), hotspotPrefix);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
+
+ // - Test previous enabled hotspot prefix(cached prefix) is reserved.
+ when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ getSubAddress(hotspotAddress.getAddress().getAddress()));
+ final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, false /* useLastAddress */);
+ final IpPrefix usbPrefix = asIpPrefix(usbAddress);
+ assertNotEquals(asIpPrefix(mBluetoothAddress), usbPrefix);
+ assertNotEquals(hotspotPrefix, usbPrefix);
+ mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
+
+ // - Test wifi p2p prefix is reserved.
+ when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
+ getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
+ final LinkAddress etherAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mEthernetIpServer, false /* useLastAddress */);
+ final IpPrefix etherPrefix = asIpPrefix(etherAddress);
+ assertNotEquals(asIpPrefix(mLegacyWifiP2pAddress), etherPrefix);
+ assertNotEquals(asIpPrefix(mBluetoothAddress), etherPrefix);
+ assertNotEquals(hotspotPrefix, etherPrefix);
+ mPrivateAddressCoordinator.releaseDownstream(mEthernetIpServer);
}
@Test
- public void testNoConflictDownstreamPrefix() throws Exception {
+ public void testRequestLastDownstreamAddress() throws Exception {
final int fakeHotspotSubAddr = 0x2b05;
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
- LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(address);
- assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
- when(mHotspotIpServer.getAddress()).thenReturn(address);
+ final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true /* useLastAddress */);
+ assertEquals("Wrong wifi prefix: ", predefinedPrefix, asIpPrefix(hotspotAddress));
+ when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddress);
- address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mUsbIpServer);
- final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(address);
- assertNotEquals(predefinedPrefix, usbPrefix);
+ final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, true /* useLastAddress */);
+ assertNotEquals(predefinedPrefix, asIpPrefix(usbAddress));
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
- address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mUsbIpServer);
- final IpPrefix allowUseFreePrefix = PrefixUtils.asIpPrefix(address);
- assertEquals("Fail to reselect available prefix: ", predefinedPrefix, allowUseFreePrefix);
- }
- private LinkProperties buildUpstreamLinkProperties(boolean withIPv4, boolean withIPv6,
- boolean isMobile) {
- final String testIface;
- final String testIpv4Address;
- if (isMobile) {
- testIface = TEST_MOBILE_IFNAME;
- testIpv4Address = "10.0.0.1";
- } else {
- testIface = TEST_WIFI_IFNAME;
- testIpv4Address = "192.168.43.5";
- }
+ final int newFakeSubAddr = 0x3c05;
+ when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
+
+ final LinkAddress newHotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer, true /* useLastAddress */);
+ assertEquals(hotspotAddress, newHotspotAddress);
+ final LinkAddress newUsbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mUsbIpServer, true /* useLastAddress */);
+ assertEquals(usbAddress, newUsbAddress);
+ }
+ private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
+ final LinkAddress v4Addr, final LinkAddress v6Addr, final NetworkCapabilities cap) {
final LinkProperties prop = new LinkProperties();
- prop.setInterfaceName(testIface);
+ prop.setInterfaceName(TEST_IFNAME);
+ if (v4Addr != null) prop.addLinkAddress(v4Addr);
- if (withIPv4) {
- prop.addLinkAddress(
- new LinkAddress(InetAddresses.parseNumericAddress(testIpv4Address),
- NetworkConstants.IPV4_ADDR_BITS));
- }
+ if (v6Addr != null) prop.addLinkAddress(v6Addr);
+
+ return new UpstreamNetworkState(prop, cap, network);
+ }
- if (withIPv6) {
- prop.addLinkAddress(
- new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
- NetworkConstants.RFC7421_PREFIX_LENGTH));
+ private NetworkCapabilities makeNetworkCapabilities(final int transportType) {
+ final NetworkCapabilities cap = new NetworkCapabilities();
+ cap.addTransportType(transportType);
+ if (transportType == TRANSPORT_VPN) {
+ cap.removeCapability(NET_CAPABILITY_NOT_VPN);
}
- return prop;
+
+ return cap;
}
@Test
@@ -220,57 +234,81 @@ public final class PrivateAddressCoordinatorTest {
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
// Force always get subAddress "43.5" for conflict testing.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
- // 1. Enable hotspot with prefix 192.168.43.0/24
+ // - Enable hotspot with prefix 192.168.43.0/24
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(hotspotAddr);
+ mHotspotIpServer, true /* useLastAddress */);
+ final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddr);
assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr);
- // 2. Update v6 only mobile network, hotspot prefix should not be removed.
- List<String> testConflicts;
- final LinkProperties v6OnlyMobileProp = buildUpstreamLinkProperties(false, true, true);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v6OnlyMobileProp);
+ // - test mobile network with null NetworkCapabilities. Ideally this should not happen
+ // because NetworkCapabilities update should always happen before LinkProperties update
+ // and the UpstreamNetworkState update, just make sure no crash in this case.
+ final UpstreamNetworkState noCapUpstream = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("10.0.0.8/24"), null, null);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
+ verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ // - test mobile upstream with no address.
+ final UpstreamNetworkState noAddress = buildUpstreamNetworkState(mMobileNetwork,
+ null, null, makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
+ verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ // - Update v6 only mobile network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v6OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
+ null, new LinkAddress("2001:db8::/64"),
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyMobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork);
- // 3. Update v4 only mobile network, hotspot prefix should not be removed.
- final LinkProperties v4OnlyMobileProp = buildUpstreamLinkProperties(true, false, true);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4OnlyMobileProp);
+ // - Update v4 only mobile network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v4OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("10.0.0.8/24"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyMobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // 4. Update v4v6 mobile network, hotspot prefix should not be removed.
- final LinkProperties v4v6MobileProp = buildUpstreamLinkProperties(true, true, true);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4v6MobileProp);
+ // - Update v4v6 mobile network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v4v6Mobile = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("10.0.0.8/24"), new LinkAddress("2001:db8::/64"),
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4v6Mobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // 5. Update v6 only wifi network, hotspot prefix should not be removed.
- final LinkProperties v6OnlyWifiProp = buildUpstreamLinkProperties(false, true, false);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v6OnlyWifiProp);
+ // - Update v6 only wifi network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v6OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
+ null, new LinkAddress("2001:db8::/64"), makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyWifi);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
- // 6. Update v4 only wifi network, it conflict with hotspot prefix.
- final LinkProperties v4OnlyWifiProp = buildUpstreamLinkProperties(true, false, false);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp);
+ // - Update vpn network, it conflict with hotspot prefix but VPN networks are ignored.
+ final UpstreamNetworkState v4OnlyVpn = buildUpstreamNetworkState(mVpnNetwork,
+ new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_VPN));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyVpn);
+ verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ // - Update v4 only wifi network, it conflict with hotspot prefix.
+ final UpstreamNetworkState v4OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
+ new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
reset(mHotspotIpServer);
- // 7. Restart hotspot again and its prefix is different previous.
+ // - Restart hotspot again and its prefix is different previous.
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix hotspotPrefix2 = PrefixUtils.asIpPrefix(hotspotAddr2);
+ mHotspotIpServer, true /* useLastAddress */);
+ final IpPrefix hotspotPrefix2 = asIpPrefix(hotspotAddr2);
assertNotEquals(hotspotPrefix, hotspotPrefix2);
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // 7. Usb tethering can be enabled and its prefix is different with conflict one.
+ // - Usb tethering can be enabled and its prefix is different with conflict one.
final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
- mUsbIpServer);
- final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(usbAddr);
+ mUsbIpServer, true /* useLastAddress */);
+ final IpPrefix usbPrefix = asIpPrefix(usbAddr);
assertNotEquals(predefinedPrefix, usbPrefix);
assertNotEquals(hotspotPrefix2, usbPrefix);
when(mUsbIpServer.getAddress()).thenReturn(usbAddr);
- // 8. Disable wifi upstream, then wifi's prefix can be selected again.
+ // - Disable wifi upstream, then wifi's prefix can be selected again.
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
- mEthernetIpServer);
- final IpPrefix ethPrefix = PrefixUtils.asIpPrefix(ethAddr);
+ mEthernetIpServer, true /* useLastAddress */);
+ final IpPrefix ethPrefix = asIpPrefix(ethAddr);
assertEquals(predefinedPrefix, ethPrefix);
}
@@ -283,9 +321,9 @@ public final class PrivateAddressCoordinatorTest {
private void assertReseveredWifiP2pPrefix() throws Exception {
LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mHotspotIpServer);
- final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(address);
- final IpPrefix legacyWifiP2pPrefix = PrefixUtils.asIpPrefix(mLegacyWifiP2pAddress);
+ mHotspotIpServer, true /* useLastAddress */);
+ final IpPrefix hotspotPrefix = asIpPrefix(address);
+ final IpPrefix legacyWifiP2pPrefix = asIpPrefix(mLegacyWifiP2pAddress);
assertNotEquals(legacyWifiP2pPrefix, hotspotPrefix);
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
}
@@ -303,7 +341,7 @@ public final class PrivateAddressCoordinatorTest {
// If #shouldEnableWifiP2pDedicatedIp() is enabled, wifi P2P gets the configured address.
LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
- mWifiP2pIpServer);
+ mWifiP2pIpServer, true /* useLastAddress */);
assertEquals(mLegacyWifiP2pAddress, address);
mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8a1baf25481b..b59f7645445d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1126,7 +1126,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Listen to package add and removal events for all users.
intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
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/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 09c0ba37028a..d990c1e9fbe1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3318,6 +3318,10 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean setProcessMemoryTrimLevel(String process, int userId, int level)
throws RemoteException {
+ if (!isCallerShell()) {
+ EventLog.writeEvent(0x534e4554, 160390416, Binder.getCallingUid(), "");
+ throw new SecurityException("Only shell can call it");
+ }
synchronized (this) {
final ProcessRecord app = findProcessLocked(process, userId, "setProcessMemoryTrimLevel");
if (app == null) {
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 01fa9e755bd6..8625a6f470c5 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -47,7 +47,6 @@ import android.net.NetworkAgent;
import android.net.NetworkUtils;
import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
-import android.net.util.IpUtils;
import android.net.util.KeepaliveUtils;
import android.os.Binder;
import android.os.Handler;
@@ -63,6 +62,7 @@ import android.util.Pair;
import com.android.internal.R;
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.IpUtils;
import java.io.FileDescriptor;
import java.net.InetAddress;
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index de302fc01f2d..198de78ecfa6 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -154,7 +154,7 @@ public class PacManager {
mNetThreadHandler = new Handler(netThread.getLooper());
mPacRefreshIntent = PendingIntent.getBroadcast(
- context, 0, new Intent(ACTION_PAC_REFRESH), 0);
+ context, 0, new Intent(ACTION_PAC_REFRESH), PendingIntent.FLAG_IMMUTABLE);
context.registerReceiver(new PacRefreshIntentReceiver(),
new IntentFilter(ACTION_PAC_REFRESH));
mConnectivityHandler = handler;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 8e1fccd07f7a..2f15918d3064 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -380,8 +380,8 @@ public class Vpn {
}
}
- public boolean checkInterfacePresent(final Vpn vpn, final String iface) {
- return vpn.jniCheck(iface) == 0;
+ public boolean isInterfacePresent(final Vpn vpn, final String iface) {
+ return vpn.jniCheck(iface) != 0;
}
}
@@ -1130,7 +1130,13 @@ public class Vpn {
return mNetworkInfo;
}
- public int getNetId() {
+ /**
+ * Return netId of current running VPN network.
+ *
+ * @return a netId if there is a running VPN network or NETID_UNSET if there is no running VPN
+ * network or network is null.
+ */
+ public synchronized int getNetId() {
final NetworkAgent agent = mNetworkAgent;
if (null == agent) return NETID_UNSET;
final Network network = agent.getNetwork();
@@ -1708,7 +1714,7 @@ public class Vpn {
/**
* Return the configuration of the currently running VPN.
*/
- public VpnConfig getVpnConfig() {
+ public synchronized VpnConfig getVpnConfig() {
enforceControlPermission();
return mConfig;
}
@@ -2755,7 +2761,10 @@ public class Vpn {
final LinkProperties lp = cm.getLinkProperties(network);
if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) {
final NetworkInfo networkInfo = cm.getNetworkInfo(network);
- if (networkInfo != null) mOuterConnection.set(networkInfo.getType());
+ if (networkInfo != null) {
+ mOuterConnection.set(networkInfo.getType());
+ break;
+ }
}
}
}
@@ -2986,7 +2995,7 @@ public class Vpn {
checkInterruptAndDelay(false);
// Check if the interface is gone while we are waiting.
- if (mDeps.checkInterfacePresent(Vpn.this, mConfig.interfaze)) {
+ if (!mDeps.isInterfacePresent(Vpn.this, mConfig.interfaze)) {
throw new IllegalStateException(mConfig.interfaze + " is gone");
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 66652ca26e54..535284083d11 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -16,6 +16,8 @@
package com.android.server.hdmi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.tv.cec.V1_0.CecMessage;
import android.hardware.tv.cec.V1_0.HotplugEvent;
@@ -725,6 +727,7 @@ final class HdmiCecController {
private IHdmiCec mHdmiCec;
private final Object mLock = new Object();
private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
+ @Nullable private HdmiCecCallback mCallback;
@Override
public String nativeInit() {
@@ -733,7 +736,7 @@ final class HdmiCecController {
boolean connectToHal() {
try {
- mHdmiCec = IHdmiCec.getService();
+ mHdmiCec = IHdmiCec.getService(true);
try {
mHdmiCec.linkToDeath(this, HDMI_CEC_HAL_DEATH_COOKIE);
} catch (RemoteException e) {
@@ -747,7 +750,8 @@ final class HdmiCecController {
}
@Override
- public void setCallback(HdmiCecCallback callback) {
+ public void setCallback(@NonNull HdmiCecCallback callback) {
+ mCallback = callback;
try {
mHdmiCec.setCallback(callback);
} catch (RemoteException e) {
@@ -887,6 +891,10 @@ final class HdmiCecController {
if (cookie == HDMI_CEC_HAL_DEATH_COOKIE) {
HdmiLogger.error(TAG, "Service died cokkie : " + cookie + "; reconnecting");
connectToHal();
+ // Reconnect the callback
+ if (mCallback != null) {
+ setCallback(mCallback);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index bc78d66037fe..c3cb42f95cc6 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -75,6 +75,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -173,6 +174,8 @@ public class PreferencesHelper implements RankingConfig {
private boolean mAllowInvalidShortcuts = false;
+ private Map<String, List<String>> mOemLockedApps = new HashMap();
+
public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
ZenModeHelper zenHelper, NotificationChannelLogger notificationChannelLogger,
AppOpsManager appOpsManager,
@@ -314,6 +317,12 @@ public class PreferencesHelper implements RankingConfig {
}
channel.setImportanceLockedByCriticalDeviceFunction(
r.defaultAppLockedImportance);
+ channel.setImportanceLockedByOEM(r.oemLockedImportance);
+ if (!channel.isImportanceLockedByOEM()) {
+ if (r.oemLockedChannels.contains(channel.getId())) {
+ channel.setImportanceLockedByOEM(true);
+ }
+ }
boolean isInvalidShortcutChannel =
channel.getConversationId() != null &&
channel.getConversationId().contains(
@@ -396,6 +405,14 @@ public class PreferencesHelper implements RankingConfig {
r.visibility = visibility;
r.showBadge = showBadge;
r.bubblePreference = bubblePreference;
+ if (mOemLockedApps.containsKey(r.pkg)) {
+ List<String> channels = mOemLockedApps.get(r.pkg);
+ if (channels == null || channels.isEmpty()) {
+ r.oemLockedImportance = true;
+ } else {
+ r.oemLockedChannels = channels;
+ }
+ }
try {
createDefaultChannelIfNeededLocked(r);
@@ -1149,8 +1166,10 @@ public class PreferencesHelper implements RankingConfig {
String channelId = appSplit.length == 2 ? appSplit[1] : null;
synchronized (mPackagePreferences) {
+ boolean foundApp = false;
for (PackagePreferences r : mPackagePreferences.values()) {
if (r.pkg.equals(appName)) {
+ foundApp = true;
if (channelId == null) {
// lock all channels for the app
r.oemLockedImportance = true;
@@ -1168,6 +1187,14 @@ public class PreferencesHelper implements RankingConfig {
}
}
}
+ if (!foundApp) {
+ List<String> channels =
+ mOemLockedApps.getOrDefault(appName, new ArrayList<>());
+ if (channelId != null) {
+ channels.add(channelId);
+ }
+ mOemLockedApps.put(appName, channels);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 0dfa081e7695..48ec9b4b502d 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -337,6 +337,7 @@ public class BackgroundDexOptService extends JobService {
private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
long lowStorageThreshold) {
ArraySet<String> updatedPackages = new ArraySet<>();
+ ArraySet<String> updatedPackagesDueToSecondaryDex = new ArraySet<>();
try {
final boolean supportSecondaryDex = supportSecondaryDex();
@@ -391,11 +392,14 @@ public class BackgroundDexOptService extends JobService {
}
int secondaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
- /*isForPrimaryDex*/ false, updatedPackages);
+ /*isForPrimaryDex*/ false, updatedPackagesDueToSecondaryDex);
return secondaryResult;
} finally {
// Always let the pinner service know about changes.
notifyPinService(updatedPackages);
+ // Only notify IORap the primary dex opt, because we don't want to
+ // invalidate traces unnecessary due to b/161633001 and that it's
+ // better to have a trace than no trace at all.
notifyPackagesUpdated(updatedPackages);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4f0c707a1dae..9d0a5c4787fd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3649,6 +3649,8 @@ public class PackageManagerService extends IPackageManager.Stub
PackageParser.readConfigUseRoundIcon(mContext.getResources());
mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
+
+ Slog.i(TAG, "Fix for b/169414761 is applied");
}
/**
@@ -11096,6 +11098,8 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.addRenamedPackageLPw(parsedPackage.getRealPackage(),
originalPkgSetting.name);
mTransferredPackages.add(originalPkgSetting.name);
+ } else {
+ mSettings.removeRenamedPackageLPw(parsedPackage.getPackageName());
}
}
if (pkgSetting.sharedUser != null) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a0feb94fd3fc..0f5d9781c612 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -476,6 +476,10 @@ public final class Settings {
return mRenamedPackages.put(pkgName, origPkgName);
}
+ void removeRenamedPackageLPw(String pkgName) {
+ mRenamedPackages.remove(pkgName);
+ }
+
public boolean canPropagatePermissionToInstantApp(String permName) {
return mPermissions.canPropagatePermissionToInstantApp(permName);
}
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index 01dc01efaca8..0e88862e01b1 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -1,4 +1,5 @@
moltmann@google.com
+zhanghai@google.com
per-file DefaultPermissionGrantPolicy.java = hackbod@android.com
per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com
per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com
@@ -7,3 +8,4 @@ per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
per-file DefaultPermissionGrantPolicy.java = patb@google.com
per-file DefaultPermissionGrantPolicy.java = eugenesusla@google.com
per-file DefaultPermissionGrantPolicy.java = moltmann@google.com
+per-file DefaultPermissionGrantPolicy.java = zhanghai@google.com
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index c4e03f5c65f5..aa76a07bc9c7 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-
import static com.android.server.wm.ActivityStack.TAG_VISIBILITY;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
@@ -174,12 +172,7 @@ class EnsureActivitiesVisibleHelper {
}
final int windowingMode = mContiner.getWindowingMode();
- if (windowingMode == WINDOWING_MODE_FREEFORM) {
- // The visibility of tasks and the activities they contain in freeform stack are
- // determined individually unlike other stacks where the visibility or fullscreen
- // status of an activity in a previous task affects other.
- mBehindFullscreenActivity = !mContainerShouldBeVisible;
- } else if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome()
+ if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome()
&& r.isRootOfTask()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner
+ " stackShouldBeVisible=" + mContainerShouldBeVisible
diff --git a/services/core/xsd/vts/Android.mk b/services/core/xsd/vts/Android.mk
deleted file mode 100644
index 6dc2c437a2f9..000000000000
--- a/services/core/xsd/vts/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := VtsValidateDefaultPermissions
-include test/vts/tools/build/Android.host_config.mk
diff --git a/services/core/xsd/vts/AndroidTest.xml b/services/core/xsd/vts/AndroidTest.xml
deleted file mode 100644
index 4f3b2ef1ace1..000000000000
--- a/services/core/xsd/vts/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Config for VTS VtsValidateDefaultPermissions.">
- <option name="config-descriptor:metadata" key="plan" value="vts-treble" />
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
- <option name="abort-on-push-failure" value="false"/>
- <option name="push-group" value="HostDrivenTest.push"/>
- <option name="push" value="DATA/etc/default-permissions.xsd->/data/local/tmp/default-permissions.xsd"/>
- </target_preparer>
- <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
- <option name="test-module-name" value="VtsValidateDefaultPermissions"/>
- <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_defaultPermissions_validate_test/vts_defaultPermissions_validate_test" />
- <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_defaultPermissions_validate_test/vts_defaultPermissions_validate_test" />
- <option name="binary-test-type" value="gtest"/>
- <option name="test-timeout" value="30s"/>
- </test>
-</configuration>
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/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java
index c0c386b3046e..4875c7cc4263 100644
--- a/services/net/java/android/net/TcpKeepalivePacketData.java
+++ b/services/net/java/android/net/TcpKeepalivePacketData.java
@@ -19,11 +19,12 @@ import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.system.OsConstants;
+import com.android.net.module.util.IpUtils;
+
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 4dc8ad9d0a98..a118e0df1338 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2670,6 +2670,96 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testLockChannelsForOEM_onlyGivenPkg_appDoesNotExistYet() {
+ mHelper.lockChannelsForOEM(new String[] {PKG_O});
+
+ NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
+ NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW);
+ mHelper.createNotificationChannel(PKG_O, 3, a, true, false);
+ mHelper.createNotificationChannel(PKG_N_MR1, 30, b, false, false);
+
+ assertTrue(mHelper.getNotificationChannel(PKG_O, 3, a.getId(), false)
+ .isImportanceLockedByOEM());
+ assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 30, b.getId(), false)
+ .isImportanceLockedByOEM());
+ }
+
+ @Test
+ public void testLockChannelsForOEM_channelSpecific_appDoesNotExistYet() {
+ mHelper.lockChannelsForOEM(new String[] {PKG_O + ":b", PKG_O + ":c"});
+
+ NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
+ NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW);
+ NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT);
+ // different uids, same package
+ mHelper.createNotificationChannel(PKG_O, 3, a, true, false);
+ mHelper.createNotificationChannel(PKG_O, 3, b, false, false);
+ mHelper.createNotificationChannel(PKG_O, 30, c, true, true);
+
+ assertFalse(mHelper.getNotificationChannel(PKG_O, 3, a.getId(), false)
+ .isImportanceLockedByOEM());
+ assertTrue(mHelper.getNotificationChannel(PKG_O, 3, b.getId(), false)
+ .isImportanceLockedByOEM());
+ assertTrue(mHelper.getNotificationChannel(PKG_O, 30, c.getId(), false)
+ .isImportanceLockedByOEM());
+ }
+
+ @Test
+ public void testLockChannelsForOEM_onlyGivenPkg_appDoesNotExistYet_restoreData()
+ throws Exception {
+ mHelper.lockChannelsForOEM(new String[] {PKG_O});
+
+ final String xml = "<ranking version=\"1\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
+ + "<channel id=\"a\" name=\"a\" importance=\"3\"/>"
+ + "<channel id=\"b\" name=\"b\" importance=\"3\"/>"
+ + "</package>"
+ + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1 + "\" >\n"
+ + "<channel id=\"a\" name=\"a\" importance=\"3\"/>"
+ + "<channel id=\"b\" name=\"b\" importance=\"3\"/>"
+ + "</package>"
+ + "</ranking>";
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, "a", false)
+ .isImportanceLockedByOEM());
+ assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "b", false)
+ .isImportanceLockedByOEM());
+ }
+
+ @Test
+ public void testLockChannelsForOEM_channelSpecific_appDoesNotExistYet_restoreData()
+ throws Exception {
+ mHelper.lockChannelsForOEM(new String[] {PKG_O + ":b", PKG_O + ":c"});
+
+ final String xml = "<ranking version=\"1\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + 3 + "\" >\n"
+ + "<channel id=\"a\" name=\"a\" importance=\"3\"/>"
+ + "<channel id=\"b\" name=\"b\" importance=\"3\"/>"
+ + "</package>"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + 30 + "\" >\n"
+ + "<channel id=\"c\" name=\"c\" importance=\"3\"/>"
+ + "</package>"
+ + "</ranking>";
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertFalse(mHelper.getNotificationChannel(PKG_O, 3, "a", false)
+ .isImportanceLockedByOEM());
+ assertTrue(mHelper.getNotificationChannel(PKG_O, 3, "b", false)
+ .isImportanceLockedByOEM());
+ assertTrue(mHelper.getNotificationChannel(PKG_O, 30, "c", false)
+ .isImportanceLockedByOEM());
+ }
+
+ @Test
public void testLockChannelsForOEM_channelSpecific_clearData() {
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.getImportance(PKG_O, UID_O);
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index b406da3c9ba9..9f16543c410e 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -2137,7 +2137,13 @@ public final class Call {
/**
* Obtains a list of canned, pre-configured message responses to present to the user as
- * ways of rejecting this {@code Call} using via a text message.
+ * ways of rejecting an incoming {@code Call} using via a text message.
+ * <p>
+ * <em>Note:</em> Since canned responses may be loaded from the file system, they are not
+ * guaranteed to be present when this {@link Call} is first added to the {@link InCallService}
+ * via {@link InCallService#onCallAdded(Call)}. The callback
+ * {@link Call.Callback#onCannedTextResponsesLoaded(Call, List)} will be called when/if canned
+ * responses for the call become available.
*
* @see #reject(boolean, String)
*
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 4d9311c282f7..49f183151e27 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -64,7 +64,7 @@ import com.android.internal.telecom.ICallScreeningService;
* </li>
* </ol>
* <p>
- * <h2>Becoming the {@link CallScreeningService}</h2>
+ * <h2>Becoming the CallScreeningService</h2>
* Telecom will bind to a single app chosen by the user which implements the
* {@link CallScreeningService} API when there are new incoming and outgoing calls.
* <p>
@@ -90,7 +90,27 @@ import com.android.internal.telecom.ICallScreeningService;
* }
* }
* }
+ * }
* </pre>
+ *
+ * <h2>CallScreeningService Lifecycle</h2>
+ *
+ * The framework binds to the {@link CallScreeningService} implemented by the user-chosen app
+ * filling the {@link android.app.role.RoleManager#ROLE_CALL_SCREENING} role when incoming calls are
+ * received (prior to ringing) and when outgoing calls are placed. The platform calls the
+ * {@link #onScreenCall(Call.Details)} method to provide your service with details about the call.
+ * <p>
+ * For incoming calls, the {@link CallScreeningService} must call
+ * {@link #respondToCall(Call.Details, CallResponse)} within 5 seconds of being bound to indicate to
+ * the platform whether the call should be blocked or not. Your app must do this even if it is
+ * primarily performing caller ID operations and not screening calls. It is important to perform
+ * screening operations in a timely matter as the user's device will not begin ringing until the
+ * response is received (or the timeout is hit). A {@link CallScreeningService} may choose to
+ * perform local database lookups to help determine if a call should be screened or not; care should
+ * be taken to ensure the timeout is not repeatedly hit, causing delays in the incoming call flow.
+ * <p>
+ * If your app provides a caller ID experience, it should launch an activity to show the caller ID
+ * information from {@link #onScreenCall(Call.Details)}.
*/
public abstract class CallScreeningService extends Service {
/**
@@ -339,7 +359,7 @@ public abstract class CallScreeningService extends Service {
}
/**
- * Called when a new incoming or outgoing call is added which is not in the user's contact list.
+ * Called when a new incoming or outgoing call is added.
* <p>
* A {@link CallScreeningService} must indicate whether an incoming call is allowed or not by
* calling
@@ -347,21 +367,32 @@ public abstract class CallScreeningService extends Service {
* Your app can tell if a call is an incoming call by checking to see if
* {@link Call.Details#getCallDirection()} is {@link Call.Details#DIRECTION_INCOMING}.
* <p>
- * Note: The {@link Call.Details} instance provided to a call screening service will only have
- * the following properties set. The rest of the {@link Call.Details} properties will be set to
- * their default value or {@code null}.
+ * <em>Note:</em> A {@link CallScreeningService} must respond to a call within 5 seconds. After
+ * this time, the framework will unbind from the {@link CallScreeningService} and ignore its
+ * response.
+ * <p>
+ * <em>Note:</em> The {@link Call.Details} instance provided to a call screening service will
+ * only have the following properties set. The rest of the {@link Call.Details} properties will
+ * be set to their default value or {@code null}.
* <ul>
* <li>{@link Call.Details#getCallDirection()}</li>
+ * <li>{@link Call.Details#getCallerNumberVerificationStatus()}</li>
* <li>{@link Call.Details#getConnectTimeMillis()}</li>
* <li>{@link Call.Details#getCreationTimeMillis()}</li>
* <li>{@link Call.Details#getHandle()}</li>
- * <li>{@link Call.Details#getHandlePresentation()}</li>
* </ul>
* <p>
* Only calls where the {@link Call.Details#getHandle() handle} {@link Uri#getScheme() scheme}
* is {@link PhoneAccount#SCHEME_TEL} are passed for call
* screening. Further, only calls which are not in the user's contacts are passed for
- * screening. For outgoing calls, no post-dial digits are passed.
+ * screening, unless the {@link CallScreeningService} has been granted
+ * {@link Manifest.permission#READ_CONTACTS} permission by the user. For outgoing calls, no
+ * post-dial digits are passed.
+ * <p>
+ * Calls with a {@link Call.Details#getHandlePresentation()} of
+ * {@link TelecomManager#PRESENTATION_RESTRICTED}, {@link TelecomManager#PRESENTATION_UNKNOWN}
+ * or {@link TelecomManager#PRESENTATION_PAYPHONE} presentation are not provided to the
+ * {@link CallScreeningService}.
*
* @param callDetails Information about a new call, see {@link Call.Details}.
*/
@@ -376,6 +407,13 @@ public abstract class CallScreeningService extends Service {
* <p>
* Calls to this method are ignored unless the {@link Call.Details#getCallDirection()} is
* {@link Call.Details#DIRECTION_INCOMING}.
+ * <p>
+ * For incoming calls, a {@link CallScreeningService} MUST call this method within 5 seconds of
+ * {@link #onScreenCall(Call.Details)} being invoked by the platform.
+ * <p>
+ * Calls which are blocked/rejected will be logged to the system call log with a call type of
+ * {@link android.provider.CallLog.Calls#BLOCKED_TYPE} and
+ * {@link android.provider.CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE} block reason.
*
* @param callDetails The call to allow.
* <p>
diff --git a/telephony/java/android/telephony/BinderCacheManager.java b/telephony/java/android/telephony/BinderCacheManager.java
new file mode 100644
index 000000000000..0d3e2fe7591c
--- /dev/null
+++ b/telephony/java/android/telephony/BinderCacheManager.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Keeps track of the connection to a Binder node, refreshes the cache if the node dies, and lets
+ * interested parties register listeners on the node to be notified when the node has died via the
+ * registered {@link Runnable}.
+ * @param <T> The IInterface representing the Binder type that this manager will be managing the
+ * cache of.
+ * @hide
+ */
+public class BinderCacheManager<T extends IInterface> {
+
+ /**
+ * Factory class for creating new IInterfaces in the case that {@link #getBinder()} is
+ * called and there is no active binder available.
+ * @param <T> The IInterface that should be cached and returned to the caller when
+ * {@link #getBinder()} is called until the Binder node dies.
+ */
+ public interface BinderInterfaceFactory<T> {
+ /**
+ * @return A new instance of the Binder node, which will be cached until it dies.
+ */
+ T create();
+ }
+
+ /**
+ * Tracks the cached Binder node as well as the listeners that were associated with that
+ * Binder node during its lifetime. If the Binder node dies, the listeners will be called and
+ * then this tracker will be unlinked and cleaned up.
+ */
+ private class BinderDeathTracker implements IBinder.DeathRecipient {
+
+ private final T mConnection;
+ private final HashMap<Object, Runnable> mListeners = new HashMap<>();
+
+ /**
+ * Create a tracker to cache the Binder node and add the ability to listen for the cached
+ * interface's death.
+ */
+ BinderDeathTracker(@NonNull T connection) {
+ mConnection = connection;
+ try {
+ mConnection.asBinder().linkToDeath(this, 0 /*flags*/);
+ } catch (RemoteException e) {
+ // isAlive will return false.
+ }
+ }
+
+ public boolean addListener(Object key, Runnable r) {
+ synchronized (mListeners) {
+ if (!isAlive()) return false;
+ mListeners.put(key, r);
+ return true;
+ }
+ }
+
+ public void removeListener(Object runnableKey) {
+ synchronized (mListeners) {
+ mListeners.remove(runnableKey);
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ ArrayList<Runnable> listeners;
+ synchronized (mListeners) {
+ listeners = new ArrayList<>(mListeners.values());
+ mListeners.clear();
+ try {
+ mConnection.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ } catch (NoSuchElementException e) {
+ // No need to worry about this, this means the death recipient was never linked.
+ }
+ }
+ listeners.forEach(Runnable::run);
+ }
+
+ /**
+ * @return The cached Binder.
+ */
+ public T getConnection() {
+ return mConnection;
+ }
+
+ /**
+ * @return true if the cached Binder is alive at the time of calling, false otherwise.
+ */
+ public boolean isAlive() {
+ return mConnection.asBinder().isBinderAlive();
+ }
+ }
+
+ private final BinderInterfaceFactory<T> mBinderInterfaceFactory;
+ private final AtomicReference<BinderDeathTracker> mCachedConnection;
+
+ /**
+ * Create a new instance, which manages a cached IInterface and creates new ones using the
+ * provided factory when the cached IInterface dies.
+ * @param factory The factory used to create new Instances of the cached IInterface when it
+ * dies.
+ */
+ public BinderCacheManager(BinderInterfaceFactory<T> factory) {
+ mBinderInterfaceFactory = factory;
+ mCachedConnection = new AtomicReference<>();
+ }
+
+ /**
+ * Get the binder node connection and add a Runnable to be run if this Binder dies. Once this
+ * Runnable is run, the Runnable itself is discarded and must be added again.
+ * <p>
+ * Note: There should be no assumptions here as to which Thread this Runnable is called on. If
+ * the Runnable should be called on a specific thread, it should be up to the caller to handle
+ * that in the runnable implementation.
+ * @param runnableKey The Key associated with this runnable so that it can be removed later
+ * using {@link #removeRunnable(Object)} if needed.
+ * @param deadRunnable The runnable that will be run if the cached Binder node dies.
+ * @return T if the runnable was added or {@code null} if the connection is not alive right now
+ * and the associated runnable was never added.
+ */
+ public T listenOnBinder(Object runnableKey, Runnable deadRunnable) {
+ if (runnableKey == null || deadRunnable == null) return null;
+ BinderDeathTracker tracker = getTracker();
+ if (tracker == null) return null;
+
+ boolean addSucceeded = tracker.addListener(runnableKey, deadRunnable);
+ return addSucceeded ? tracker.getConnection() : null;
+ }
+
+ /**
+ * @return The cached Binder node. May return null if the requested Binder node is not currently
+ * available.
+ */
+ public T getBinder() {
+ BinderDeathTracker tracker = getTracker();
+ return (tracker != null) ? tracker.getConnection() : null;
+ }
+
+ /**
+ * Removes a previously registered runnable associated with the returned cached Binder node
+ * using the key it was registered with in {@link #listenOnBinder} if the runnable still exists.
+ * @param runnableKey The key that was used to register the Runnable earlier.
+ * @return The cached Binder node that the runnable used to registered to or null if the cached
+ * Binder node is not alive anymore.
+ */
+ public T removeRunnable(Object runnableKey) {
+ if (runnableKey == null) return null;
+ BinderDeathTracker tracker = getTracker();
+ if (tracker == null) return null;
+ tracker.removeListener(runnableKey);
+ return tracker.getConnection();
+ }
+
+ /**
+ * @return The BinderDeathTracker container, which contains the cached IInterface instance or
+ * null if it is not available right now.
+ */
+ private BinderDeathTracker getTracker() {
+ return mCachedConnection.updateAndGet((oldVal) -> {
+ BinderDeathTracker tracker = oldVal;
+ // Update cache if no longer alive. BinderDied will eventually be called on the tracker,
+ // which will call listeners & clean up.
+ if (tracker == null || !tracker.isAlive()) {
+ T binder = mBinderInterfaceFactory.create();
+ tracker = (binder != null) ? new BinderDeathTracker(binder) : null;
+
+ }
+ return (tracker != null && tracker.isAlive()) ? tracker : null;
+ });
+ }
+
+}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index d6ce40c24b78..af49dc4bb9b3 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2091,17 +2091,25 @@ public final class SmsManager {
}
/**
- * Gets the total capacity of SMS storage on RUIM and SIM cards
- * <p>
- * This is the number of 176 byte EF-SMS records which can be stored on the RUIM or SIM card.
+ * Gets the total capacity of SMS storage on the SIM card.
+ *
* <p>
- * See 3GPP TS 31.102 - 4.2.25 - EF-SMS for more information
+ * This is the number of 176 byte EF-SMS records which can be stored on the SIM card.
+ * See 3GPP TS 31.102 - 4.2.25 - EF-SMS for more information.
+ * </p>
*
- * @return the total number of SMS records which can be stored on the RUIM or SIM cards.
- * @hide
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this method will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation
+ * is performed on the correct subscription.
+ * </p>
+ *
+ * @return the total number of SMS records which can be stored on the SIM card.
*/
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getSmsCapacityOnIcc() {
int ret = 0;
try {
@@ -2110,7 +2118,7 @@ public final class SmsManager {
ret = iccISms.getSmsCapacityOnIccForSubscriber(getSubscriptionId());
}
} catch (RemoteException ex) {
- //ignore it
+ throw new RuntimeException(ex);
}
return ret;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 66eadb5f71e0..26b669a70cf8 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -85,8 +85,6 @@ import android.telephony.emergency.EmergencyNumber;
import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.aidl.IImsConfig;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -94,7 +92,6 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
-import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CellNetworkScanResult;
@@ -7309,80 +7306,6 @@ public class TelephonyManager {
}
/**
- * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id and MMTel
- * feature or {@link null} if the service is not available. If an MMTelFeature is available, the
- * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
- * @param slotIndex The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
- * @param callback Listener that will send updates to ImsManager when there are updates to
- * ImsServiceController.
- * @return {@link IImsMmTelFeature} interface for the feature specified or {@code null} if
- * it is unavailable.
- * @hide
- */
- public @Nullable IImsMmTelFeature getImsMmTelFeatureAndListen(int slotIndex,
- IImsServiceFeatureCallback callback) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getMmTelFeatureAndListen(slotIndex, callback);
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "getImsMmTelFeatureAndListen, RemoteException: "
- + e.getMessage());
- }
- return null;
- }
-
- /**
- * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id and RCS
- * feature for emergency calling or {@link null} if the service is not available. If an
- * RcsFeature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
- * listener for feature updates.
- * @param slotIndex The SIM slot that we are requesting the {@link IImsRcsFeature} for.
- * @param callback Listener that will send updates to ImsManager when there are updates to
- * ImsServiceController.
- * @return {@link IImsRcsFeature} interface for the feature specified or {@code null} if
- * it is unavailable.
- * @hide
- */
- public @Nullable IImsRcsFeature getImsRcsFeatureAndListen(int slotIndex,
- IImsServiceFeatureCallback callback) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getRcsFeatureAndListen(slotIndex, callback);
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "getImsRcsFeatureAndListen, RemoteException: "
- + e.getMessage());
- }
- return null;
- }
-
- /**
- * Unregister a IImsServiceFeatureCallback previously associated with an ImsFeature through
- * {@link #getImsMmTelFeatureAndListen(int, IImsServiceFeatureCallback)} or
- * {@link #getImsRcsFeatureAndListen(int, IImsServiceFeatureCallback)}.
- * @param slotIndex The SIM slot associated with the callback.
- * @param featureType The {@link android.telephony.ims.feature.ImsFeature.FeatureType}
- * associated with the callback.
- * @param callback The callback to be unregistered.
- * @hide
- */
- public void unregisterImsFeatureCallback(int slotIndex, int featureType,
- IImsServiceFeatureCallback callback) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.unregisterImsFeatureCallback(slotIndex, featureType, callback);
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "unregisterImsFeatureCallback, RemoteException: "
- + e.getMessage());
- }
- }
-
- /**
* @return the {@IImsRegistration} interface that corresponds with the slot index and feature.
* @param slotIndex The SIM slot corresponding to the ImsService ImsRegistration is active for.
* @param feature An integer indicating the feature that we wish to get the ImsRegistration for.
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index f6c14e67306b..ee2fce7e7dd5 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -59,6 +59,7 @@ import java.util.function.Consumer;
* manager.
*/
public class ImsMmTelManager implements RegistrationManager {
+ private static final String TAG = "ImsMmTelManager";
/**
* @hide
@@ -809,7 +810,7 @@ public class ImsMmTelManager implements RegistrationManager {
}
try {
- getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
+ iTelephony.isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
executor.execute(() -> callback.accept(result == 1));
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index da7311c08307..8a05bdfc8401 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -16,6 +16,7 @@
package android.telephony.ims;
+import android.annotation.LongDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Service;
@@ -41,6 +42,11 @@ import android.util.SparseArray;
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
* ImsService must register the service in their AndroidManifest to be detected by the framework.
@@ -98,6 +104,32 @@ public class ImsService extends Service {
private static final String LOG_TAG = "ImsService";
/**
+ * This ImsService supports the capability to place emergency calls over MMTEL.
+ * @hide This is encoded into the {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, but we will be
+ * adding other capabilities in a central location, so track this capability here as well.
+ */
+ public static final long CAPABILITY_EMERGENCY_OVER_MMTEL = 1 << 0;
+
+ /**
+ * @hide
+ */
+ @LongDef(flag = true,
+ prefix = "CAPABILITY_",
+ value = {
+ CAPABILITY_EMERGENCY_OVER_MMTEL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ImsServiceCapability {}
+
+ /**
+ * Used for logging purposes, see {@link #getCapabilitiesString(long)}
+ * @hide
+ */
+ private static final Map<Long, String> CAPABILITIES_LOG_MAP = new HashMap<Long, String>() {{
+ put(CAPABILITY_EMERGENCY_OVER_MMTEL, "EMERGENCY_OVER_MMTEL");
+ }};
+
+ /**
* The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
* @hide
*/
@@ -409,4 +441,30 @@ public class ImsService extends Service {
public ImsRegistrationImplBase getRegistration(int slotId) {
return new ImsRegistrationImplBase();
}
+
+ /**
+ * @return A string representation of the ImsService capabilties for logging.
+ * @hide
+ */
+ public static String getCapabilitiesString(@ImsServiceCapability long caps) {
+ StringBuffer result = new StringBuffer();
+ result.append("capabilities={ ");
+ // filter incrementally fills 0s from left to right. This is used to keep filtering out
+ // more bits in the long until the remaining leftmost bits are all zero.
+ long filter = 0xFFFFFFFFFFFFFFFFL;
+ // position of iterator to potentially print capability.
+ long i = 0;
+ while ((caps & filter) != 0 && i <= 63) {
+ long bitToCheck = (1L << i);
+ if ((caps & bitToCheck) != 0) {
+ result.append(CAPABILITIES_LOG_MAP.getOrDefault(bitToCheck, bitToCheck + "?"));
+ result.append(" ");
+ }
+ // shift left by one and fill in another 1 on the leftmost bit.
+ filter <<= 1;
+ i++;
+ }
+ result.append("}");
+ return result.toString();
+ }
} \ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
index 7bbe30a444b9..52464703c608 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
@@ -27,8 +27,11 @@ import com.android.ims.internal.IImsCallSession;
* See MmTelFeature#Listener for more information.
* {@hide}
*/
-oneway interface IImsMmTelListener {
+ // This interface is not considered oneway because we need to ensure that these operations are
+ // processed by telephony before the control flow returns to the ImsService to perform
+ // operations on the IImsCallSession.
+interface IImsMmTelListener {
void onIncomingCall(IImsCallSession c, in Bundle extras);
void onRejectedCall(in ImsCallProfile callProfile, in ImsReasonInfo reason);
- void onVoiceMessageCountUpdate(int count);
+ oneway void onVoiceMessageCountUpdate(int count);
}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index 9e461420e126..e01ea9179452 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -22,6 +22,8 @@ import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
+import com.android.ims.ImsFeatureContainer;
+import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.IIntegerConsumer;
/**
@@ -50,4 +52,8 @@ interface IImsRcsController {
void setUceSettingEnabled(int subId, boolean isEnabled);
void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c);
void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c);
+
+ // Internal commands that should not be made public
+ void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
+ void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback);
}
diff --git a/telephony/java/com/android/ims/ImsFeatureContainer.aidl b/telephony/java/com/android/ims/ImsFeatureContainer.aidl
new file mode 100644
index 000000000000..9706f20c59ca
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsFeatureContainer.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ims;
+
+parcelable ImsFeatureContainer; \ No newline at end of file
diff --git a/telephony/java/com/android/ims/ImsFeatureContainer.java b/telephony/java/com/android/ims/ImsFeatureContainer.java
new file mode 100644
index 000000000000..b259679ea1bf
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsFeatureContainer.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ims;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.feature.ImsFeature;
+
+import java.util.Objects;
+
+/**
+ * Contains an IBinder linking to the appropriate ImsFeature as well as the associated
+ * interfaces.
+ * @hide
+ */
+public final class ImsFeatureContainer implements Parcelable {
+ /**
+ * ImsFeature that is being tracked.
+ */
+ public final IBinder imsFeature;
+
+ /**
+ * IImsConfig interface that should be associated with the ImsFeature.
+ */
+ public final android.telephony.ims.aidl.IImsConfig imsConfig;
+
+ /**
+ * IImsRegistration interface that should be associated with this ImsFeature.
+ */
+ public final IImsRegistration imsRegistration;
+
+ /**
+ * State of the feature that is being tracked.
+ */
+ private @ImsFeature.ImsState int mState = ImsFeature.STATE_UNAVAILABLE;
+
+ /**
+ * Capabilities of this ImsService.
+ */
+ private @ImsService.ImsServiceCapability long mCapabilities;
+ /**
+ * Contains the ImsFeature IBinder as well as the ImsService interfaces associated with
+ * that feature.
+ * @param iFace IBinder connection to the ImsFeature.
+ * @param iConfig IImsConfig interface associated with the ImsFeature.
+ * @param iReg IImsRegistration interface associated with the ImsFeature
+ * @param initialCaps The initial capabilities that the ImsService supports.
+ */
+ public ImsFeatureContainer(@NonNull IBinder iFace, @NonNull IImsConfig iConfig,
+ @NonNull IImsRegistration iReg, long initialCaps) {
+ imsFeature = iFace;
+ imsConfig = iConfig;
+ imsRegistration = iReg;
+ mCapabilities = initialCaps;
+ }
+
+ /**
+ * Create an ImsFeatureContainer from a Parcel.
+ */
+ private ImsFeatureContainer(Parcel in) {
+ imsFeature = in.readStrongBinder();
+ imsConfig = IImsConfig.Stub.asInterface(in.readStrongBinder());
+ imsRegistration = IImsRegistration.Stub.asInterface(in.readStrongBinder());
+ mState = in.readInt();
+ mCapabilities = in.readLong();
+ }
+
+ /**
+ * @return the capabilties that are associated with the ImsService that this ImsFeature
+ * belongs to.
+ */
+ public @ImsService.ImsServiceCapability long getCapabilities() {
+ return mCapabilities;
+ }
+
+ /**
+ * Update the capabilities that are associated with the ImsService that this ImsFeature
+ * belongs to.
+ */
+ public void setCapabilities(@ImsService.ImsServiceCapability long caps) {
+ mCapabilities = caps;
+ }
+
+ /**
+ * @return The state of the ImsFeature.
+ */
+ public @ImsFeature.ImsState int getState() {
+ return mState;
+ }
+
+ /**
+ * Set the state that is associated with the ImsService that this ImsFeature
+ * belongs to.
+ */
+ public void setState(@ImsFeature.ImsState int state) {
+ mState = state;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ImsFeatureContainer that = (ImsFeatureContainer) o;
+ return imsFeature.equals(that.imsFeature) &&
+ imsConfig.equals(that.imsConfig) &&
+ imsRegistration.equals(that.imsRegistration) &&
+ mState == that.getState() &&
+ mCapabilities == that.getCapabilities();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(imsFeature, imsConfig, imsRegistration, mState, mCapabilities);
+ }
+
+ @Override
+ public String toString() {
+ return "FeatureContainer{" +
+ "imsFeature=" + imsFeature +
+ ", imsConfig=" + imsConfig +
+ ", imsRegistration=" + imsRegistration +
+ ", state=" + ImsFeature.STATE_LOG_MAP.get(mState) +
+ ", capabilities = " + ImsService.getCapabilitiesString(mCapabilities) +
+ '}';
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(imsFeature);
+ dest.writeStrongInterface(imsConfig);
+ dest.writeStrongInterface(imsRegistration);
+ dest.writeInt(mState);
+ dest.writeLong(mCapabilities);
+ }
+
+
+ public static final Creator<ImsFeatureContainer> CREATOR = new Creator<ImsFeatureContainer>() {
+ @Override
+ public ImsFeatureContainer createFromParcel(Parcel source) {
+ return new ImsFeatureContainer(source);
+ }
+
+ @Override
+ public ImsFeatureContainer[] newArray(int size) {
+ return new ImsFeatureContainer[size];
+ }
+ };
+}
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
index 9a9cf5325310..f5f67bd36ec3 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
@@ -16,13 +16,18 @@
package com.android.ims.internal;
+import com.android.ims.ImsFeatureContainer;
/**
- * Interface from ImsResolver to ImsServiceProxy in ImsManager.
- * Callback to ImsManager when a feature changes in the ImsServiceController.
+ * Interface from ImsResolver to FeatureConnections.
+ * Callback to FeatureConnections when a feature's status changes.
* {@hide}
*/
oneway interface IImsServiceFeatureCallback {
- void imsFeatureCreated(int slotId, int feature);
- void imsFeatureRemoved(int slotId, int feature);
- void imsStatusChanged(int slotId, int feature, int status);
+ void imsFeatureCreated(in ImsFeatureContainer feature);
+ // Reason defined in FeatureConnector.UnavailableReason
+ void imsFeatureRemoved(int reason);
+ // Status defined in ImsFeature.ImsState.
+ void imsStatusChanged(int status);
+ //Capabilities defined in ImsService.ImsServiceCapability
+ void updateCapabilities(long capabilities);
} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 659d9cd38faf..934103ebe2b6 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -828,22 +828,14 @@ interface ITelephony {
* as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
* interface.
*/
- IImsMmTelFeature getMmTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
-
- /**
- * Get IImsRcsFeature binder from ImsResolver that corresponds to the subId and RCS feature
- * as well as registering the RcsFeature for callbacks using the IImsServiceFeatureCallback
- * interface.
- */
- IImsRcsFeature getRcsFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
+ void registerMmTelFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
/**
* Unregister a callback that was previously registered through
- * {@link #getMmTelFeatureAndListen} or {@link #getRcsFeatureAndListen}. This should always be
- * called when the callback is no longer being used.
+ * {@link #registerMmTelFeatureCallback}. This should always be called when the callback is no
+ * longer being used.
*/
- void unregisterImsFeatureCallback(int slotId, int featureType,
- in IImsServiceFeatureCallback callback);
+ void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback);
/**
* Returns the IImsRegistration associated with the slot and feature specified.
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 2be4ae6bb214..a23df920b396 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -29,7 +29,12 @@ java_test_host {
name: "StagedRollbackTest",
srcs: ["StagedRollbackTest/src/**/*.java"],
libs: ["tradefed"],
- static_libs: ["testng", "compatibility-tradefed", "RollbackTestLib"],
+ static_libs: [
+ "compatibility-tradefed",
+ "frameworks-base-hostutils",
+ "RollbackTestLib",
+ "testng",
+ ],
test_suites: ["general-tests"],
test_config: "StagedRollbackTest.xml",
data: [":com.android.apex.apkrollback.test_v1"],
@@ -39,7 +44,7 @@ java_test_host {
name: "NetworkStagedRollbackTest",
srcs: ["NetworkStagedRollbackTest/src/**/*.java"],
libs: ["tradefed"],
- static_libs: ["RollbackTestLib"],
+ static_libs: ["RollbackTestLib", "frameworks-base-hostutils"],
test_suites: ["general-tests"],
test_config: "NetworkStagedRollbackTest.xml",
}
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 1e286bb15c49..30f3f185203c 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -28,6 +28,7 @@ java_test_host {
"testng",
"compatibility-tradefed",
"module_test_util",
+ "frameworks-base-hostutils",
],
data: [
":com.android.apex.cts.shim.v2_prebuilt",
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 86d5fd80c108..e259c9efbfcd 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.ddmlib.Log;
+import com.android.tests.rollback.host.AbandonSessionsRule;
import com.android.tests.util.ModuleTestUtils;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -29,6 +30,7 @@ import com.android.tradefed.util.ProcessInfo;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,7 +41,9 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
private static final String TAG = StagedInstallInternalTest.class.getSimpleName();
private static final long SYSTEM_SERVER_TIMEOUT_MS = 60 * 1000;
- private boolean mWasRoot = false;
+
+ @Rule
+ public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this);
private static final String SHIM_V2 = "com.android.apex.cts.shim.v2.apex";
private static final String APK_A = "TestAppAv1.apk";
@@ -71,21 +75,11 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
@Before
public void setUp() throws Exception {
- mWasRoot = getDevice().isAdbRoot();
- if (!mWasRoot) {
- getDevice().enableAdbRoot();
- }
cleanUp();
- // Abandon all staged sessions
- getDevice().executeShellCommand("pm install-abandon $(pm get-stagedsessions --only-ready "
- + "--only-parent --only-sessionid)");
}
@After
public void tearDown() throws Exception {
- if (!mWasRoot) {
- getDevice().disableAdbRoot();
- }
cleanUp();
}
@@ -150,8 +144,11 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
private void restartSystemServer() throws Exception {
// Restart the system server
- long oldStartTime = getDevice().getProcessByName("system_server").getStartTime();
+ final long oldStartTime = getDevice().getProcessByName("system_server").getStartTime();
+
+ getDevice().enableAdbRoot(); // Need root to restart system server
assertThat(getDevice().executeShellCommand("am restart")).contains("Restart the system");
+ getDevice().disableAdbRoot();
// Wait for new system server process to start
long start = System.currentTimeMillis();
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/android/net/util/IpUtilsTest.java b/tests/net/java/android/net/util/IpUtilsTest.java
deleted file mode 100644
index 193d85d0013a..000000000000
--- a/tests/net/java/android/net/util/IpUtilsTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.util;
-
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class IpUtilsTest {
-
- private static final int IPV4_HEADER_LENGTH = 20;
- private static final int IPV6_HEADER_LENGTH = 40;
- private static final int TCP_HEADER_LENGTH = 20;
- private static final int UDP_HEADER_LENGTH = 8;
- private static final int IP_CHECKSUM_OFFSET = 10;
- private static final int TCP_CHECKSUM_OFFSET = 16;
- private static final int UDP_CHECKSUM_OFFSET = 6;
-
- private int getUnsignedByte(ByteBuffer buf, int offset) {
- return buf.get(offset) & 0xff;
- }
-
- private int getChecksum(ByteBuffer buf, int offset) {
- return getUnsignedByte(buf, offset) * 256 + getUnsignedByte(buf, offset + 1);
- }
-
- private void assertChecksumEquals(int expected, short actual) {
- assertEquals(Integer.toHexString(expected), Integer.toHexString(actual & 0xffff));
- }
-
- // Generate test packets using Python code like this::
- //
- // from scapy import all as scapy
- //
- // def JavaPacketDefinition(bytes):
- // out = " ByteBuffer packet = ByteBuffer.wrap(new byte[] {\n "
- // for i in xrange(len(bytes)):
- // out += "(byte) 0x%02x" % ord(bytes[i])
- // if i < len(bytes) - 1:
- // if i % 4 == 3:
- // out += ",\n "
- // else:
- // out += ", "
- // out += "\n });"
- // return out
- //
- // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2") /
- // scapy.UDP(sport=12345, dport=7) /
- // "hello")
- // print JavaPacketDefinition(str(packet))
-
- @Test
- public void testIpv6TcpChecksum() throws Exception {
- // packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80) /
- // scapy.TCP(sport=12345, dport=7,
- // seq=1692871236, ack=128376451, flags=16,
- // window=32768) /
- // "hello, world")
- ByteBuffer packet = ByteBuffer.wrap(new byte[] {
- (byte) 0x68, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x20, (byte) 0x06, (byte) 0x40,
- (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
- (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
- (byte) 0x30, (byte) 0x39, (byte) 0x00, (byte) 0x07,
- (byte) 0x64, (byte) 0xe7, (byte) 0x2a, (byte) 0x44,
- (byte) 0x07, (byte) 0xa6, (byte) 0xde, (byte) 0x83,
- (byte) 0x50, (byte) 0x10, (byte) 0x80, (byte) 0x00,
- (byte) 0xee, (byte) 0x71, (byte) 0x00, (byte) 0x00,
- (byte) 0x68, (byte) 0x65, (byte) 0x6c, (byte) 0x6c,
- (byte) 0x6f, (byte) 0x2c, (byte) 0x20, (byte) 0x77,
- (byte) 0x6f, (byte) 0x72, (byte) 0x6c, (byte) 0x64
- });
-
- // Check that a valid packet has checksum 0.
- int transportLen = packet.limit() - IPV6_HEADER_LENGTH;
- assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
-
- // Check that we can calculate the checksum from scratch.
- int sumOffset = IPV6_HEADER_LENGTH + TCP_CHECKSUM_OFFSET;
- int sum = getUnsignedByte(packet, sumOffset) * 256 + getUnsignedByte(packet, sumOffset + 1);
- assertEquals(0xee71, sum);
-
- packet.put(sumOffset, (byte) 0);
- packet.put(sumOffset + 1, (byte) 0);
- assertChecksumEquals(sum, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
-
- // Check that writing the checksum back into the packet results in a valid packet.
- packet.putShort(
- sumOffset,
- IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
- assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
- }
-
- @Test
- public void testIpv4UdpChecksum() {
- // packet = (scapy.IP(src="192.0.2.1", dst="192.0.2.2", tos=0x40) /
- // scapy.UDP(sport=32012, dport=4500) /
- // "\xff")
- ByteBuffer packet = ByteBuffer.wrap(new byte[] {
- (byte) 0x45, (byte) 0x40, (byte) 0x00, (byte) 0x1d,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
- (byte) 0x40, (byte) 0x11, (byte) 0xf6, (byte) 0x8b,
- (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01,
- (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02,
- (byte) 0x7d, (byte) 0x0c, (byte) 0x11, (byte) 0x94,
- (byte) 0x00, (byte) 0x09, (byte) 0xee, (byte) 0x36,
- (byte) 0xff
- });
-
- // Check that a valid packet has IP checksum 0 and UDP checksum 0xffff (0 is not a valid
- // UDP checksum, so the udpChecksum rewrites 0 to 0xffff).
- assertEquals(0, IpUtils.ipChecksum(packet, 0));
- assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
-
- // Check that we can calculate the checksums from scratch.
- final int ipSumOffset = IP_CHECKSUM_OFFSET;
- final int ipSum = getChecksum(packet, ipSumOffset);
- assertEquals(0xf68b, ipSum);
-
- packet.put(ipSumOffset, (byte) 0);
- packet.put(ipSumOffset + 1, (byte) 0);
- assertChecksumEquals(ipSum, IpUtils.ipChecksum(packet, 0));
-
- final int udpSumOffset = IPV4_HEADER_LENGTH + UDP_CHECKSUM_OFFSET;
- final int udpSum = getChecksum(packet, udpSumOffset);
- assertEquals(0xee36, udpSum);
-
- packet.put(udpSumOffset, (byte) 0);
- packet.put(udpSumOffset + 1, (byte) 0);
- assertChecksumEquals(udpSum, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
-
- // Check that writing the checksums back into the packet results in a valid packet.
- packet.putShort(ipSumOffset, IpUtils.ipChecksum(packet, 0));
- packet.putShort(udpSumOffset, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
- assertEquals(0, IpUtils.ipChecksum(packet, 0));
- assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
- }
-}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index f2b7c1ea2ba7..1df510987d25 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -1263,7 +1263,7 @@ public class VpnTest {
}
@Override
- public boolean checkInterfacePresent(final Vpn vpn, final String iface) {
+ public boolean isInterfacePresent(final Vpn vpn, final String iface) {
return true;
}
}
diff --git a/tests/RollbackTest/lib/src/com/android/tests/rollback/host/AbandonSessionsRule.java b/tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java
index b08621314ee0..b08621314ee0 100644
--- a/tests/RollbackTest/lib/src/com/android/tests/rollback/host/AbandonSessionsRule.java
+++ b/tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java
diff --git a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl
index cf2cb4ae5eb4..57055f78d03d 100644
--- a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl
+++ b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi.p2p.servicediscovery;
+package android.net.wifi.p2p.nsd;
parcelable WifiP2pServiceInfo;
diff --git a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl
index d5a1e8f505a9..e4d28bb2d39f 100644
--- a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl
+++ b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi.p2p.servicediscovery;
+package android.net.wifi.p2p.nsd;
parcelable WifiP2pServiceRequest;
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index e253ae25659e..eef08b54f570 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -70,7 +70,6 @@ rule android.net.util.NetworkConstants* com.android.wifi.x.@0
rule android.net.util.InterfaceParams* com.android.wifi.x.@0
rule android.net.util.SharedLog* com.android.wifi.x.@0
rule android.net.util.NetUtils* com.android.wifi.x.@0
-rule android.net.util.IpUtils* com.android.wifi.x.@0
rule androidx.annotation.** com.android.wifi.x.@0