Merge "Replace CM#isNetworkSupported() with checking FEATURE_TELEPHONY"
diff --git a/Android.bp b/Android.bp
index c9ed7ed..4709323 100644
--- a/Android.bp
+++ b/Android.bp
@@ -306,8 +306,8 @@
genrule {
name: "statslog-telephony-common-java-gen",
tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --java $(out) --module telephony_common"
- + " --javaPackage com.android.internal.telephony --javaClass TelephonyCommonStatsLog",
+ cmd: "$(location stats-log-api-gen) --java $(out) --module telephony_common" +
+ " --javaPackage com.android.internal.telephony --javaClass TelephonyCommonStatsLog",
out: ["com/android/internal/telephony/TelephonyCommonStatsLog.java"],
}
@@ -607,7 +607,6 @@
// TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly.
"gps_debug.conf",
"icu4j-platform-compat-config",
- "libcore-platform-compat-config",
"protolog.conf.json.gz",
"services-platform-compat-config",
"documents-ui-compat-config",
@@ -687,7 +686,7 @@
name: "statslog-framework-java-gen",
tools: ["stats-log-api-gen"],
cmd: "$(location stats-log-api-gen) --java $(out) --module framework" +
- " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
+ " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
out: ["com/android/internal/util/FrameworkStatsLog.java"],
}
@@ -788,7 +787,7 @@
java_library {
name: "framework-annotations-lib",
- srcs: [ ":framework-annotations" ],
+ srcs: [":framework-annotations"],
sdk_version: "core_current",
}
@@ -1015,7 +1014,6 @@
},
}
-
// This is the full proto version of libplatformprotos. It may only
// be used by test code that is not shipped on the device.
cc_library {
@@ -1176,7 +1174,7 @@
"core/java/android/os/RemoteException.java",
"core/java/android/util/AndroidException.java",
],
- libs: [ "unsupportedappusage" ],
+ libs: ["unsupportedappusage"],
dxflags: ["--core-library"],
installable: false,
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 24b8055..a3fa8ac 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -1006,6 +1006,41 @@
mJobId = jobId;
}
+ /**
+ * Creates a new Builder of JobInfo from an existing instance.
+ * @hide
+ */
+ public Builder(@NonNull JobInfo job) {
+ mJobId = job.getId();
+ mJobService = job.getService();
+ mExtras = job.getExtras();
+ mTransientExtras = job.getTransientExtras();
+ mClipData = job.getClipData();
+ mClipGrantFlags = job.getClipGrantFlags();
+ mPriority = job.getPriority();
+ mFlags = job.getFlags();
+ mConstraintFlags = job.getConstraintFlags();
+ mNetworkRequest = job.getRequiredNetwork();
+ mNetworkDownloadBytes = job.getEstimatedNetworkDownloadBytes();
+ mNetworkUploadBytes = job.getEstimatedNetworkUploadBytes();
+ mTriggerContentUris = job.getTriggerContentUris() != null
+ ? new ArrayList<>(Arrays.asList(job.getTriggerContentUris())) : null;
+ mTriggerContentUpdateDelay = job.getTriggerContentUpdateDelay();
+ mTriggerContentMaxDelay = job.getTriggerContentMaxDelay();
+ mIsPersisted = job.isPersisted();
+ mMinLatencyMillis = job.getMinLatencyMillis();
+ mMaxExecutionDelayMillis = job.getMaxExecutionDelayMillis();
+ mIsPeriodic = job.isPeriodic();
+ mHasEarlyConstraint = job.hasEarlyConstraint();
+ mHasLateConstraint = job.hasLateConstraint();
+ mIntervalMillis = job.getIntervalMillis();
+ mFlexMillis = job.getFlexMillis();
+ mInitialBackoffMillis = job.getInitialBackoffMillis();
+ // mBackoffPolicySet isn't set but it's fine since this is copying from an already valid
+ // job.
+ mBackoffPolicy = job.getBackoffPolicy();
+ }
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Builder setPriority(int priority) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index d7be259..ea8e7bc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -28,6 +28,7 @@
import android.content.ClipData;
import android.content.ComponentName;
import android.net.Network;
+import android.net.NetworkRequest;
import android.net.Uri;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -35,6 +36,7 @@
import android.text.format.DateFormat;
import android.util.ArraySet;
import android.util.Pair;
+import android.util.Range;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -52,6 +54,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.function.Predicate;
/**
@@ -486,8 +489,15 @@
// Later, when we check if a given network satisfies the required
// network, we need to know the UID that is requesting it, so push
// our source UID into place.
- job.getRequiredNetwork().networkCapabilities.setSingleUid(this.sourceUid);
+ final JobInfo.Builder builder = new JobInfo.Builder(job);
+ final NetworkRequest.Builder requestBuilder =
+ new NetworkRequest.Builder(job.getRequiredNetwork());
+ requestBuilder.setUids(
+ Collections.singleton(new Range<Integer>(this.sourceUid, this.sourceUid)));
+ builder.setRequiredNetwork(requestBuilder.build());
+ job = builder.build();
}
+
final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class);
mHasMediaBackupExemption = !job.hasLateConstraint() && exemptedMediaUrisOnly
&& requiresNetwork && this.sourcePackageName.equals(jsi.getMediaBackupPackage());
diff --git a/core/api/current.txt b/core/api/current.txt
index 07bebbe..15dfc51 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25723,7 +25723,7 @@
public abstract static class VcnManager.VcnStatusCallback {
ctor public VcnManager.VcnStatusCallback();
method public abstract void onGatewayConnectionError(@NonNull int[], int, @Nullable Throwable);
- method public abstract void onVcnStatusChanged(int);
+ method public abstract void onStatusChanged(int);
}
}
@@ -34219,6 +34219,9 @@
method public static android.net.Uri getUriForSubscriptionIdAndField(int, String);
field public static final String AUTHORITY = "service-state";
field public static final android.net.Uri CONTENT_URI;
+ field public static final String DATA_NETWORK_TYPE = "data_network_type";
+ field public static final String DATA_REG_STATE = "data_reg_state";
+ field public static final String DUPLEX_MODE = "duplex_mode";
field public static final String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
field public static final String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
field public static final String VOICE_REG_STATE = "voice_reg_state";
@@ -40662,7 +40665,6 @@
method public static int[] calculateLength(String, boolean);
method @Deprecated public static android.telephony.SmsMessage createFromPdu(byte[]);
method public static android.telephony.SmsMessage createFromPdu(byte[], String);
- method @Nullable public static android.telephony.SmsMessage createSmsSubmitPdu(@NonNull byte[], boolean);
method public String getDisplayMessageBody();
method public String getDisplayOriginatingAddress();
method public String getEmailBody();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 92c18c6..86f1eae 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11745,6 +11745,7 @@
method @Nullable public android.telephony.ims.RcsContactPresenceTuple getCapabilityTuple(@NonNull String);
method @NonNull public java.util.List<android.telephony.ims.RcsContactPresenceTuple> getCapabilityTuples();
method @NonNull public android.net.Uri getContactUri();
+ method @NonNull public java.util.Set<java.lang.String> getFeatureTags();
method public int getRequestResult();
method public int getSourceType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -11759,6 +11760,14 @@
field public static final int SOURCE_TYPE_NETWORK = 0; // 0x0
}
+ public static final class RcsContactUceCapability.OptionsBuilder {
+ ctor public RcsContactUceCapability.OptionsBuilder(@NonNull android.net.Uri);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.OptionsBuilder addFeatureTag(@NonNull String);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.OptionsBuilder addFeatureTags(@NonNull java.util.Set<java.lang.String>);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability build();
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.OptionsBuilder setRequestResult(int);
+ }
+
public static final class RcsContactUceCapability.PresenceBuilder {
ctor public RcsContactUceCapability.PresenceBuilder(@NonNull android.net.Uri, int, int);
method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuple(@NonNull android.telephony.ims.RcsContactPresenceTuple);
@@ -12052,7 +12061,7 @@
package android.telephony.ims.stub {
public interface CapabilityExchangeEventListener {
- method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException;
+ method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set<java.lang.String>, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException;
method public void onRequestPublishCapabilities(int) throws android.telephony.ims.ImsException;
method public void onUnpublish() throws android.telephony.ims.ImsException;
}
@@ -12248,7 +12257,7 @@
public class RcsCapabilityExchangeImplBase {
ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor);
method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback);
- method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback);
+ method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback);
method public void subscribeForCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback);
field public static final int COMMAND_CODE_FETCH_ERROR = 3; // 0x3
field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 11df058..1d094c3 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1652,6 +1652,7 @@
public class ServiceState implements android.os.Parcelable {
method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo);
method public int getDataNetworkType();
+ method public int getDataRegState();
method public void setCdmaSystemAndNetworkId(int, int);
method public void setCellBandwidths(int[]);
method public void setChannelNumber(int);
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 8672150..3c20dca 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -587,7 +587,7 @@
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
*/
public Builder setDeviceAddress(String deviceAddress) {
- return setDeviceAddress(mDeviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
+ return setDeviceAddress(deviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
}
/**
diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl
index 6a3cb42..5b79f73 100644
--- a/core/java/android/net/vcn/IVcnManagementService.aidl
+++ b/core/java/android/net/vcn/IVcnManagementService.aidl
@@ -29,7 +29,7 @@
*/
interface IVcnManagementService {
void setVcnConfig(in ParcelUuid subscriptionGroup, in VcnConfig config, in String opPkgName);
- void clearVcnConfig(in ParcelUuid subscriptionGroup);
+ void clearVcnConfig(in ParcelUuid subscriptionGroup, in String opPkgName);
void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index b73fdbf..abd41da 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -154,7 +154,7 @@
requireNonNull(subscriptionGroup, "subscriptionGroup was null");
try {
- mService.clearVcnConfig(subscriptionGroup);
+ mService.clearVcnConfig(subscriptionGroup, mContext.getOpPackageName());
} catch (ServiceSpecificException e) {
throw new IOException(e);
} catch (RemoteException e) {
@@ -439,7 +439,7 @@
* @param statusCode the code for the status change encountered by this {@link
* VcnStatusCallback}'s subscription group.
*/
- public abstract void onVcnStatusChanged(@VcnStatusCode int statusCode);
+ public abstract void onStatusChanged(@VcnStatusCode int statusCode);
/**
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription group
@@ -476,7 +476,7 @@
* and there is a VCN active for its specified subscription group (this may happen after the
* callback is registered).
*
- * <p>{@link VcnStatusCallback#onVcnStatusChanged(int)} will be invoked on registration with the
+ * <p>{@link VcnStatusCallback#onStatusChanged(int)} will be invoked on registration with the
* current status for the specified subscription group's VCN. If the registrant is not
* privileged for this subscription group, {@link #VCN_STATUS_CODE_NOT_CONFIGURED} will be
* returned.
@@ -580,7 +580,7 @@
@Override
public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> mCallback.onVcnStatusChanged(statusCode)));
+ () -> mExecutor.execute(() -> mCallback.onStatusChanged(statusCode)));
}
// TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 753abea..a3a910a 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4557,6 +4557,15 @@
public static final String VOICE_REG_STATE = "voice_reg_state";
/**
+ * An integer value indicating the current data service state.
+ * <p>
+ * Valid values: {@link ServiceState#STATE_IN_SERVICE},
+ * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY},
+ * {@link ServiceState#STATE_POWER_OFF}.
+ */
+ public static final String DATA_REG_STATE = "data_reg_state";
+
+ /**
* The current registered operator numeric id.
* <p>
* In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit
@@ -4572,6 +4581,24 @@
* This is the same as {@link ServiceState#getIsManualSelection()}.
*/
public static final String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
+
+ /**
+ * The current data network type.
+ * <p>
+ * This is the same as {@link TelephonyManager#getDataNetworkType()}.
+ */
+ public static final String DATA_NETWORK_TYPE = "data_network_type";
+
+ /**
+ * An integer value indicating the current duplex mode if the radio technology is LTE,
+ * LTE-CA or NR.
+ * <p>
+ * Valid values: {@link ServiceState#DUPLEX_MODE_UNKNOWN},
+ * {@link ServiceState#DUPLEX_MODE_FDD}, {@link ServiceState#DUPLEX_MODE_TDD}.
+ * <p>
+ * This is the same as {@link ServiceState#getDuplexMode()}.
+ */
+ public static final String DUPLEX_MODE = "duplex_mode";
}
/**
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0f6f15d..8db991b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4343,6 +4343,11 @@
check after reboot or airplane mode toggling -->
<bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">false</bool>
+ <!-- Boolean indicating whether all CB messages should be disabled on this device. This config
+ is intended to be used by OEMs who need to disable CB messages for regulatory requirements,
+ (e.g. the device is a tablet in a country where tablets should not receive CB messages) -->
+ <bool translatable="false" name="config_disable_all_cb_messages">false</bool>
+
<!-- Screen Wake Keys
Determines whether the specified key groups can be used to wake up the device. -->
<bool name="config_wakeOnDpadKeyPress">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ad24b79..46efd2c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3848,6 +3848,7 @@
<java-symbol type="layout" name="chooser_action_button" />
<java-symbol type="dimen" name="chooser_action_button_icon_size" />
<java-symbol type="string" name="config_defaultNearbySharingComponent" />
+ <java-symbol type="bool" name="config_disable_all_cb_messages" />
<java-symbol type="drawable" name="ic_close" />
<java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" />
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index fe5c1be..d048efc 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1196,13 +1196,11 @@
/** @hide */
public boolean isSupportedAxes(int axis) {
- if (mSupportedAxes == null) {
- synchronized (this) {
+ synchronized (this) {
+ if (mSupportedAxes == null) {
+ mSupportedAxes = nativeGetSupportedAxes(native_instance);
if (mSupportedAxes == null) {
- mSupportedAxes = nativeGetSupportedAxes(native_instance);
- if (mSupportedAxes == null) {
- mSupportedAxes = EMPTY_AXES;
- }
+ mSupportedAxes = EMPTY_AXES;
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 5cb2c3b..9ca551b 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -288,7 +288,7 @@
private static final Date DEFAULT_CERT_NOT_AFTER = new Date(2461449600000L); // Jan 1 2048
private final String mKeystoreAlias;
- private final int mNamespace;
+ private final @KeyProperties.Namespace int mNamespace;
private final int mKeySize;
private final AlgorithmParameterSpec mSpec;
private final X500Principal mCertificateSubject;
@@ -331,7 +331,7 @@
*/
public KeyGenParameterSpec(
String keyStoreAlias,
- int namespace,
+ @KeyProperties.Namespace int namespace,
int keySize,
AlgorithmParameterSpec spec,
X500Principal certificateSubject,
@@ -472,7 +472,7 @@
* @hide
*/
@SystemApi
- public int getNamespace() {
+ public @KeyProperties.Namespace int getNamespace() {
return mNamespace;
}
@@ -896,7 +896,7 @@
private final String mKeystoreAlias;
private @KeyProperties.PurposeEnum int mPurposes;
- private int mNamespace = KeyProperties.NAMESPACE_APPLICATION;
+ private @KeyProperties.Namespace int mNamespace = KeyProperties.NAMESPACE_APPLICATION;
private int mKeySize = -1;
private AlgorithmParameterSpec mSpec;
private X500Principal mCertificateSubject;
@@ -1051,7 +1051,7 @@
*/
@SystemApi
@NonNull
- public Builder setNamespace(int namespace) {
+ public Builder setNamespace(@KeyProperties.Namespace int namespace) {
mNamespace = namespace;
return this;
}
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 7b0fa91..682d12a 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -892,6 +892,22 @@
}
/**
+ * Namespaces provide system developers and vendors with a way to use keystore without
+ * requiring an applications uid. Namespaces can be configured using SEPolicy.
+ * See <a href="https://source.android.com/security/keystore#access-control">
+ * Keystore 2.0 access-control</a>
+ * {@See KeyGenParameterSpec.Builder#setNamespace}
+ * {@See android.security.keystore2.AndroidKeyStoreLoadStoreParameter}
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "NAMESPACE_" }, value = {
+ NAMESPACE_APPLICATION,
+ NAMESPACE_WIFI,
+ })
+ public @interface Namespace {}
+
+ /**
* This value indicates the implicit keystore namespace of the calling application.
* It is used by default. Only select system components can choose a different namespace
* which it must be configured in SEPolicy.
@@ -912,14 +928,12 @@
* For legacy support, translate namespaces into known UIDs.
* @hide
*/
- public static int namespaceToLegacyUid(int namespace) {
+ public static int namespaceToLegacyUid(@Namespace int namespace) {
switch (namespace) {
case NAMESPACE_APPLICATION:
return KeyStore.UID_SELF;
case NAMESPACE_WIFI:
return Process.WIFI_UID;
- // TODO Translate WIFI and VPN UIDs once the namespaces are defined.
- // b/171305388 and b/171305607
default:
throw new IllegalArgumentException("No UID corresponding to namespace "
+ namespace);
@@ -930,14 +944,12 @@
* For legacy support, translate namespaces into known UIDs.
* @hide
*/
- public static int legacyUidToNamespace(int uid) {
+ public static @Namespace int legacyUidToNamespace(int uid) {
switch (uid) {
case KeyStore.UID_SELF:
return NAMESPACE_APPLICATION;
case Process.WIFI_UID:
return NAMESPACE_WIFI;
- // TODO Translate WIFI and VPN UIDs once the namespaces are defined.
- // b/171305388 and b/171305607
default:
throw new IllegalArgumentException("No namespace corresponding to uid "
+ uid);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
index 0c6744f..25b1c86 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
@@ -16,6 +16,8 @@
package android.security.keystore2;
+import android.security.keystore.KeyProperties;
+
import java.security.KeyStore;
import java.security.KeyStore.ProtectionParameter;
@@ -24,9 +26,9 @@
*/
public class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
- private final int mNamespace;
+ private final @KeyProperties.Namespace int mNamespace;
- public AndroidKeyStoreLoadStoreParameter(int namespace) {
+ public AndroidKeyStoreLoadStoreParameter(@KeyProperties.Namespace int namespace) {
mNamespace = namespace;
}
@@ -35,7 +37,7 @@
return null;
}
- int getNamespace() {
+ @KeyProperties.Namespace int getNamespace() {
return mNamespace;
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 39607ae..32f98a2 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -100,7 +100,7 @@
public static final String NAME = "AndroidKeyStore";
private KeyStore2 mKeyStore;
- private int mNamespace = KeyProperties.NAMESPACE_APPLICATION;
+ private @KeyProperties.Namespace int mNamespace = KeyProperties.NAMESPACE_APPLICATION;
@Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
@@ -1125,7 +1125,7 @@
@Override
public void engineLoad(LoadStoreParameter param) throws IOException,
NoSuchAlgorithmException, CertificateException {
- int namespace = KeyProperties.NAMESPACE_APPLICATION;
+ @KeyProperties.Namespace int namespace = KeyProperties.NAMESPACE_APPLICATION;
if (param != null) {
if (param instanceof AndroidKeyStoreLoadStoreParameter) {
namespace = ((AndroidKeyStoreLoadStoreParameter) param).getNamespace();
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index e415e01..ad44b27 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -396,6 +396,7 @@
public static class NetworkRequest.Builder {
ctor public NetworkRequest.Builder();
+ ctor public NetworkRequest.Builder(@NonNull android.net.NetworkRequest);
method public android.net.NetworkRequest.Builder addCapability(int);
method public android.net.NetworkRequest.Builder addTransportType(int);
method public android.net.NetworkRequest build();
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index 23c92a5..bcbc04f7 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -216,6 +216,14 @@
}
/**
+ * Creates a new Builder of NetworkRequest from an existing instance.
+ */
+ public Builder(@NonNull final NetworkRequest request) {
+ Objects.requireNonNull(request);
+ mNetworkCapabilities = request.networkCapabilities;
+ }
+
+ /**
* Build {@link NetworkRequest} give the current set of capabilities.
*/
public NetworkRequest build() {
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index d561ab9..642fc6b 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -349,7 +349,8 @@
}
}
- private void enforceCallingUserAndCarrierPrivilege(ParcelUuid subscriptionGroup) {
+ private void enforceCallingUserAndCarrierPrivilege(
+ ParcelUuid subscriptionGroup, String pkgName) {
// Only apps running in the primary (system) user are allowed to configure the VCN. This is
// in line with Telephony's behavior with regards to binding to a Carrier App provided
// CarrierConfigService.
@@ -363,12 +364,15 @@
subscriptionInfos.addAll(subMgr.getSubscriptionsInGroup(subscriptionGroup));
});
- final TelephonyManager telMgr = mContext.getSystemService(TelephonyManager.class);
for (SubscriptionInfo info : subscriptionInfos) {
+ final TelephonyManager telMgr = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(info.getSubscriptionId());
+
// Check subscription is active first; much cheaper/faster check, and an app (currently)
// cannot be carrier privileged for inactive subscriptions.
if (subMgr.isValidSlotIndex(info.getSimSlotIndex())
- && telMgr.hasCarrierPrivileges(info.getSubscriptionId())) {
+ && telMgr.checkCarrierPrivilegesForPackage(pkgName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
// TODO (b/173717728): Allow configuration for inactive, but manageable
// subscriptions.
// TODO (b/173718661): Check for whole subscription groups at a time.
@@ -536,7 +540,7 @@
mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName());
- enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
+ enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) {
@@ -554,11 +558,14 @@
* <p>Implements the IVcnManagementService Binder interface.
*/
@Override
- public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) {
+ public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull String opPkgName) {
requireNonNull(subscriptionGroup, "subscriptionGroup was null");
+ requireNonNull(opPkgName, "opPkgName was null");
Slog.v(TAG, "VCN config cleared for subGrp: " + subscriptionGroup);
- enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
+ mContext.getSystemService(AppOpsManager.class)
+ .checkPackage(mDeps.getBinderCallingUid(), opPkgName);
+ enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 7dad9e0..c8f9982 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -19,10 +19,10 @@
import static android.Manifest.permission.BIND_VPN_SERVICE;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.os.UserHandle.PER_USER_RANGE;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
+import static android.os.UserHandle.PER_USER_RANGE;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -223,7 +223,7 @@
protected NetworkAgent mNetworkAgent;
private final Looper mLooper;
@VisibleForTesting
- protected final NetworkCapabilities mNetworkCapabilities;
+ protected NetworkCapabilities mNetworkCapabilities;
private final SystemServices mSystemServices;
private final Ikev2SessionCreator mIkev2SessionCreator;
private final UserManager mUserManager;
@@ -460,11 +460,12 @@
mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
"" /* subtypeName */);
- mNetworkCapabilities = new NetworkCapabilities();
- mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
- mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
- mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE));
+ mNetworkCapabilities = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+ .build();
loadAlwaysOnPackage();
}
@@ -525,8 +526,10 @@
}
private void resetNetworkCapabilities() {
- mNetworkCapabilities.setUids(null);
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE));
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setUids(null)
+ .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+ .build();
}
/**
@@ -1237,7 +1240,9 @@
// registered with registerDefaultNetworkCallback. This in turn protects the invariant
// that an app calling ConnectivityManager#bindProcessToNetwork(getDefaultNetwork())
// behaves the same as when it uses the default network.
- mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ final NetworkCapabilities.Builder capsBuilder =
+ new NetworkCapabilities.Builder(mNetworkCapabilities);
+ capsBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mLegacyState = LegacyVpnInfo.STATE_CONNECTING;
updateState(DetailedState.CONNECTING, "agentConnect");
@@ -1246,21 +1251,22 @@
.setBypassableVpn(mConfig.allowBypass && !mLockdown)
.build();
- mNetworkCapabilities.setOwnerUid(mOwnerUID);
- mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID});
- mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId,
+ capsBuilder.setOwnerUid(mOwnerUID);
+ capsBuilder.setAdministratorUids(new int[] {mOwnerUID});
+ capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+ capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
// Only apps targeting Q and above can explicitly declare themselves as metered.
// These VPNs are assumed metered unless they state otherwise.
if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) {
- mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_METERED);
+ capsBuilder.removeCapability(NET_CAPABILITY_NOT_METERED);
} else {
- mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
+ capsBuilder.addCapability(NET_CAPABILITY_NOT_METERED);
}
+ mNetworkCapabilities = capsBuilder.build();
mNetworkAgent = new NetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */,
mNetworkCapabilities, lp,
new NetworkScore.Builder().setLegacyInt(VPN_DEFAULT_SCORE).build(),
@@ -1427,7 +1433,8 @@
// restore old state
mConfig = oldConfig;
mConnection = oldConnection;
- mNetworkCapabilities.setUids(oldUsers);
+ mNetworkCapabilities =
+ new NetworkCapabilities.Builder(mNetworkCapabilities).setUids(oldUsers).build();
mNetworkAgent = oldNetworkAgent;
mInterface = oldInterface;
throw e;
@@ -1577,7 +1584,8 @@
try {
addUserToRanges(existingRanges, userId, mConfig.allowedApplications,
mConfig.disallowedApplications);
- mNetworkCapabilities.setUids(existingRanges);
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setUids(existingRanges).build();
} catch (Exception e) {
Log.wtf(TAG, "Failed to add restricted user to owner", e);
}
@@ -1606,7 +1614,8 @@
final List<Range<Integer>> removedRanges =
uidRangesForUser(userId, existingRanges);
existingRanges.removeAll(removedRanges);
- mNetworkCapabilities.setUids(existingRanges);
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setUids(existingRanges).build();
} catch (Exception e) {
Log.wtf(TAG, "Failed to remove restricted user to owner", e);
}
@@ -1850,22 +1859,13 @@
/**
* Updates underlying network set.
*/
- public synchronized boolean setUnderlyingNetworks(Network[] networks) {
+ public synchronized boolean setUnderlyingNetworks(@Nullable Network[] networks) {
if (!isCallerEstablishedOwnerLocked()) {
return false;
}
- if (networks == null) {
- mConfig.underlyingNetworks = null;
- } else {
- mConfig.underlyingNetworks = new Network[networks.length];
- for (int i = 0; i < networks.length; ++i) {
- if (networks[i] == null) {
- mConfig.underlyingNetworks[i] = null;
- } else {
- mConfig.underlyingNetworks[i] = new Network(networks[i].getNetId());
- }
- }
- }
+ // Make defensive copy since the content of array might be altered by the caller.
+ mConfig.underlyingNetworks =
+ (networks != null) ? Arrays.copyOf(networks, networks.length) : null;
mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null)
? Arrays.asList(mConfig.underlyingNetworks) : null);
return true;
@@ -1887,7 +1887,12 @@
if (!isRunningLocked()) {
return false;
}
- return mNetworkCapabilities.appliesToUid(uid);
+ final Set<Range<Integer>> uids = mNetworkCapabilities.getUids();
+ if (uids == null) return true;
+ for (final Range<Integer> range : uids) {
+ if (range.contains(uid)) return true;
+ }
+ return false;
}
/**
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 7d1827d..0c1ba96 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -32,6 +32,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -177,6 +178,8 @@
private Map<String, List<String>> mOemLockedApps = new HashMap();
+ private int mCurrentUserId = UserHandle.USER_NULL;
+
public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
ZenModeHelper zenHelper, NotificationChannelLogger notificationChannelLogger,
AppOpsManager appOpsManager,
@@ -191,7 +194,8 @@
updateBadgingEnabled();
updateBubblesEnabled();
- syncChannelsBypassingDnd(mContext.getUserId());
+ mCurrentUserId = ActivityManager.getCurrentUser();
+ syncChannelsBypassingDnd();
}
public void readXml(XmlPullParser parser, boolean forRestore, int userId)
@@ -790,7 +794,7 @@
// but the system can
if (group.isBlocked() != oldGroup.isBlocked()) {
group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE);
- updateChannelsBypassingDnd(mContext.getUserId());
+ updateChannelsBypassingDnd();
}
}
}
@@ -871,13 +875,13 @@
// fields on the channel yet
if (existing.getUserLockedFields() == 0 && hasDndAccess) {
boolean bypassDnd = channel.canBypassDnd();
- if (bypassDnd != existing.canBypassDnd()) {
+ if (bypassDnd != existing.canBypassDnd() || wasUndeleted) {
existing.setBypassDnd(bypassDnd);
needsPolicyFileChange = true;
if (bypassDnd != mAreChannelsBypassingDnd
|| previousExistingImportance != existing.getImportance()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ updateChannelsBypassingDnd();
}
}
}
@@ -941,7 +945,7 @@
r.channels.put(channel.getId(), channel);
if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ updateChannelsBypassingDnd();
}
MetricsLogger.action(getChannelLog(channel, pkg).setType(
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
@@ -1013,7 +1017,7 @@
if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
|| channel.getImportance() != updatedChannel.getImportance()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ updateChannelsBypassingDnd();
}
}
updateConfig();
@@ -1110,7 +1114,7 @@
mNotificationChannelLogger.logNotificationChannelDeleted(channel, uid, pkg);
if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ updateChannelsBypassingDnd();
}
}
}
@@ -1454,7 +1458,7 @@
}
}
if (!deletedChannelIds.isEmpty() && mAreChannelsBypassingDnd) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ updateChannelsBypassingDnd();
}
return deletedChannelIds;
}
@@ -1600,29 +1604,29 @@
}
/**
- * Syncs {@link #mAreChannelsBypassingDnd} with the user's notification policy before
+ * Syncs {@link #mAreChannelsBypassingDnd} with the current user's notification policy before
* updating
- * @param userId
*/
- private void syncChannelsBypassingDnd(int userId) {
+ private void syncChannelsBypassingDnd() {
mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state
& NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
- updateChannelsBypassingDnd(userId);
+ updateChannelsBypassingDnd();
}
/**
- * Updates the user's NotificationPolicy based on whether the given userId
+ * Updates the user's NotificationPolicy based on whether the current userId
* has channels bypassing DND
* @param userId
*/
- private void updateChannelsBypassingDnd(int userId) {
+ private void updateChannelsBypassingDnd() {
synchronized (mPackagePreferences) {
final int numPackagePreferences = mPackagePreferences.size();
for (int i = 0; i < numPackagePreferences; i++) {
final PackagePreferences r = mPackagePreferences.valueAt(i);
- // Package isn't associated with this userId or notifications from this package are
- // blocked
- if (userId != UserHandle.getUserId(r.uid) || r.importance == IMPORTANCE_NONE) {
+ // Package isn't associated with the current userId or notifications from this
+ // package are blocked
+ if (mCurrentUserId != UserHandle.getUserId(r.uid)
+ || r.importance == IMPORTANCE_NONE) {
continue;
}
@@ -2168,14 +2172,16 @@
* Called when user switches
*/
public void onUserSwitched(int userId) {
- syncChannelsBypassingDnd(userId);
+ mCurrentUserId = userId;
+ syncChannelsBypassingDnd();
}
/**
* Called when user is unlocked
*/
public void onUserUnlocked(int userId) {
- syncChannelsBypassingDnd(userId);
+ mCurrentUserId = userId;
+ syncChannelsBypassingDnd();
}
public void onUserRemoved(int userId) {
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 0a6772b..fe21201 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -734,7 +734,15 @@
return REBOOT_ERROR_SLOT_MISMATCH;
}
- if (!mInjector.getLockSettingsService().armRebootEscrow()) {
+ final long origId = Binder.clearCallingIdentity();
+ boolean result;
+ try {
+ result = mInjector.getLockSettingsService().armRebootEscrow();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+
+ if (!result) {
Slog.w(TAG, "Failure to escrow key for reboot");
return REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE;
}
@@ -742,11 +750,20 @@
return REBOOT_ERROR_NONE;
}
+ private boolean useServerBasedRoR() {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
+ "server_based_ror_enabled", false);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
private void reportMetricsOnRebootWithLskf(String packageName, boolean slotSwitch,
@ResumeOnRebootRebootErrorCode int errorCode) {
int uid = mInjector.getUidFromPackageName(packageName);
- boolean serverBased = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
- "server_based_ror_enabled", false);
+ boolean serverBased = useServerBasedRoR();
int preparedClientCount;
synchronized (this) {
preparedClientCount = mCallerPreparedForReboot.size();
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 3f74938..89ed956 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -41,6 +41,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -110,6 +111,24 @@
@NonNull private final VcnNetworkRequestListener mRequestListener;
@NonNull private final VcnCallback mVcnCallback;
+ /**
+ * Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs.
+ *
+ * <p>Due to potential for race conditions, VcnGatewayConnections MUST only be created and added
+ * to this map in {@link #handleNetworkRequested(NetworkRequest, int, int)}, when a VCN receives
+ * a NetworkRequest that matches a VcnGatewayConnectionConfig for this VCN's VcnConfig.
+ *
+ * <p>A VcnGatewayConnection instance MUST NEVER overwrite an existing instance - otherwise
+ * there is potential for a orphaned VcnGatewayConnection instance that does not get properly
+ * shut down.
+ *
+ * <p>Due to potential for race conditions, VcnGatewayConnections MUST only be removed from this
+ * map once they have finished tearing down, which is reported to this VCN via {@link
+ * VcnGatewayStatusCallback#onQuit()}. Once this is done, all NetworkRequests are retrieved from
+ * the NetworkProvider so that another VcnGatewayConnectionConfig can match the
+ * previously-matched request.
+ */
+ // TODO(b/182533200): remove the invariant on VcnGatewayConnection lifecycles
@NonNull
private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
new HashMap<>();
@@ -191,6 +210,19 @@
return Collections.unmodifiableSet(new HashSet<>(mVcnGatewayConnections.values()));
}
+ /** Get current Configs and Gateways for testing purposes */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public Map<VcnGatewayConnectionConfig, VcnGatewayConnection>
+ getVcnGatewayConnectionConfigMap() {
+ return Collections.unmodifiableMap(new HashMap<>(mVcnGatewayConnections));
+ }
+
+ /** Set whether this Vcn is active for testing purposes */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public void setIsActive(boolean isActive) {
+ mIsActive.set(isActive);
+ }
+
private class VcnNetworkRequestListener implements VcnNetworkProvider.NetworkRequestListener {
@Override
public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
@@ -202,11 +234,6 @@
@Override
public void handleMessage(@NonNull Message msg) {
- // Ignore if this Vcn is not active and we're not receiving new configs
- if (!isActive() && msg.what != MSG_EVENT_CONFIG_UPDATED) {
- return;
- }
-
switch (msg.what) {
case MSG_EVENT_CONFIG_UPDATED:
handleConfigUpdated((VcnConfig) msg.obj);
@@ -237,9 +264,31 @@
mConfig = config;
- // TODO(b/181815405): Reevaluate active VcnGatewayConnection(s)
+ if (mIsActive.getAndSet(true)) {
+ // VCN is already active - teardown any GatewayConnections whose configs have been
+ // removed and get all current requests
+ for (final Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry :
+ mVcnGatewayConnections.entrySet()) {
+ final VcnGatewayConnectionConfig gatewayConnectionConfig = entry.getKey();
+ final VcnGatewayConnection gatewayConnection = entry.getValue();
- if (!mIsActive.getAndSet(true)) {
+ // GatewayConnectionConfigs must match exactly (otherwise authentication or
+ // connection details may have changed).
+ if (!mConfig.getGatewayConnectionConfigs().contains(gatewayConnectionConfig)) {
+ if (gatewayConnection == null) {
+ Slog.wtf(
+ getLogTag(),
+ "Found gatewayConnectionConfig without GatewayConnection");
+ } else {
+ gatewayConnection.teardownAsynchronously();
+ }
+ }
+ }
+
+ // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be
+ // satisfied start a new GatewayConnection)
+ mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
+ } else {
// If this VCN was not previously active, it is exiting Safe Mode. Re-register the
// request listener to get NetworkRequests again (and all cached requests).
mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener);
@@ -259,13 +308,16 @@
private void handleEnterSafeMode() {
handleTeardown();
- mVcnGatewayConnections.clear();
-
mVcnCallback.onEnteredSafeMode();
}
private void handleNetworkRequested(
@NonNull NetworkRequest request, int score, int providerId) {
+ if (!isActive()) {
+ Slog.v(getLogTag(), "Received NetworkRequest while inactive. Ignore for now");
+ return;
+ }
+
if (score > getNetworkScore()) {
if (VDBG) {
Slog.v(
@@ -318,8 +370,10 @@
mVcnGatewayConnections.remove(config);
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
- // start a new GatewayConnection)
- mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
+ // start a new GatewayConnection), but only if the Vcn is still active
+ if (isActive()) {
+ mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
+ }
}
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 4259831..ee89e1c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -833,10 +833,10 @@
@Test
public void testDefaultAssistant_overrideDefault() {
- final int userId = 0;
+ final int userId = mContext.getUserId();
final String testComponent = "package/class";
final List<UserInfo> userInfos = new ArrayList<>();
- userInfos.add(new UserInfo(0, "", 0));
+ userInfos.add(new UserInfo(userId, "", 0));
final ArraySet<ComponentName> validAssistants = new ArraySet<>();
validAssistants.add(ComponentName.unflattenFromString(testComponent));
when(mActivityManager.isLowRamDevice()).thenReturn(false);
@@ -2393,7 +2393,7 @@
.thenReturn(mTestNotificationChannel);
reset(mListeners);
- mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
+ mBinderService.updateNotificationChannelForPackage(PKG, mUid, mTestNotificationChannel);
verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
@@ -2929,7 +2929,7 @@
@Test
public void testSetListenerAccessForUser() throws Exception {
- UserHandle user = UserHandle.of(10);
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
ComponentName c = ComponentName.unflattenFromString("package/Component");
mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
@@ -2945,20 +2945,20 @@
@Test
public void testSetAssistantAccessForUser() throws Exception {
- UserHandle user = UserHandle.of(10);
- List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 10;
+ ui.id = mContext.getUserId() + 10;
+ UserHandle user = UserHandle.of(ui.id);
+ List<UserInfo> uis = new ArrayList<>();
uis.add(ui);
ComponentName c = ComponentName.unflattenFromString("package/Component");
- when(mUm.getEnabledProfiles(10)).thenReturn(uis);
+ when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
mBinderService.setNotificationAssistantAccessGrantedForUser(c, user.getIdentifier(), true);
verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
c.flattenToString(), user.getIdentifier(), true, true);
- verify(mAssistants).setUserSet(10, true);
+ verify(mAssistants).setUserSet(ui.id, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
c.flattenToString(), user.getIdentifier(), false, true);
verify(mListeners, never()).setPackageOrComponentEnabled(
@@ -2967,7 +2967,7 @@
@Test
public void testGetAssistantAllowedForUser() throws Exception {
- UserHandle user = UserHandle.of(10);
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
try {
mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
} catch (IllegalStateException e) {
@@ -2987,12 +2987,12 @@
throw e;
}
}
- verify(mAssistants, times(1)).getAllowedComponents(0);
+ verify(mAssistants, times(1)).getAllowedComponents(mContext.getUserId());
}
@Test
public void testSetDndAccessForUser() throws Exception {
- UserHandle user = UserHandle.of(10);
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
ComponentName c = ComponentName.unflattenFromString("package/Component");
mBinderService.setNotificationPolicyAccessGrantedForUser(
c.getPackageName(), user.getIdentifier(), true);
@@ -3012,9 +3012,9 @@
mBinderService.setNotificationListenerAccessGranted(c, true);
verify(mListeners, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), mContext.getUserId(), true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), mContext.getUserId(), false, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
@@ -3023,7 +3023,7 @@
public void testSetAssistantAccess() throws Exception {
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 0;
+ ui.id = mContext.getUserId();
uis.add(ui);
when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
ComponentName c = ComponentName.unflattenFromString("package/Component");
@@ -3031,9 +3031,9 @@
mBinderService.setNotificationAssistantAccessGranted(c, true);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), ui.id, true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), ui.id, false, true);
verify(mListeners, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
@@ -3042,10 +3042,10 @@
public void testSetAssistantAccess_multiProfile() throws Exception {
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 0;
+ ui.id = mContext.getUserId();
uis.add(ui);
UserInfo ui10 = new UserInfo();
- ui10.id = 10;
+ ui10.id = mContext.getUserId() + 10;
uis.add(ui10);
when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
ComponentName c = ComponentName.unflattenFromString("package/Component");
@@ -3053,13 +3053,13 @@
mBinderService.setNotificationAssistantAccessGranted(c, true);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), ui.id, true, true);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 10, true, true);
+ c.flattenToString(), ui10.id, true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), ui.id, false, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 10, false, true);
+ c.flattenToString(), ui10.id, false, true);
verify(mListeners, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
@@ -3072,16 +3072,16 @@
when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 0;
+ ui.id = mContext.getUserId();
uis.add(ui);
when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
mBinderService.setNotificationAssistantAccessGranted(null, true);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, false);
+ c.flattenToString(), ui.id, true, false);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, false);
+ c.flattenToString(), ui.id, false, false);
verify(mListeners, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
@@ -3090,21 +3090,21 @@
public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 10;
+ ui.id = mContext.getUserId() + 10;
uis.add(ui);
UserHandle user = ui.getUserHandle();
ArrayList<ComponentName> componentList = new ArrayList<>();
ComponentName c = ComponentName.unflattenFromString("package/Component");
componentList.add(c);
when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
- when(mUm.getEnabledProfiles(10)).thenReturn(uis);
+ when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
mBinderService.setNotificationAssistantAccessGrantedForUser(
null, user.getIdentifier(), true);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
c.flattenToString(), user.getIdentifier(), true, false);
- verify(mAssistants).setUserSet(10, true);
+ verify(mAssistants).setUserSet(ui.id, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
c.flattenToString(), user.getIdentifier(), false, false);
verify(mListeners, never()).setPackageOrComponentEnabled(
@@ -3116,10 +3116,10 @@
throws Exception {
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 0;
+ ui.id = mContext.getUserId();
uis.add(ui);
UserInfo ui10 = new UserInfo();
- ui10.id = 10;
+ ui10.id = mContext.getUserId() + 10;
uis.add(ui10);
UserHandle user = ui.getUserHandle();
ArrayList<ComponentName> componentList = new ArrayList<>();
@@ -3135,8 +3135,8 @@
c.flattenToString(), user.getIdentifier(), true, false);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
c.flattenToString(), ui10.id, true, false);
- verify(mAssistants).setUserSet(0, true);
- verify(mAssistants).setUserSet(10, true);
+ verify(mAssistants).setUserSet(ui.id, true);
+ verify(mAssistants).setUserSet(ui10.id, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
c.flattenToString(), user.getIdentifier(), false, false);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
@@ -3152,7 +3152,7 @@
mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.getPackageName(), 0, true, true);
+ c.getPackageName(), mContext.getUserId(), true, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
verify(mListeners, never()).setPackageOrComponentEnabled(
@@ -3179,7 +3179,7 @@
ComponentName c = ComponentName.unflattenFromString("package/Component");
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 0;
+ ui.id = mContext.getUserId();
uis.add(ui);
when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
@@ -3214,9 +3214,9 @@
mBinderService.setNotificationListenerAccessGranted(c, true);
verify(mListeners, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), mContext.getUserId(), true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), mContext.getUserId(), false, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
@@ -3228,7 +3228,7 @@
ComponentName c = ComponentName.unflattenFromString("package/Component");
List<UserInfo> uis = new ArrayList<>();
UserInfo ui = new UserInfo();
- ui.id = 0;
+ ui.id = mContext.getUserId();
uis.add(ui);
when(mUm.getEnabledProfiles(ui.id)).thenReturn(uis);
@@ -3237,9 +3237,9 @@
verify(mListeners, never()).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), ui.id, false, true);
verify(mAssistants, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), ui.id, true, true);
}
@Test
@@ -3253,7 +3253,7 @@
verify(mListeners, never()).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.getPackageName(), 0, true, true);
+ c.getPackageName(), mContext.getUserId(), true, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index f110dae..2d06062 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -564,6 +564,7 @@
* @hide
*/
@UnsupportedAppUsage
+ @TestApi
public int getDataRegState() {
return mDataRegState;
}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index cfb29f1..5a12865 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -300,9 +300,12 @@
* @param data Message data.
* @param isCdma Indicates weather the type of the SMS is CDMA.
* @return An SmsMessage representing the message.
+ *
+ * @hide
*/
+ @SystemApi
@Nullable
- public static SmsMessage createSmsSubmitPdu(@NonNull byte[] data, boolean isCdma) {
+ public static SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[] data, boolean isCdma) {
SmsMessageBase wrappedMessage;
if (isCdma) {
@@ -318,23 +321,6 @@
}
/**
- * Create an SmsMessage from a native SMS-Submit PDU, specified by Bluetooth Message Access
- * Profile Specification v1.4.2 5.8.
- * This is used by Bluetooth MAP profile to decode message when sending non UTF-8 SMS messages.
- *
- * @param data Message data.
- * @param isCdma Indicates weather the type of the SMS is CDMA.
- * @return An SmsMessage representing the message.
- *
- * @hide
- */
- @SystemApi
- @Nullable
- public static SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[] data, boolean isCdma) {
- return null;
- }
-
- /**
* Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
* length in bytes (not hex chars) less the SMSC header
*
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index bae032c..7c39cf0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -14570,7 +14570,12 @@
* DataThrottlingRequest#DATA_THROTTLING_ACTION_NO_DATA_THROTTLING} can still be requested in
* order to undo the mitigations above it (i.e {@link
* ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_VOICE_ONLY} and/or {@link
- * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF}).
+ * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF}). </p>
+ *
+ * <p> In addition to the {@link Manifest.permission#MODIFY_PHONE_STATE} permission, callers of
+ * this API must also be listed in the device configuration as an authorized app in
+ * {@code packages/services/Telephony/res/values/config.xml} under the
+ * {@code thermal_mitigation_allowlisted_packages} key. </p>
*
* @param thermalMitigationRequest Thermal mitigation request. See {@link
* ThermalMitigationRequest} for details.
@@ -14589,7 +14594,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.sendThermalMitigationRequest(getSubId(), thermalMitigationRequest);
+ return telephony.sendThermalMitigationRequest(getSubId(), thermalMitigationRequest,
+ getOpPackageName());
}
throw new IllegalStateException("telephony service is null.");
} catch (RemoteException ex) {
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 52d0f03..a133ead 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -29,7 +29,9 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Contains the User Capability Exchange capabilities corresponding to a contact's URI.
@@ -110,7 +112,6 @@
/**
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through SIP OPTIONS.
- * @hide
*/
public static final class OptionsBuilder {
@@ -151,7 +152,7 @@
* @param tags the list of the supported feature tags
* @return this OptionBuilder
*/
- public @NonNull OptionsBuilder addFeatureTags(@NonNull List<String> tags) {
+ public @NonNull OptionsBuilder addFeatureTags(@NonNull Set<String> tags) {
mCapabilities.mFeatureTags.addAll(tags);
return this;
}
@@ -220,7 +221,7 @@
private @CapabilityMechanism int mCapabilityMechanism;
private @RequestResult int mRequestResult;
- private final List<String> mFeatureTags = new ArrayList<>();
+ private final Set<String> mFeatureTags = new HashSet<>();
private final List<RcsContactPresenceTuple> mPresenceTuples = new ArrayList<>();
private RcsContactUceCapability(@NonNull Uri contactUri, @CapabilityMechanism int mechanism,
@@ -235,7 +236,9 @@
mCapabilityMechanism = in.readInt();
mSourceType = in.readInt();
mRequestResult = in.readInt();
- in.readStringList(mFeatureTags);
+ List<String> featureTagList = new ArrayList<>();
+ in.readStringList(featureTagList);
+ mFeatureTags.addAll(featureTagList);
in.readParcelableList(mPresenceTuples, RcsContactPresenceTuple.class.getClassLoader());
}
@@ -245,7 +248,7 @@
out.writeInt(mCapabilityMechanism);
out.writeInt(mSourceType);
out.writeInt(mRequestResult);
- out.writeStringList(mFeatureTags);
+ out.writeStringList(new ArrayList<>(mFeatureTags));
out.writeParcelableList(mPresenceTuples, flags);
}
@@ -285,7 +288,20 @@
if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) {
return Collections.emptyList();
}
- return Collections.unmodifiableList(mFeatureTags);
+ return Collections.unmodifiableList(new ArrayList<>(mFeatureTags));
+ }
+
+ /**
+ * @return The feature tags present in the OPTIONS response from the network.
+ * <p>
+ * Note: this is only populated if {@link #getCapabilityMechanism} is
+ * {@link RcsContactUceCapability#CAPABILITY_MECHANISM_OPTIONS}
+ */
+ public @NonNull Set<String> getFeatureTags() {
+ if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) {
+ return Collections.emptySet();
+ }
+ return Collections.unmodifiableSet(mFeatureTags);
}
/**
diff --git a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
index a217d13..c3d7325 100644
--- a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
@@ -26,7 +26,8 @@
import android.telephony.ims.stub.CapabilityExchangeEventListener;
import android.util.Log;
-import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
/**
* The ICapabilityExchangeEventListener wrapper class to store the listener which is registered by
@@ -84,7 +85,7 @@
* request to the framework.
*/
public void onRemoteCapabilityRequest(@NonNull Uri contactUri,
- @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback)
+ @NonNull Set<String> remoteCapabilities, @NonNull OptionsRequestCallback callback)
throws ImsException {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
@@ -114,7 +115,8 @@
};
try {
- listener.onRemoteCapabilityRequest(contactUri, remoteCapabilities, internalCallback);
+ listener.onRemoteCapabilityRequest(contactUri, new ArrayList<>(remoteCapabilities),
+ internalCallback);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Remote capability request exception: " + e);
throw new ImsException("Remote is not available",
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 85703f8..6315b24 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -47,6 +47,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
@@ -145,8 +146,8 @@
throws RemoteException {
OptionsResponseCallback callbackWrapper = new RcsOptionsResponseAidlWrapper(callback);
executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal()
- .sendOptionsCapabilityRequest(contactUri, myCapabilities, callbackWrapper),
- "sendOptionsCapabilityRequest");
+ .sendOptionsCapabilityRequest(contactUri, new HashSet<>(myCapabilities),
+ callbackWrapper), "sendOptionsCapabilityRequest");
}
// Call the methods with a clean calling identity on the executor and wait indefinitely for
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index 6295548..a3be8da 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -26,7 +26,7 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
-import java.util.List;
+import java.util.Set;
/**
* The interface that is used by the framework to listen to events from the vendor RCS stack
@@ -98,7 +98,8 @@
* {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}.
* @param contactUri The URI associated with the remote contact that is
* requesting capabilities.
- * @param remoteCapabilities The remote contact's capability information.
+ * @param remoteCapabilities The remote contact's capability information. The capability
+ * information is in the format defined in RCC.07 section 2.6.1.3.
* @param callback The callback of this request which is sent from the remote user.
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not
* currently connected to the framework. This can happen if the {@link RcsFeature} is not
@@ -107,6 +108,6 @@
* cases when the Telephony stack has crashed.
*/
void onRemoteCapabilityRequest(@NonNull Uri contactUri,
- @NonNull List<String> remoteCapabilities,
+ @NonNull Set<String> remoteCapabilities,
@NonNull OptionsRequestCallback callback) throws ImsException;
}
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index 03e17fb..25b9446 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -33,6 +33,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -433,6 +434,7 @@
* @param contactUri The URI of the remote user that we wish to get the capabilities of.
* @param myCapabilities The capabilities of this device to send to the remote user.
* @param callback The callback of this request which is sent from the remote user.
+ * @hide
*/
// executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration")
@@ -446,4 +448,27 @@
// Do not do anything, this is a stub implementation.
}
}
+
+ /**
+ * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism
+ * in order to receive the capabilities of the remote user in response.
+ * <p>
+ * The implementer must use {@link OptionsResponseCallback} to send the response of
+ * this query from the network back to the framework.
+ * @param contactUri The URI of the remote user that we wish to get the capabilities of.
+ * @param myCapabilities The capabilities of this device to send to the remote user.
+ * @param callback The callback of this request which is sent from the remote user.
+ */
+ // executor used is defined in the constructor.
+ @SuppressLint("ExecutorRegistration")
+ public void sendOptionsCapabilityRequest(@NonNull Uri contactUri,
+ @NonNull Set<String> myCapabilities, @NonNull OptionsResponseCallback callback) {
+ // Stub - to be implemented by service
+ Log.w(LOG_TAG, "sendOptionsCapabilityRequest called with no implementation.");
+ try {
+ callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
+ } catch (ImsException e) {
+ // Do not do anything, this is a stub implementation.
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 45702c31..c306c57 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2231,10 +2231,12 @@
*
* @param subId the id of the subscription
* @param thermalMitigationRequest holds the parameters necessary for the request.
+ * @param callingPackage the package name of the calling package.
* @throws InvalidThermalMitigationRequestException if the parametes are invalid.
*/
int sendThermalMitigationRequest(int subId,
- in ThermalMitigationRequest thermalMitigationRequest);
+ in ThermalMitigationRequest thermalMitigationRequest,
+ String callingPackage);
/**
* Get the Generic Bootstrapping Architecture authentication keys
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index f161e52..1f50e31 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -329,7 +329,8 @@
if (isAtLeastS()) {
netCap.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2));
netCap.setUids(uids);
- } else if (isAtLeastR()) {
+ }
+ if (isAtLeastR()) {
netCap.setOwnerUid(123);
netCap.setAdministratorUids(new int[] {5, 11});
}
@@ -611,17 +612,18 @@
// From S, it is not allowed to have the same capability in both wanted and
// unwanted list.
assertThrows(IllegalArgumentException.class, () -> nc2.combineCapabilities(nc1));
+ // Remove unwanted capability to continue other tests.
+ nc1.removeUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
} else {
nc2.combineCapabilities(nc1);
// We will get this capability in both requested and unwanted lists thus this request
// will never be satisfied.
assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+ // For R or below, remove unwanted capability via removeCapability.
+ nc1.removeCapability(NET_CAPABILITY_NOT_ROAMING);
}
- // Remove unwanted capability to continue other tests.
- nc1.removeUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
-
nc1.setSSID(TEST_SSID);
nc2.combineCapabilities(nc1);
if (isAtLeastR()) {
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 7515971..516c206 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -204,7 +204,7 @@
new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback);
cbBinder.onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
- verify(mMockStatusCallback).onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
+ verify(mMockStatusCallback).onStatusChanged(VCN_STATUS_CODE_ACTIVE);
cbBinder.onGatewayConnectionError(
UNDERLYING_NETWORK_CAPABILITIES,
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index a9d5822..babea36 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -19,6 +19,8 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
@@ -238,9 +240,14 @@
doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
.when(mSubMgr)
.getSubscriptionsInGroup(any());
- doReturn(isPrivileged)
+ doReturn(mTelMgr)
.when(mTelMgr)
- .hasCarrierPrivileges(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
+ .createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
+ doReturn(isPrivileged
+ ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ : CARRIER_PRIVILEGE_STATUS_NO_ACCESS)
+ .when(mTelMgr)
+ .checkCarrierPrivilegesForPackage(eq(TEST_PACKAGE_NAME));
}
@Test
@@ -391,7 +398,7 @@
mTestLooper.moveTimeForward(
VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
mTestLooper.dispatchAll();
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2);
// Verify that new instance was different, and the old one was torn down
@@ -492,7 +499,7 @@
doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
try {
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
fail("Expected IllegalStateException exception for system server");
} catch (IllegalStateException expected) {
}
@@ -505,7 +512,7 @@
.getBinderCallingUid();
try {
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
fail("Expected security exception for non system user");
} catch (SecurityException expected) {
}
@@ -516,15 +523,24 @@
setupMockedCarrierPrivilege(false);
try {
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
fail("Expected security exception for missing carrier privileges");
} catch (SecurityException expected) {
}
}
@Test
+ public void testClearVcnConfigMismatchedPackages() throws Exception {
+ try {
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, "IncorrectPackage");
+ fail("Expected security exception due to mismatched packages");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
public void testClearVcnConfig() throws Exception {
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
}
@@ -535,7 +551,7 @@
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED);
}
@@ -564,7 +580,7 @@
verify(vcnInstance).updateConfig(TEST_VCN_CONFIG);
// Verify Vcn is stopped if it was already started
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
verify(vcnInstance).teardownAsynchronously();
}
@@ -781,7 +797,7 @@
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
verify(mMockPolicyListener).onPolicyChanged();
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java
index 4fa63d4..c853fc5 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -139,8 +140,7 @@
mTestLooper.dispatchAll();
}
- @Test
- public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
+ private void verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(boolean isActive) {
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
startVcnGatewayWithCapabilities(requestListener, TEST_CAPS[0]);
@@ -150,14 +150,27 @@
final TelephonySubscriptionSnapshot updatedSnapshot =
mock(TelephonySubscriptionSnapshot.class);
+ mVcn.setIsActive(isActive);
+
mVcn.updateSubscriptionSnapshot(updatedSnapshot);
mTestLooper.dispatchAll();
for (final VcnGatewayConnection gateway : gatewayConnections) {
- verify(gateway).updateSubscriptionSnapshot(eq(updatedSnapshot));
+ verify(gateway, isActive ? times(1) : never())
+ .updateSubscriptionSnapshot(eq(updatedSnapshot));
}
}
+ @Test
+ public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
+ verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(true /* isActive */);
+ }
+
+ @Test
+ public void testSubscriptionSnapshotUpdatesVcnGatewayConnectionsWhileInactive() {
+ verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(false /* isActive */);
+ }
+
private void triggerVcnRequestListeners(NetworkRequestListener requestListener) {
for (final int[] caps : TEST_CAPS) {
startVcnGatewayWithCapabilities(requestListener, caps);
@@ -187,7 +200,6 @@
NetworkRequestListener requestListener,
Set<VcnGatewayConnection> expectedGatewaysTornDown) {
assertFalse(mVcn.isActive());
- assertTrue(mVcn.getVcnGatewayConnections().isEmpty());
for (final VcnGatewayConnection gatewayConnection : expectedGatewaysTornDown) {
verify(gatewayConnection).teardownAsynchronously();
}
@@ -238,6 +250,51 @@
}
@Test
+ public void testGatewayQuitWhileInactive() {
+ final NetworkRequestListener requestListener = verifyAndGetRequestListener();
+ final Set<VcnGatewayConnection> gatewayConnections =
+ new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
+
+ mVcn.teardownAsynchronously();
+ mTestLooper.dispatchAll();
+
+ final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
+ statusCallback.onQuit();
+ mTestLooper.dispatchAll();
+
+ // Verify that the VCN requests the networkRequests be resent
+ assertEquals(1, mVcn.getVcnGatewayConnections().size());
+ verify(mVcnNetworkProvider, never()).resendAllRequests(requestListener);
+ }
+
+ @Test
+ public void testUpdateConfigReevaluatesGatewayConnections() {
+ final NetworkRequestListener requestListener = verifyAndGetRequestListener();
+ startGatewaysAndGetGatewayConnections(requestListener);
+ assertEquals(2, mVcn.getVcnGatewayConnectionConfigMap().size());
+
+ // Create VcnConfig with only one VcnGatewayConnectionConfig so a gateway connection is torn
+ // down
+ final VcnGatewayConnectionConfig activeConfig =
+ VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(TEST_CAPS[0]);
+ final VcnGatewayConnectionConfig removedConfig =
+ VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(TEST_CAPS[1]);
+ final VcnConfig updatedConfig =
+ new VcnConfig.Builder(mContext).addGatewayConnectionConfig(activeConfig).build();
+
+ mVcn.updateConfig(updatedConfig);
+ mTestLooper.dispatchAll();
+
+ final VcnGatewayConnection activeGatewayConnection =
+ mVcn.getVcnGatewayConnectionConfigMap().get(activeConfig);
+ final VcnGatewayConnection removedGatewayConnection =
+ mVcn.getVcnGatewayConnectionConfigMap().get(removedConfig);
+ verify(activeGatewayConnection, never()).teardownAsynchronously();
+ verify(removedGatewayConnection).teardownAsynchronously();
+ verify(mVcnNetworkProvider).resendAllRequests(requestListener);
+ }
+
+ @Test
public void testUpdateConfigExitsSafeMode() {
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
final Set<VcnGatewayConnection> gatewayConnections =
@@ -261,8 +318,8 @@
verify(mVcnNetworkProvider, times(2)).registerListener(eq(requestListener));
assertTrue(mVcn.isActive());
for (final int[] caps : TEST_CAPS) {
- // Expect each gateway connection created on initial startup, and again with new configs
- verify(mDeps, times(2))
+ // Expect each gateway connection created only on initial startup
+ verify(mDeps)
.newVcnGatewayConnection(
eq(mVcnContext),
eq(TEST_SUB_GROUP),
@@ -271,4 +328,14 @@
any());
}
}
+
+ @Test
+ public void testIgnoreNetworkRequestWhileInactive() {
+ mVcn.setIsActive(false /* isActive */);
+
+ final NetworkRequestListener requestListener = verifyAndGetRequestListener();
+ triggerVcnRequestListeners(requestListener);
+
+ verify(mDeps, never()).newVcnGatewayConnection(any(), any(), any(), any(), any());
+ }
}