Merge "Fix crash when MultipathPolicyTracker cannot get IMSI"
diff --git a/core/api/current.txt b/core/api/current.txt
index 0610446..4036c98 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25209,6 +25209,7 @@
public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
+ method @Nullable public android.net.ipsec.ike.IkeTunnelConnectionParams getIkeTunnelConnectionParams();
method public int getMaxMtu();
method @Nullable public String getPassword();
method @Nullable public byte[] getPresharedKey();
@@ -25503,11 +25504,13 @@
public class VpnManager {
method public void deleteProvisionedVpnProfile();
+ method @Nullable public android.net.VpnProfileState getProvisionedVpnProfileState();
method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
method @Deprecated public void startProvisionedVpnProfile();
method @NonNull public String startProvisionedVpnProfileSession();
method public void stopProvisionedVpnProfile();
field public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
+ field public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED = "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
field public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER = "android.net.category.EVENT_DEACTIVATED_BY_USER";
field public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
field public static final String CATEGORY_EVENT_NETWORK_ERROR = "android.net.category.EVENT_NETWORK_ERROR";
@@ -25524,6 +25527,22 @@
field public static final String EXTRA_UNDERLYING_LINK_PROPERTIES = "android.net.extra.UNDERLYING_LINK_PROPERTIES";
field public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
field public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES = "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
+ field public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
+ }
+
+ public final class VpnProfileState implements android.os.Parcelable {
+ ctor public VpnProfileState(int, @Nullable String, boolean, boolean);
+ method public int describeContents();
+ method @Nullable public String getSessionId();
+ method public int getState();
+ method public boolean isAlwaysOn();
+ method public boolean isLockdownEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnProfileState> CREATOR;
+ field public static final int STATE_CONNECTED = 2; // 0x2
+ field public static final int STATE_CONNECTING = 1; // 0x1
+ field public static final int STATE_DISCONNECTED = 0; // 0x0
+ field public static final int STATE_FAILED = 3; // 0x3
}
public class VpnService extends android.app.Service {
@@ -41403,7 +41422,8 @@
method public void setSubscriptionOverrideCongested(int, boolean, @NonNull int[], long);
method public void setSubscriptionOverrideUnmetered(int, boolean, long);
method public void setSubscriptionOverrideUnmetered(int, boolean, @NonNull int[], long);
- method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
+ method @Deprecated public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
+ method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>, long);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, @NonNull android.app.PendingIntent);
field public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6145886..cbfd86e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11594,7 +11594,7 @@
}
public class TelephonyManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -11639,7 +11639,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public int getMaxNumberOfSimultaneouslyActiveSims();
method public static long getMaxNumberVerificationTimeoutMillis();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
@@ -11647,10 +11647,13 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
method public int getSimApplicationState();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int, int);
method public int getSimCardState();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Collection<android.telephony.UiccSlotMapping> getSimSlotMapping();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -11687,7 +11690,8 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -11737,6 +11741,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterCarrierPrivilegesCallback(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
method public void updateServiceLocation();
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
@@ -11841,8 +11846,13 @@
field public static final int RESULT_SUCCESS = 0; // 0x0
}
- public static interface TelephonyManager.CarrierPrivilegesListener {
- method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
+ public static interface TelephonyManager.CarrierPrivilegesCallback {
+ method public void onCarrierPrivilegesChanged(@NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.Integer>);
+ method public default void onCarrierServiceChanged(@Nullable String, int);
+ }
+
+ @Deprecated public static interface TelephonyManager.CarrierPrivilegesListener {
+ method @Deprecated public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
}
public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
diff --git a/core/java/android/content/pm/SHORTCUT_OWNERS b/core/java/android/content/pm/SHORTCUT_OWNERS
index 3688d5a..f8bba473 100644
--- a/core/java/android/content/pm/SHORTCUT_OWNERS
+++ b/core/java/android/content/pm/SHORTCUT_OWNERS
@@ -1,7 +1,6 @@
set noparent
+pinyaoting@google.com
+sunnygoyal@google.com
omakoto@google.com
yamasani@google.com
-sunnygoyal@google.com
-mett@google.com
-pinyaoting@google.com
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 6284f56..dc24106 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -72,9 +72,9 @@
SubscriptionPlan getSubscriptionPlan(in NetworkTemplate template);
void notifyStatsProviderWarningOrLimitReached();
SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
- void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
+ void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, long expirationDurationMillis, String callingPackage);
String getSubscriptionPlansOwner(int subId);
- void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long timeoutMillis, String callingPackage);
+ void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long expirationDurationMillis, String callingPackage);
void factoryReset(String subscriber);
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index 070efa3..b4647ca 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -17,6 +17,7 @@
package android.net;
import android.net.Network;
+import android.net.VpnProfileState;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
@@ -40,6 +41,7 @@
void deleteVpnProfile(String packageName);
String startVpnProfile(String packageName);
void stopVpnProfile(String packageName);
+ VpnProfileState getProvisionedVpnProfileState(String packageName);
/** Always-on VPN APIs */
boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 0fd3e03..3abe83b 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -142,6 +142,7 @@
private final boolean mIsMetered; // Defaults in builder
private final int mMaxMtu; // Defaults in builder
private final boolean mIsRestrictedToTestNetworks;
+ @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams;
private Ikev2VpnProfile(
int type,
@@ -160,7 +161,8 @@
int maxMtu,
boolean restrictToTestNetworks,
boolean excludeLocalRoutes,
- boolean requiresInternetValidation) {
+ boolean requiresInternetValidation,
+ @Nullable IkeTunnelConnectionParams ikeTunConnParams) {
super(type, excludeLocalRoutes, requiresInternetValidation);
checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
@@ -190,6 +192,8 @@
mMaxMtu = maxMtu;
mIsRestrictedToTestNetworks = restrictToTestNetworks;
+ mIkeTunConnParams = ikeTunConnParams;
+
validate();
}
@@ -375,6 +379,12 @@
return mMaxMtu;
}
+ /** Retrieves the ikeTunnelConnectionParams contains IKEv2 configurations, if any was set. */
+ @Nullable
+ public IkeTunnelConnectionParams getIkeTunnelConnectionParams() {
+ return mIkeTunConnParams;
+ }
+
/**
* Returns whether or not this VPN profile is restricted to test networks.
*
@@ -403,7 +413,8 @@
mMaxMtu,
mIsRestrictedToTestNetworks,
mExcludeLocalRoutes,
- mRequiresInternetValidation);
+ mRequiresInternetValidation,
+ mIkeTunConnParams);
}
@Override
@@ -429,7 +440,8 @@
&& mMaxMtu == other.mMaxMtu
&& mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
&& mExcludeLocalRoutes == other.mExcludeLocalRoutes
- && mRequiresInternetValidation == other.mRequiresInternetValidation;
+ && mRequiresInternetValidation == other.mRequiresInternetValidation
+ && Objects.equals(mIkeTunConnParams, other.mIkeTunConnParams);
}
/**
@@ -504,6 +516,7 @@
@NonNull
public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
throws GeneralSecurityException {
+ // TODO: Build the VpnProfile from mIkeTunConnParams if it exists.
final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
builder.setProxy(profile.proxy);
builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
@@ -788,7 +801,7 @@
private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
private boolean mIsRestrictedToTestNetworks = false;
private boolean mExcludeLocalRoutes = false;
- @Nullable private IkeTunnelConnectionParams mIkeTunConnParams;
+ @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams;
/**
* Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -803,6 +816,8 @@
mServerAddr = serverAddr;
mUserIdentity = identity;
+
+ mIkeTunConnParams = null;
}
/**
@@ -1135,7 +1150,8 @@
mMaxMtu,
mIsRestrictedToTestNetworks,
mExcludeLocalRoutes,
- mRequiresInternetValidation);
+ mRequiresInternetValidation,
+ mIkeTunConnParams);
}
}
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 341d98f..43ae4fc 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -484,8 +484,8 @@
* @param networkTypes the network types this override applies to. If no
* network types are specified, override values will be ignored.
* {@see TelephonyManager#getAllNetworkTypes()}
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first
* @param callingPackage the name of the package making the call.
@@ -493,11 +493,11 @@
*/
public void setSubscriptionOverride(int subId, @SubscriptionOverrideMask int overrideMask,
@SubscriptionOverrideMask int overrideValue,
- @NonNull @Annotation.NetworkType int[] networkTypes, long timeoutMillis,
+ @NonNull @Annotation.NetworkType int[] networkTypes, long expirationDurationMillis,
@NonNull String callingPackage) {
try {
mService.setSubscriptionOverride(subId, overrideMask, overrideValue, networkTypes,
- timeoutMillis, callingPackage);
+ expirationDurationMillis, callingPackage);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -508,13 +508,16 @@
*
* @param subId the subscriber this relationship applies to.
* @param plans the list of plans.
+ * @param expirationDurationMillis the duration after which the subscription plans
+ * will be automatically cleared, or {@code 0} to leave the plans until
+ * explicitly cleared, or the next reboot, whichever happens first
* @param callingPackage the name of the package making the call
* @hide
*/
public void setSubscriptionPlans(int subId, @NonNull SubscriptionPlan[] plans,
- @NonNull String callingPackage) {
+ long expirationDurationMillis, @NonNull String callingPackage) {
try {
- mService.setSubscriptionPlans(subId, plans, callingPackage);
+ mService.setSubscriptionPlans(subId, plans, expirationDurationMillis, callingPackage);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -525,9 +528,11 @@
*
* @param subId the subscriber to get the subscription plans for.
* @param callingPackage the name of the package making the call.
+ * @return the active {@link SubscriptionPlan}s for the given subscription id, or
+ * {@code null} if not found.
* @hide
*/
- @NonNull
+ @Nullable
public SubscriptionPlan[] getSubscriptionPlans(int subId, @NonNull String callingPackage) {
try {
return mService.getSubscriptionPlans(subId, callingPackage);
@@ -540,7 +545,7 @@
* Get subscription plan for the given networkTemplate.
*
* @param template the networkTemplate to get the subscription plan for.
- * @return the active {@link SubscriptionPlan} for the given template, or
+ * @return the active {@link SubscriptionPlan}s for the given template, or
* {@code null} if not found.
* @hide
*/
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index 0eb4cf3..b05f7cf 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -60,7 +60,7 @@
private static final int TRANSMIT_TIME_OFFSET = 40;
private static final int NTP_PACKET_SIZE = 48;
- private static final int NTP_PORT = 123;
+ public static final int STANDARD_NTP_PORT = 123;
private static final int NTP_MODE_CLIENT = 3;
private static final int NTP_MODE_SERVER = 4;
private static final int NTP_MODE_BROADCAST = 5;
@@ -108,18 +108,21 @@
* Sends an SNTP request to the given host and processes the response.
*
* @param host host name of the server.
+ * @param port port of the server.
* @param timeout network timeout in milliseconds. the timeout doesn't include the DNS lookup
* time, and it applies to each individual query to the resolved addresses of
* the NTP server.
* @param network network over which to send the request.
* @return true if the transaction was successful.
*/
- public boolean requestTime(String host, int timeout, Network network) {
+ public boolean requestTime(String host, int port, int timeout, Network network) {
final Network networkForResolv = network.getPrivateDnsBypassingCopy();
try {
final InetAddress[] addresses = networkForResolv.getAllByName(host);
for (int i = 0; i < addresses.length; i++) {
- if (requestTime(addresses[i], NTP_PORT, timeout, networkForResolv)) return true;
+ if (requestTime(addresses[i], port, timeout, networkForResolv)) {
+ return true;
+ }
}
} catch (UnknownHostException e) {
Log.w(TAG, "Unknown host: " + host);
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index c51444c..ae7d91f 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -161,6 +161,23 @@
"android.net.category.EVENT_DEACTIVATED_BY_USER";
/**
+ * The always-on state of this VPN was changed
+ *
+ * <p>This may be the result of a user changing VPN settings, or a Device Policy Manager app
+ * having changed the VPN policy.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED =
+ "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
+
+ /**
+ * The VpnProfileState at the time that this event occurred.
+ *
+ * <p>This extra may be null if the VPN was revoked by the user, or the profile was deleted.
+ */
+ public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
+
+ /**
* The key of the session that experienced this event, as a {@code String}.
*
* This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
@@ -403,6 +420,21 @@
}
/**
+ * Retrieve the VpnProfileState for the profile provisioned by the calling package.
+ *
+ * @return the VpnProfileState with current information, or null if there was no profile
+ * provisioned by the calling package.
+ */
+ @Nullable
+ public VpnProfileState getProvisionedVpnProfileState() {
+ try {
+ return mService.getProvisionedVpnProfileState(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Resets all VPN settings back to factory defaults.
* @hide
*/
diff --git a/core/java/android/net/VpnProfileState.aidl b/core/java/android/net/VpnProfileState.aidl
new file mode 100644
index 0000000..add6386e
--- /dev/null
+++ b/core/java/android/net/VpnProfileState.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable VpnProfileState;
\ No newline at end of file
diff --git a/core/java/android/net/VpnProfileState.java b/core/java/android/net/VpnProfileState.java
new file mode 100644
index 0000000..c69ea1a
--- /dev/null
+++ b/core/java/android/net/VpnProfileState.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Describe the state of VPN.
+ */
+public final class VpnProfileState implements Parcelable {
+ /** The VPN has not been started, or some other VPN is active. */
+ public static final int STATE_DISCONNECTED = 0;
+ /** The VPN is attempting to connect, potentially after a failure. */
+ public static final int STATE_CONNECTING = 1;
+ /** The VPN was established successfully. */
+ public static final int STATE_CONNECTED = 2;
+ /** A non-recoverable error has occurred, and will not be retried. */
+ public static final int STATE_FAILED = 3;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"STATE_"}, value = {
+ STATE_CONNECTED,
+ STATE_CONNECTING,
+ STATE_DISCONNECTED,
+ STATE_FAILED,
+ })
+ public @interface State {}
+
+ @State private final int mState;
+ private final String mSessionKey;
+ private final boolean mAlwaysOn;
+ private final boolean mLockdown;
+
+ public VpnProfileState(@State int state, @Nullable String sessionKey, boolean alwaysOn,
+ boolean lockdown) {
+ mState = state;
+ mSessionKey = sessionKey;
+ mAlwaysOn = alwaysOn;
+ mLockdown = lockdown;
+ }
+
+ /**
+ * Returns the state of the Platform VPN
+ *
+ * <p>This state represents the internal connection state of the VPN. This state may diverge
+ * from the VPN Network's state during error and recovery handling.
+ */
+ @State public int getState() {
+ return mState;
+ }
+
+ /**
+ * Retrieves the Session Key
+ *
+ * <p>The session key is an ephemeral key uniquely identifying the session for a Platform VPN.
+ * The lifetime of this key is tied to the lifetime of the VPN session. In other words,
+ * reprovisioning of the VPN profile, restarting of the device, or manually restarting the
+ * platform VPN session will result in a new VPN session, and a new key.
+ *
+ * @return the unique key for the platform VPN session, or null if it is not running.
+ */
+ @Nullable
+ public String getSessionId() {
+ return mSessionKey;
+ }
+
+ /**
+ * Returns the always-on status of the PlatformVpnProfile.
+ *
+ * <p>If the PlatformVpnProfile is set to be running in always-on mode, the system will ensure
+ * that the profile is always started, and restarting it when necessary (e.g. after reboot).
+ *
+ * <p>Always-on can be set by an appropriately privileged user via the Settings VPN menus, or by
+ * the Device Policy Manager app programmatically.
+ *
+ * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
+ */
+ public boolean isAlwaysOn() {
+ return mAlwaysOn;
+ }
+
+ /**
+ * Returns the lockdown mode status of the PlatformVpnProfile.
+ *
+ * <p>In lockdown mode, the system will ensure that apps are not allowed to bypass the VPN,
+ * including during startup or failure of the VPN.
+ *
+ * <p>Lockdown mode can be set by an appropriately privileged user via the Settings VPN menus,
+ * or by the Device Policy Manager app programmatically.
+ *
+ * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
+ */
+ public boolean isLockdownEnabled() {
+ return mLockdown;
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mState);
+ out.writeString(mSessionKey);
+ out.writeBoolean(mAlwaysOn);
+ out.writeBoolean(mLockdown);
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<VpnProfileState> CREATOR =
+ new Parcelable.Creator<VpnProfileState>() {
+ public VpnProfileState createFromParcel(Parcel in) {
+ return new VpnProfileState(in);
+ }
+
+ public VpnProfileState[] newArray(int size) {
+ return new VpnProfileState[size];
+ }
+ };
+
+ private VpnProfileState(Parcel in) {
+ mState = in.readInt();
+ mSessionKey = in.readString();
+ mAlwaysOn = in.readBoolean();
+ mLockdown = in.readBoolean();
+ }
+}
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 5bf1b04..ef33543 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -125,7 +125,6 @@
boolean isUserKeyUnlocked(int userId) = 65;
void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66;
void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67;
- boolean isConvertibleToFBE() = 68;
void addUserKeyAuth(int userId, int serialNumber, in byte[] secret) = 70;
void fixateNewestUserKeyAuth(int userId) = 71;
void fstrim(int flags, IVoldTaskListener listener) = 72;
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 0d5ef34..5b59b21 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1425,25 +1425,6 @@
public static final String KEY_TYPE = "key_type";
/**
- * MVNO type:
- * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
- * <P> Type: TEXT </P>
- */
- public static final String MVNO_TYPE = "mvno_type";
-
- /**
- * MVNO data.
- * Use the following examples.
- * <ul>
- * <li>SPN: A MOBILE, BEN NL, ...</li>
- * <li>IMSI: 302720x94, 2060188, ...</li>
- * <li>GID: 4E, 33, ...</li>
- * </ul>
- * <P> Type: TEXT </P>
- */
- public static final String MVNO_MATCH_DATA = "mvno_match_data";
-
- /**
* The carrier public key that is used for the IMSI encryption.
* <P> Type: TEXT </P>
*/
@@ -1470,6 +1451,11 @@
public static final String LAST_MODIFIED = "last_modified";
/**
+ * Carrier ID of the operetor.
+ * <P> Type: TEXT </P>
+ */
+ public static final String CARRIER_ID = "carrier_id";
+ /**
* The {@code content://} style URL for this table.
*/
@NonNull
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index aebc5e8..01a037a 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -140,6 +140,10 @@
/** An in-memory config override for use during tests. */
@Nullable
+ private Integer mPortForTests;
+
+ /** An in-memory config override for use during tests. */
+ @Nullable
private Duration mTimeoutForTests;
// Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
@@ -163,9 +167,11 @@
* Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
* test value, i.e. so the normal value will be used next time.
*/
- public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+ public void setServerConfigForTests(
+ @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) {
synchronized (this) {
mHostnameForTests = hostname;
+ mPortForTests = port;
mTimeoutForTests = timeout;
}
}
@@ -195,8 +201,9 @@
if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
final SntpClient client = new SntpClient();
final String serverName = connectionInfo.getServer();
+ final int port = connectionInfo.getPort();
final int timeoutMillis = connectionInfo.getTimeoutMillis();
- if (client.requestTime(serverName, timeoutMillis, network)) {
+ if (client.requestTime(serverName, port, timeoutMillis, network)) {
long ntpCertainty = client.getRoundTripTime() / 2;
mTimeResult = new TimeResult(
client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
@@ -297,10 +304,12 @@
private static class NtpConnectionInfo {
@NonNull private final String mServer;
+ private final int mPort;
private final int mTimeoutMillis;
- NtpConnectionInfo(@NonNull String server, int timeoutMillis) {
+ NtpConnectionInfo(@NonNull String server, int port, int timeoutMillis) {
mServer = Objects.requireNonNull(server);
+ mPort = port;
mTimeoutMillis = timeoutMillis;
}
@@ -309,6 +318,11 @@
return mServer;
}
+ @NonNull
+ public int getPort() {
+ return mPort;
+ }
+
int getTimeoutMillis() {
return mTimeoutMillis;
}
@@ -317,6 +331,7 @@
public String toString() {
return "NtpConnectionInfo{"
+ "mServer='" + mServer + '\''
+ + ", mPort='" + mPort + '\''
+ ", mTimeoutMillis=" + mTimeoutMillis
+ '}';
}
@@ -341,6 +356,13 @@
}
}
+ final Integer port;
+ if (mPortForTests != null) {
+ port = mPortForTests;
+ } else {
+ port = SntpClient.STANDARD_NTP_PORT;
+ }
+
final int timeoutMillis;
if (mTimeoutForTests != null) {
timeoutMillis = (int) mTimeoutForTests.toMillis();
@@ -350,7 +372,8 @@
timeoutMillis = Settings.Global.getInt(
resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
}
- return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis);
+ return TextUtils.isEmpty(hostname) ? null :
+ new NtpConnectionInfo(hostname, port, timeoutMillis);
}
/** Prints debug information. */
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index e6c911e..3833976 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -9,3 +9,6 @@
per-file *Assist* = file:/core/java/android/service/voice/OWNERS
per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
+# System language settings
+per-file *Locale* = file:platform/packages/apps/Settings:/src/com/android/settings/localepicker/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java
index b400b9b..1299d7f 100644
--- a/core/tests/coretests/src/android/net/SntpClientTest.java
+++ b/core/tests/coretests/src/android/net/SntpClientTest.java
@@ -293,7 +293,8 @@
@Test
public void testDnsResolutionFailure() throws Exception {
- assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000, mNetwork));
+ assertFalse(mClient.requestTime("ntp.server.doesnotexist.example",
+ SntpClient.STANDARD_NTP_PORT, 5000, mNetwork));
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index b89e8bc..625f52a 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -232,7 +232,7 @@
assertThat(entry3.handlerClassName).isEqualTo(
"com.android.internal.os.LooperStatsTest$TestHandlerSecond");
assertThat(entry3.messageName).startsWith(
- "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda4");
+ "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda");
assertThat(entry3.messageCount).isEqualTo(1);
assertThat(entry3.recordedMessageCount).isEqualTo(1);
assertThat(entry3.exceptionCount).isEqualTo(0);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c9abee2..e608a74 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -292,6 +292,8 @@
<!-- Needed for test only -->
<permission name="android.permission.BATTERY_PREDICTION"/>
<permission name="android.permission.BATTERY_STATS"/>
+ <!-- BLUETOOTH_PRIVILEGED is needed for test only -->
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
<permission name="android.permission.BIND_APPWIDGET"/>
<permission name="android.permission.CHANGE_APP_IDLE_STATE"/>
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index ec56d61..ad1405a 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -25,7 +25,8 @@
/**
* <p>A class for producing sounds that match those produced by various actions
- * taken by the media and camera APIs. </p>
+ * taken by the media and camera APIs. It is recommended to call methods in this class
+ * in a background thread since it relies on binder calls.</p>
*
* <p>This class is recommended for use with the {@link android.hardware.camera2} API, since the
* camera2 API does not play any sounds on its own for any capture or video recording actions.</p>
@@ -109,7 +110,7 @@
/**
* <p>Returns true if the application must play the shutter sound in accordance
- * to certain regional restrictions. </p>
+ * to certain regional restrictions.</p>
*
* <p>If this method returns true, applications are strongly recommended to use
* MediaActionSound.play(SHUTTER_CLICK) or START_VIDEO_RECORDING whenever it captures
diff --git a/packages/DynamicSystemInstallationService/Android.bp b/packages/DynamicSystemInstallationService/Android.bp
index ad86f46..b8f54b3 100644
--- a/packages/DynamicSystemInstallationService/Android.bp
+++ b/packages/DynamicSystemInstallationService/Android.bp
@@ -22,6 +22,9 @@
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
+ static_libs: [
+ "DynamicSystemInstallationService-logtags",
+ ],
resource_dirs: ["res"],
certificate: "platform",
@@ -32,3 +35,8 @@
enabled: false,
},
}
+
+java_library {
+ name: "DynamicSystemInstallationService-logtags",
+ srcs: ["src/**/*.logtags"],
+}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index f8cb5d3..02128d4 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -58,6 +58,7 @@
import android.os.image.DynamicSystemClient;
import android.os.image.DynamicSystemManager;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import android.widget.Toast;
@@ -104,6 +105,36 @@
private static final int NOTIFICATION_ID = 1;
/*
+ * Event log tags
+ */
+ private static final int EVENT_DSU_PROGRESS_UPDATE = 120000;
+ private static final int EVENT_DSU_INSTALL_COMPLETE = 120001;
+ private static final int EVENT_DSU_INSTALL_FAILED = 120002;
+
+ protected static void logEventProgressUpdate(
+ String partition,
+ long installedSize,
+ long partitionSize,
+ int partitionNumber,
+ int totalPartitionNumber) {
+ EventLog.writeEvent(
+ EVENT_DSU_PROGRESS_UPDATE,
+ partition,
+ installedSize,
+ partitionSize,
+ partitionNumber,
+ totalPartitionNumber);
+ }
+
+ protected static void logEventComplete() {
+ EventLog.writeEvent(EVENT_DSU_INSTALL_COMPLETE);
+ }
+
+ protected static void logEventFailed(String cause) {
+ EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
+ }
+
+ /*
* IPC
*/
/** Keeps track of all current registered clients. */
@@ -132,15 +163,10 @@
private DynamicSystemManager mDynSystem;
private NotificationManager mNM;
- private int mNumInstalledPartitions;
-
- private String mCurrentPartitionName;
- private long mCurrentPartitionSize;
- private long mCurrentPartitionInstalledSize;
-
// This is for testing only now
private boolean mEnableWhenCompleted;
+ private InstallationAsyncTask.Progress mInstallTaskProgress;
private InstallationAsyncTask mInstallTask;
@@ -203,17 +229,21 @@
@Override
public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
- mCurrentPartitionName = progress.partitionName;
- mCurrentPartitionSize = progress.partitionSize;
- mCurrentPartitionInstalledSize = progress.installedSize;
- mNumInstalledPartitions = progress.numInstalledPartitions;
+ logEventProgressUpdate(
+ progress.partitionName,
+ progress.installedSize,
+ progress.partitionSize,
+ progress.partitionNumber,
+ progress.totalPartitionNumber);
+ mInstallTaskProgress = progress;
postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
}
@Override
public void onResult(int result, Throwable detail) {
if (result == RESULT_OK) {
+ logEventComplete();
postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null);
// For testing: enable DSU and restart the device when install completed
@@ -223,6 +253,12 @@
return;
}
+ if (result == RESULT_CANCELLED) {
+ logEventFailed("Dynamic System installation task is canceled by the user.");
+ } else {
+ logEventFailed("error: " + detail);
+ }
+
boolean removeNotification = false;
switch (result) {
case RESULT_CANCELLED:
@@ -251,16 +287,20 @@
private void executeInstallCommand(Intent intent) {
if (!verifyRequest(intent)) {
Log.e(TAG, "Verification failed. Did you use VerificationActivity?");
+ logEventFailed("VerificationActivity");
return;
}
if (mInstallTask != null) {
Log.e(TAG, "There is already an installation task running");
+ logEventFailed("There is already an ongoing installation task.");
return;
}
if (isInDynamicSystem()) {
Log.e(TAG, "We are already running in DynamicSystem");
+ logEventFailed(
+ "Cannot start a Dynamic System installation task within a Dynamic System.");
return;
}
@@ -445,19 +485,22 @@
case STATUS_IN_PROGRESS:
builder.setContentText(getString(R.string.notification_install_inprogress));
- int max = 1024;
- int progress = 0;
+ if (mInstallTaskProgress != null) {
+ int max = 1024;
+ int progress = 0;
- int currentMax = max >> (mNumInstalledPartitions + 1);
- progress = max - currentMax * 2;
+ int currentMax = max >> mInstallTaskProgress.partitionNumber;
+ progress = max - currentMax * 2;
- long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax
- / Math.max(mCurrentPartitionSize >> 20, 1);
+ long currentProgress =
+ (mInstallTaskProgress.installedSize >> 20)
+ * currentMax
+ / Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
- progress += (int) currentProgress;
+ progress += (int) currentProgress;
- builder.setProgress(max, progress, false);
-
+ builder.setProgress(max, progress, false);
+ }
builder.addAction(new Notification.Action.Builder(
null, getString(R.string.notification_action_cancel),
createPendingIntent(ACTION_CANCEL_INSTALL)).build());
@@ -563,13 +606,13 @@
StringBuilder msg = new StringBuilder();
msg.append("status: " + statusString + ", cause: " + causeString);
- if (status == STATUS_IN_PROGRESS) {
+ if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) {
msg.append(
String.format(
", partition name: %s, progress: %d/%d",
- mCurrentPartitionName,
- mCurrentPartitionInstalledSize,
- mCurrentPartitionSize));
+ mInstallTaskProgress.partitionName,
+ mInstallTaskProgress.installedSize,
+ mInstallTaskProgress.partitionSize));
}
if (detail != null) {
msg.append(", detail: " + detail);
@@ -594,7 +637,10 @@
Bundle bundle = new Bundle();
// TODO: send more info to the clients
- bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize);
+ if (mInstallTaskProgress != null) {
+ bundle.putLong(
+ DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize);
+ }
if (detail != null) {
bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL,
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
new file mode 100644
index 0000000..eae9de9
--- /dev/null
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
@@ -0,0 +1,7 @@
+# See system/logging/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.dynsystem
+
+120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5)
+120001 dsu_install_complete
+120002 dsu_install_failed (cause|3)
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index f18d426..998aeeab 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -23,9 +23,11 @@
import android.os.Build;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.os.image.DynamicSystemManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Log;
+import android.util.Range;
import android.webkit.URLUtil;
import org.json.JSONException;
@@ -44,11 +46,16 @@
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
-class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> {
+class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask";
- private static final int READ_BUFFER_SIZE = 1 << 13;
+ private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB
+ private static final int MAX_SHARED_MEMORY_SIZE = 1024 << 10; // 1MiB
+ private static final int DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB
+ private static final String SHARED_MEMORY_SIZE_PROP =
+ "dynamic_system.data_transfer.shared_memory.size";
+
private static final long MIN_PROGRESS_TO_PUBLISH = 1 << 27;
private static final List<String> UNSUPPORTED_PARTITIONS =
@@ -106,14 +113,22 @@
static class Progress {
public final String partitionName;
+ public final long installedSize;
public final long partitionSize;
- public final int numInstalledPartitions;
- public long installedSize;
+ public final int partitionNumber;
+ public final int totalPartitionNumber;
- Progress(String partitionName, long partitionSize, int numInstalledPartitions) {
+ Progress(
+ String partitionName,
+ long installedSize,
+ long partitionSize,
+ int partitionNumber,
+ int totalPartitionNumber) {
this.partitionName = partitionName;
+ this.installedSize = installedSize;
this.partitionSize = partitionSize;
- this.numInstalledPartitions = numInstalledPartitions;
+ this.partitionNumber = partitionNumber;
+ this.totalPartitionNumber = totalPartitionNumber;
}
}
@@ -123,6 +138,7 @@
void onResult(int resultCode, Throwable detail);
}
+ private final int mSharedMemorySize;
private final String mUrl;
private final String mDsuSlot;
private final String mPublicKey;
@@ -139,7 +155,10 @@
private boolean mIsZip;
private boolean mIsCompleted;
- private int mNumInstalledPartitions;
+ private String mPartitionName;
+ private long mPartitionSize;
+ private int mPartitionNumber;
+ private int mTotalPartitionNumber;
private InputStream mStream;
private ZipFile mZipFile;
@@ -153,6 +172,11 @@
Context context,
DynamicSystemManager dynSystem,
ProgressListener listener) {
+ mSharedMemorySize =
+ Range.create(MIN_SHARED_MEMORY_SIZE, MAX_SHARED_MEMORY_SIZE)
+ .clamp(
+ SystemProperties.getInt(
+ SHARED_MEMORY_SIZE_PROP, DEFAULT_SHARED_MEMORY_SIZE));
mUrl = url;
mDsuSlot = dsuSlot;
mPublicKey = publicKey;
@@ -175,11 +199,15 @@
protected Throwable doInBackground(String... voids) {
Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
+ final boolean wantScratchPartition = Build.IS_DEBUGGABLE;
try {
// call DynamicSystemManager to cleanup stuff
mDynSystem.remove();
verifyAndPrepare();
+ if (wantScratchPartition) {
+ ++mTotalPartitionNumber;
+ }
mDynSystem.startInstallation(mDsuSlot);
@@ -198,7 +226,7 @@
return null;
}
- if (Build.IS_DEBUGGABLE) {
+ if (wantScratchPartition) {
// If host is debuggable, then install a scratch partition so that we can do
// adb remount in the guest system.
try {
@@ -262,9 +290,14 @@
}
@Override
- protected void onProgressUpdate(Progress... values) {
- Progress progress = values[0];
- mListener.onProgressUpdate(progress);
+ protected void onProgressUpdate(Long... installedSize) {
+ mListener.onProgressUpdate(
+ new Progress(
+ mPartitionName,
+ installedSize[0],
+ mPartitionSize,
+ mPartitionNumber,
+ mTotalPartitionNumber));
}
private void verifyAndPrepare() throws Exception {
@@ -281,12 +314,16 @@
throw new UnsupportedFormatException(
String.format(Locale.US, "Unsupported file format: %s", mUrl));
}
+ // At least two partitions, {system, userdata}
+ mTotalPartitionNumber = 2;
if (mIsNetworkUrl) {
mStream = new URL(mUrl).openStream();
} else if (URLUtil.isFileUrl(mUrl)) {
if (mIsZip) {
mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
+ // {*.img in zip} + {userdata}
+ mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1;
} else {
mStream = new URL(mUrl).openStream();
}
@@ -333,9 +370,13 @@
}
};
- thread.start();
- Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
+ mPartitionName = partitionName;
+ mPartitionSize = partitionSize;
+ ++mPartitionNumber;
+ publishProgress(/* installedSize = */ 0L);
+ long prevInstalledSize = 0;
+ thread.start();
while (thread.isAlive()) {
if (isCancelled()) {
return;
@@ -343,9 +384,9 @@
final long installedSize = mDynSystem.getInstallationProgress().bytes_processed;
- if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
- progress.installedSize = installedSize;
- publishProgress(progress);
+ if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+ publishProgress(installedSize);
+ prevInstalledSize = installedSize;
}
try {
@@ -392,14 +433,42 @@
installImage("system", mSystemSize, new GZIPInputStream(mStream));
}
+ private boolean shouldInstallEntry(String name) {
+ if (!name.endsWith(".img")) {
+ return false;
+ }
+ String partitionName = name.substring(0, name.length() - 4);
+ if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
+ return false;
+ }
+ return true;
+ }
+
+ private int calculateNumberOfImagesInLocalZip(ZipFile zipFile) {
+ int total = 0;
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if (shouldInstallEntry(entry.getName())) {
+ ++total;
+ }
+ }
+ return total;
+ }
+
private void installStreamingZipUpdate() throws IOException, ImageValidationException {
Log.d(TAG, "To install a streaming ZIP update");
ZipInputStream zis = new ZipInputStream(mStream);
- ZipEntry zipEntry = null;
+ ZipEntry entry = null;
- while ((zipEntry = zis.getNextEntry()) != null) {
- installImageFromAnEntry(zipEntry, zis);
+ while ((entry = zis.getNextEntry()) != null) {
+ String name = entry.getName();
+ if (shouldInstallEntry(name)) {
+ installImageFromAnEntry(entry, zis);
+ } else {
+ Log.d(TAG, name + " installation is not supported, skip it.");
+ }
if (isCancelled()) {
break;
@@ -414,7 +483,12 @@
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
- installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
+ String name = entry.getName();
+ if (shouldInstallEntry(name)) {
+ installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
+ } else {
+ Log.d(TAG, name + " installation is not supported, skip it.");
+ }
if (isCancelled()) {
break;
@@ -422,28 +496,16 @@
}
}
- private boolean installImageFromAnEntry(ZipEntry entry, InputStream is)
+ private void installImageFromAnEntry(ZipEntry entry, InputStream is)
throws IOException, ImageValidationException {
String name = entry.getName();
Log.d(TAG, "ZipEntry: " + name);
- if (!name.endsWith(".img")) {
- return false;
- }
-
String partitionName = name.substring(0, name.length() - 4);
-
- if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
- Log.d(TAG, name + " installation is not supported, skip it.");
- return false;
- }
-
long uncompressedSize = entry.getSize();
installImage(partitionName, uncompressedSize, is);
-
- return true;
}
private void installImage(String partitionName, long uncompressedSize, InputStream is)
@@ -492,18 +554,22 @@
Log.d(TAG, "Start installing: " + partitionName);
- MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, READ_BUFFER_SIZE);
+ MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, mSharedMemorySize);
ParcelFileDescriptor pfd = new ParcelFileDescriptor(memoryFile.getFileDescriptor());
- mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE);
+ mInstallationSession.setAshmem(pfd, memoryFile.length());
- Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
+ mPartitionName = partitionName;
+ mPartitionSize = partitionSize;
+ ++mPartitionNumber;
+ publishProgress(/* installedSize = */ 0L);
+ long prevInstalledSize = 0;
long installedSize = 0;
- byte[] bytes = new byte[READ_BUFFER_SIZE];
+ byte[] bytes = new byte[memoryFile.length()];
int numBytesRead;
- while ((numBytesRead = sis.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {
+ while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) {
if (isCancelled()) {
return;
}
@@ -516,9 +582,9 @@
installedSize += numBytesRead;
- if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
- progress.installedSize = installedSize;
- publishProgress(progress);
+ if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+ publishProgress(installedSize);
+ prevInstalledSize = installedSize;
}
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
index 4117d0f..7d23266 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -133,36 +133,32 @@
return mLeft == 0;
}
- /**
- * It overrides the InputStream.read(byte[] buf)
- */
- public int read(byte[] buf) throws IOException {
+ @Override
+ public int read(byte[] buf, int off, int len) throws IOException {
if (!mIsSparse) {
- return mIn.read(buf);
+ return mIn.read(buf, off, len);
}
if (prepareChunk()) return -1;
int n = -1;
switch (mCur.mChunkType) {
case SparseChunk.RAW:
- n = mIn.read(buf, 0, (int) min(mLeft, buf.length));
+ n = mIn.read(buf, off, (int) min(mLeft, len));
mLeft -= n;
return n;
case SparseChunk.DONTCARE:
- n = (int) min(mLeft, buf.length);
- Arrays.fill(buf, 0, n - 1, (byte) 0);
+ n = (int) min(mLeft, len);
+ Arrays.fill(buf, off, off + n, (byte) 0);
mLeft -= n;
return n;
case SparseChunk.FILL:
// The FILL type is rarely used, so use a simple implmentation.
- return super.read(buf);
+ return super.read(buf, off, len);
default:
throw new IOException("Unsupported Chunk:" + mCur.toString());
}
}
- /**
- * It overrides the InputStream.read()
- */
+ @Override
public int read() throws IOException {
if (!mIsSparse) {
return mIn.read();
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a56c490..534e41c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1038,23 +1038,6 @@
<!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
<string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string>
- <!-- Developer settings screen, convert userdata to file encryption option name -->
- <string name="convert_to_file_encryption">Convert to file encryption</string>
- <!-- Developer settings screen, convert userdata to file encryption summary when option is available -->
- <string name="convert_to_file_encryption_enabled">Convert\u2026</string>
- <!-- Developer settings screen, convert userdata to file encryption summary when option is already done -->
- <string name="convert_to_file_encryption_done">Already file encrypted</string>
- <!-- Title used on dialog with final prompt for converting to file encryption -->
- <string name="title_convert_fbe">Converting to file based encryption</string>
- <!-- Warning displayed on dialog with final prompt for converting to file encryption -->
- <string name="convert_to_fbe_warning">
- Convert data partition to file based encryption.\n
- !!Warning!! This will erase all your data.\n
- This feature is alpha, and may not work correctly.\n
- Press \'Wipe and convert\u2026\' to continue.</string>
- <!-- Button on dialog that triggers convertion to file encryption -->
- <string name="button_convert_fbe">Wipe and convert\u2026</string>
-
<!-- Name of feature to change color setting for the display [CHAR LIMIT=60] -->
<string name="picture_color_mode">Picture color mode</string>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8f2ac9f..feee4a1 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -121,6 +121,8 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+ <!-- BLUETOOTH_PRIVILEGED is needed for testing purposes only. -->
+ <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e00b941..6f46b70 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -664,4 +664,17 @@
<!-- Flag to enable privacy dot views, it shall be true for normal case -->
<bool name="config_enablePrivacyDot">true</bool>
+ <!-- Icons that don't show in a collapsed non-keyguard statusbar -->
+ <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false">
+ <item>@*android:string/status_bar_volume</item>
+ <item>@*android:string/status_bar_alarm_clock</item>
+ <item>@*android:string/status_bar_call_strength</item>
+ </string-array>
+
+ <!-- Icons that don't show in a collapsed statusbar on keyguard -->
+ <string-array name="config_keyguard_statusbar_icon_blocklist" translatable="false">
+ <item>@*android:string/status_bar_volume</item>
+ <item>@*android:string/status_bar_alarm_clock</item>
+ <item>@*android:string/status_bar_call_strength</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index e7d5724..810b95b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -263,10 +263,8 @@
);
Resources r = getResources();
- mBlockedIcons = Collections.unmodifiableList(Arrays.asList(
- r.getString(com.android.internal.R.string.status_bar_volume),
- r.getString(com.android.internal.R.string.status_bar_alarm_clock),
- r.getString(com.android.internal.R.string.status_bar_call_strength)));
+ mBlockedIcons = Arrays.asList(r.getStringArray(
+ R.array.config_keyguard_statusbar_icon_blocklist));
mNotificationsHeaderCollideDistance = r.getDimensionPixelSize(
R.dimen.header_notifications_collide_distance);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index d6ba6f3..2670ed8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -69,6 +69,7 @@
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
@@ -190,9 +191,8 @@
}
mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons), mFeatureFlags);
mDarkIconManager.setShouldLog(true);
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_volume));
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
- mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
+ mBlockedIcons = Arrays.asList(getResources().getStringArray(
+ R.array.config_collapsed_statusbar_icon_blocklist));
mDarkIconManager.setBlockList(mBlockedIcons);
mStatusBarIconController.addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 3f712dd..3801c24 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -2260,10 +2260,12 @@
ACCOUNTS_WORK_PROFILE_SETTINGS = 401;
// Settings -> Dev options -> Convert to file encryption
- CONVERT_FBE = 402;
+ // DEPRECATED: this setting was removed in Android T.
+ CONVERT_FBE = 402 [deprecated=true];
// Settings -> Dev options -> Convert to file encryption -> WIPE AND CONVERT...
- CONVERT_FBE_CONFIRM = 403;
+ // DEPRECATED: this setting was removed in Android T.
+ CONVERT_FBE_CONFIRM = 403 [deprecated=true];
// Settings -> Dev options -> Running services
RUNNING_SERVICES = 404;
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 186ff62..2015dc9 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -196,13 +196,15 @@
* Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
* test value, i.e. so the normal value will be used next time.
*/
- void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+ void setServerConfigForTests(
+ @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) {
mContext.enforceCallingPermission(
android.Manifest.permission.SET_TIME, "set NTP server config for tests");
mLocalLog.log("Setting server config for tests: hostname=" + hostname
+ + ", port=" + port
+ ", timeout=" + timeout);
- mTime.setServerConfigForTests(hostname, timeout);
+ mTime.setServerConfigForTests(hostname, port, timeout);
}
private void onPollNetworkTime(int event) {
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
index 464af01..d7504ce 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
@@ -46,6 +46,7 @@
*/
private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config";
private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname";
+ private static final String SET_SERVER_CONFIG_PORT_ARG = "--port";
private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis";
@NonNull
@@ -87,6 +88,7 @@
private int runSetServerConfig() {
String hostname = null;
+ Integer port = null;
Duration timeout = null;
String opt;
while ((opt = getNextArg()) != null) {
@@ -95,6 +97,10 @@
hostname = getNextArgRequired();
break;
}
+ case SET_SERVER_CONFIG_PORT_ARG: {
+ port = Integer.parseInt(getNextArgRequired());
+ break;
+ }
case SET_SERVER_CONFIG_TIMEOUT_ARG: {
timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired()));
break;
@@ -104,7 +110,7 @@
}
}
}
- mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout);
+ mNetworkTimeUpdateService.setServerConfigForTests(hostname, port, timeout);
return 0;
}
@@ -120,8 +126,9 @@
pw.printf(" Refreshes the latest time. Prints whether it was successful.\n");
pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
pw.printf(" Sets the NTP server config for tests. The config is not persisted.\n");
- pw.printf(" Options: [%s <hostname>] [%s <millis>]\n",
- SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG);
+ pw.printf(" Options: [%s <hostname>] [%s <port>] [%s <millis>]\n",
+ SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_PORT_ARG,
+ SET_SERVER_CONFIG_TIMEOUT_ARG);
pw.printf(" Each key/value is optional and must be specified to override the\n");
pw.printf(" normal value, not specifying a key causes it to reset to the original.\n");
pw.println();
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 9c8cb8c..9f32888 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3072,23 +3072,6 @@
}
/**
- * Is userdata convertible to file based encryption?
- * @return non zero for convertible
- */
- @Override
- public boolean isConvertibleToFBE() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- try {
- return mVold.isConvertibleToFbe();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return false;
- }
- }
-
- /**
* Check whether the device supports filesystem checkpointing.
*
* @return true if the device supports filesystem checkpointing, false otherwise.
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 811f2f5..382359a 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2009,10 +2009,8 @@
return;
}
- ApnSetting apnSetting = preciseState.getApnSetting();
-
synchronized (mRecords) {
- if (validatePhoneId(phoneId)) {
+ if (validatePhoneId(phoneId) && preciseState.getApnSetting() != null) {
Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(),
preciseState.getApnSetting());
PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId)
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 7b8cce5..c1d8e7b 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -37,6 +37,7 @@
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
import android.net.VpnManager;
+import android.net.VpnProfileState;
import android.net.VpnService;
import android.net.util.NetdService;
import android.os.Binder;
@@ -374,6 +375,24 @@
}
/**
+ * Retrieve the VpnProfileState for the profile provisioned by the given package.
+ *
+ * @return the VpnProfileState with current information, or null if there was no profile
+ * provisioned by the given package.
+ * @hide
+ */
+ @Override
+ @Nullable
+ public VpnProfileState getProvisionedVpnProfileState(@NonNull String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ verifyCallingUidAndPackage(packageName, callingUid);
+ final int user = UserHandle.getUserId(callingUid);
+ synchronized (mVpns) {
+ return mVpns.get(user).getProvisionedVpnProfileState(packageName);
+ }
+ }
+
+ /**
* Start legacy VPN, controlling native daemons as needed. Creates a
* secondary thread to perform connection work, returning quickly.
*
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 956f34f..96ea6db 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -547,7 +547,6 @@
uids.clear();
uids.put(uidRec.getUid(), uidRec);
updateUidsLSP(uids, SystemClock.elapsedRealtime());
- mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(uids);
}
}
@@ -1268,8 +1267,6 @@
}
}
- mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
-
return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
}
@@ -1304,6 +1301,11 @@
@GuardedBy({"mService", "mProcLock"})
private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
+ // This compares previously set procstate to the current procstate in regards to whether
+ // or not the app's network access will be blocked. So, this needs to be called before
+ // we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}.
+ mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
+
ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
becameIdle.clear();
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c0df095..a6da4a6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -75,6 +75,7 @@
import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.VpnManager;
+import android.net.VpnProfileState;
import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.ChildSessionCallback;
@@ -3438,6 +3439,45 @@
}
}
+ private @VpnProfileState.State int getStateFromLegacyState(int legacyState) {
+ switch (legacyState) {
+ case LegacyVpnInfo.STATE_CONNECTING:
+ return VpnProfileState.STATE_CONNECTING;
+ case LegacyVpnInfo.STATE_CONNECTED:
+ return VpnProfileState.STATE_CONNECTED;
+ case LegacyVpnInfo.STATE_DISCONNECTED:
+ return VpnProfileState.STATE_DISCONNECTED;
+ case LegacyVpnInfo.STATE_FAILED:
+ return VpnProfileState.STATE_FAILED;
+ default:
+ Log.wtf(TAG, "Unhandled state " + legacyState
+ + ", treat it as STATE_DISCONNECTED");
+ return VpnProfileState.STATE_DISCONNECTED;
+ }
+ }
+
+ private VpnProfileState makeVpnProfileState() {
+ // TODO: mSessionKey will be moved to Ikev2VpnRunner once aosp/2007077 is merged, so after
+ // merging aosp/2007077, here should check Ikev2VpnRunner is null or not. Session key will
+ // be null if Ikev2VpnRunner is null.
+ return new VpnProfileState(getStateFromLegacyState(mLegacyState), mSessionKey, mAlwaysOn,
+ mLockdown);
+ }
+
+ /**
+ * Retrieve the VpnProfileState for the profile provisioned by the given package.
+ *
+ * @return the VpnProfileState with current information, or null if there was no profile
+ * provisioned by the given package.
+ */
+ @Nullable
+ public synchronized VpnProfileState getProvisionedVpnProfileState(
+ @NonNull String packageName) {
+ requireNonNull(packageName, "No package name provided");
+ enforceNotRestrictedUser();
+ return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileState() : null;
+ }
+
/**
* Proxy to allow testing
*
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 71cc361..470aa0e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -118,9 +118,7 @@
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
import static com.android.internal.util.XmlUtils.readStringAttribute;
-import static com.android.internal.util.XmlUtils.readThisIntArrayXml;
import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
-import static com.android.internal.util.XmlUtils.writeIntArrayXml;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
@@ -243,7 +241,6 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.StatLogger;
-import com.android.internal.util.XmlUtils;
import com.android.net.module.util.NetworkIdentityUtils;
import com.android.net.module.util.NetworkStatsUtils;
import com.android.net.module.util.PermissionUtils;
@@ -257,8 +254,6 @@
import libcore.io.IoUtils;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -334,7 +329,8 @@
private static final int VERSION_ADDED_CYCLE = 11;
private static final int VERSION_ADDED_NETWORK_TYPES = 12;
private static final int VERSION_SUPPORTED_CARRIER_USAGE = 13;
- private static final int VERSION_LATEST = VERSION_SUPPORTED_CARRIER_USAGE;
+ private static final int VERSION_REMOVED_SUBSCRIPTION_PLANS = 14;
+ private static final int VERSION_LATEST = VERSION_REMOVED_SUBSCRIPTION_PLANS;
@VisibleForTesting
public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING;
@@ -347,7 +343,6 @@
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
- private static final String TAG_SUBSCRIPTION_PLAN = "subscription-plan";
private static final String TAG_UID_POLICY = "uid-policy";
private static final String TAG_APP_POLICY = "app-policy";
private static final String TAG_WHITELIST = "whitelist";
@@ -426,6 +421,13 @@
* obj = oldBlockedReasons
*/
private static final int MSG_BLOCKED_REASON_CHANGED = 21;
+ /**
+ * Message to indicate that subscription plans expired and should be cleared.
+ * arg1 = subId
+ * arg2 = setSubscriptionPlans call ID
+ * obj = callingPackage
+ */
+ private static final int MSG_CLEAR_SUBSCRIPTION_PLANS = 22;
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -492,6 +494,12 @@
/** Map from subId to package name that owns subscription plans. */
@GuardedBy("mNetworkPoliciesSecondLock")
final SparseArray<String> mSubscriptionPlansOwner = new SparseArray<>();
+ /** Map from subId to the ID of the clear plans request. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ final SparseIntArray mSetSubscriptionPlansIds = new SparseIntArray();
+ /** Atomic integer to generate a new ID for each clear plans request. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ int mSetSubscriptionPlansIdCounter = 0;
/** Map from subId to daily opportunistic quota. */
@GuardedBy("mNetworkPoliciesSecondLock")
@@ -2553,56 +2561,6 @@
warningBytes, limitBytes, lastWarningSnooze,
lastLimitSnooze, metered, inferred));
}
-
- } else if (TAG_SUBSCRIPTION_PLAN.equals(tag)) {
- final String start = readStringAttribute(in, ATTR_CYCLE_START);
- final String end = readStringAttribute(in, ATTR_CYCLE_END);
- final String period = readStringAttribute(in, ATTR_CYCLE_PERIOD);
- final SubscriptionPlan.Builder builder = new SubscriptionPlan.Builder(
- RecurrenceRule.convertZonedDateTime(start),
- RecurrenceRule.convertZonedDateTime(end),
- RecurrenceRule.convertPeriod(period));
- builder.setTitle(readStringAttribute(in, ATTR_TITLE));
- builder.setSummary(readStringAttribute(in, ATTR_SUMMARY));
-
- final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES,
- SubscriptionPlan.BYTES_UNKNOWN);
- final int limitBehavior = readIntAttribute(in, ATTR_LIMIT_BEHAVIOR,
- SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN);
- if (limitBytes != SubscriptionPlan.BYTES_UNKNOWN
- && limitBehavior != SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN) {
- builder.setDataLimit(limitBytes, limitBehavior);
- }
-
- final long usageBytes = readLongAttribute(in, ATTR_USAGE_BYTES,
- SubscriptionPlan.BYTES_UNKNOWN);
- final long usageTime = readLongAttribute(in, ATTR_USAGE_TIME,
- SubscriptionPlan.TIME_UNKNOWN);
- if (usageBytes != SubscriptionPlan.BYTES_UNKNOWN
- && usageTime != SubscriptionPlan.TIME_UNKNOWN) {
- builder.setDataUsage(usageBytes, usageTime);
- }
-
- final int subId = readIntAttribute(in, ATTR_SUB_ID);
- final String ownerPackage = readStringAttribute(in, ATTR_OWNER_PACKAGE);
-
- if (version >= VERSION_ADDED_NETWORK_TYPES) {
- final int depth = in.getDepth();
- while (XmlUtils.nextElementWithin(in, depth)) {
- if (TAG_XML_UTILS_INT_ARRAY.equals(in.getName())
- && ATTR_NETWORK_TYPES.equals(
- readStringAttribute(in, ATTR_XML_UTILS_NAME))) {
- final int[] networkTypes =
- readThisIntArrayXml(in, TAG_XML_UTILS_INT_ARRAY, null);
- builder.setNetworkTypes(networkTypes);
- }
- }
- }
-
- final SubscriptionPlan plan = builder.build();
- mSubscriptionPlans.put(subId, ArrayUtils.appendElement(
- SubscriptionPlan.class, mSubscriptionPlans.get(subId), plan));
- mSubscriptionPlansOwner.put(subId, ownerPackage);
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
final int policy = readIntAttribute(in, ATTR_POLICY);
@@ -2793,38 +2751,6 @@
out.endTag(null, TAG_NETWORK_POLICY);
}
- // write all known subscription plans
- for (int i = 0; i < mSubscriptionPlans.size(); i++) {
- final int subId = mSubscriptionPlans.keyAt(i);
- if (subId == INVALID_SUBSCRIPTION_ID) continue;
- final String ownerPackage = mSubscriptionPlansOwner.get(subId);
- final SubscriptionPlan[] plans = mSubscriptionPlans.valueAt(i);
- if (ArrayUtils.isEmpty(plans)) continue;
-
- for (SubscriptionPlan plan : plans) {
- out.startTag(null, TAG_SUBSCRIPTION_PLAN);
- writeIntAttribute(out, ATTR_SUB_ID, subId);
- writeStringAttribute(out, ATTR_OWNER_PACKAGE, ownerPackage);
- final RecurrenceRule cycleRule = plan.getCycleRule();
- writeStringAttribute(out, ATTR_CYCLE_START,
- RecurrenceRule.convertZonedDateTime(cycleRule.start));
- writeStringAttribute(out, ATTR_CYCLE_END,
- RecurrenceRule.convertZonedDateTime(cycleRule.end));
- writeStringAttribute(out, ATTR_CYCLE_PERIOD,
- RecurrenceRule.convertPeriod(cycleRule.period));
- writeStringAttribute(out, ATTR_TITLE, plan.getTitle());
- writeStringAttribute(out, ATTR_SUMMARY, plan.getSummary());
- writeLongAttribute(out, ATTR_LIMIT_BYTES, plan.getDataLimitBytes());
- writeIntAttribute(out, ATTR_LIMIT_BEHAVIOR, plan.getDataLimitBehavior());
- writeLongAttribute(out, ATTR_USAGE_BYTES, plan.getDataUsageBytes());
- writeLongAttribute(out, ATTR_USAGE_TIME, plan.getDataUsageTime());
- try {
- writeIntArrayXml(plan.getNetworkTypes(), ATTR_NETWORK_TYPES, out);
- } catch (XmlPullParserException ignored) { }
- out.endTag(null, TAG_SUBSCRIPTION_PLAN);
- }
- }
-
// write all known uid policies
for (int i = 0; i < mUidPolicy.size(); i++) {
final int uid = mUidPolicy.keyAt(i);
@@ -3698,7 +3624,8 @@
}
@Override
- public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
+ public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans,
+ long expirationDurationMillis, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
enforceSubscriptionPlanValidity(plans);
@@ -3708,34 +3635,47 @@
final long token = Binder.clearCallingIdentity();
try {
- synchronized (mUidRulesFirstLock) {
- synchronized (mNetworkPoliciesSecondLock) {
- mSubscriptionPlans.put(subId, plans);
- mSubscriptionPlansOwner.put(subId, callingPackage);
-
- final String subscriberId = mSubIdToSubscriberId.get(subId, null);
- if (subscriberId != null) {
- ensureActiveCarrierPolicyAL(subId, subscriberId);
- maybeUpdateCarrierPolicyCycleAL(subId, subscriberId);
- } else {
- Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
- }
-
- handleNetworkPoliciesUpdateAL(true);
- }
- }
-
- final Intent intent = new Intent(SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
- mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
- mHandler.sendMessage(
- mHandler.obtainMessage(MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
+ setSubscriptionPlansInternal(subId, plans, expirationDurationMillis, callingPackage);
} finally {
Binder.restoreCallingIdentity(token);
}
}
+ private void setSubscriptionPlansInternal(int subId, SubscriptionPlan[] plans,
+ long expirationDurationMillis, String callingPackage) {
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ mSubscriptionPlans.put(subId, plans);
+ mSubscriptionPlansOwner.put(subId, callingPackage);
+
+ final String subscriberId = mSubIdToSubscriberId.get(subId, null);
+ if (subscriberId != null) {
+ ensureActiveCarrierPolicyAL(subId, subscriberId);
+ maybeUpdateCarrierPolicyCycleAL(subId, subscriberId);
+ } else {
+ Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
+ }
+
+ handleNetworkPoliciesUpdateAL(true);
+
+ final Intent intent = new Intent(
+ SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+ mContext.sendBroadcast(intent,
+ android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
+ mHandler.sendMessage(mHandler.obtainMessage(
+ MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
+ final int setPlansId = mSetSubscriptionPlansIdCounter++;
+ mSetSubscriptionPlansIds.put(subId, setPlansId);
+ if (expirationDurationMillis > 0) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_SUBSCRIPTION_PLANS,
+ subId, setPlansId, callingPackage), expirationDurationMillis);
+ }
+ }
+ }
+ }
+
/**
* Only visible for testing purposes. This doesn't give any access to
* existing plans; it simply lets the debug package define new plans.
@@ -3758,7 +3698,7 @@
@Override
public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue,
- int[] networkTypes, long timeoutMillis, String callingPackage) {
+ int[] networkTypes, long expirationDurationMillis, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
final ArraySet<Integer> allNetworksSet = new ArraySet<>();
@@ -3796,10 +3736,10 @@
args.arg3 = overrideValue;
args.arg4 = applicableNetworks.toArray();
mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args));
- if (timeoutMillis > 0) {
+ if (expirationDurationMillis > 0) {
args.arg3 = 0;
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args),
- timeoutMillis);
+ expirationDurationMillis);
}
}
}
@@ -5214,6 +5154,22 @@
mListeners.finishBroadcast();
return true;
}
+ case MSG_CLEAR_SUBSCRIPTION_PLANS: {
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ int subId = msg.arg1;
+ if (msg.arg2 == mSetSubscriptionPlansIds.get(subId)) {
+ if (LOGD) Slog.d(TAG, "Clearing expired subscription plans.");
+ setSubscriptionPlansInternal(subId, new SubscriptionPlan[]{},
+ 0 /* expirationDurationMillis */,
+ (String) msg.obj /* callingPackage */);
+ } else {
+ if (LOGD) Slog.d(TAG, "Ignoring stale CLEAR_SUBSCRIPTION_PLANS.");
+ }
+ }
+ }
+ return true;
+ }
case MSG_BLOCKED_REASON_CHANGED: {
final int uid = msg.arg1;
final int newBlockedReasons = msg.arg2;
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 1393d39..f865a50 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -2238,7 +2238,7 @@
private void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage)
throws InterruptedException {
- mService.setSubscriptionPlans(subId, plans, callingPackage);
+ mService.setSubscriptionPlans(subId, plans, 0, callingPackage);
// setSubscriptionPlans() triggers async events, wait for those to be completed before
// moving forward as they could interfere with the tests later.
postMsgAndWaitForCompletion();
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index e88106c..86b98f1 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -127,7 +127,9 @@
ApnSetting.TYPE_EMERGENCY,
ApnSetting.TYPE_MCX,
ApnSetting.TYPE_XCAP,
- // ApnSetting.TYPE_ENTERPRISE
+ ApnSetting.TYPE_BIP,
+ ApnSetting.TYPE_VSIM,
+ ApnSetting.TYPE_ENTERPRISE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApnType {
@@ -707,6 +709,9 @@
NetworkCapabilities.NET_CAPABILITY_VSIM,
NetworkCapabilities.NET_CAPABILITY_BIP,
NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH
})
public @interface NetCapability { }
@@ -721,4 +726,16 @@
NetworkAgent.VALIDATION_STATUS_NOT_VALID
})
public @interface ValidationStatus {}
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "NET_CAPABILITY_ENTERPRISE_SUB_LEVEL" }, value = {
+ NetworkCapabilities.NET_ENTERPRISE_ID_1,
+ NetworkCapabilities.NET_ENTERPRISE_ID_2,
+ NetworkCapabilities.NET_ENTERPRISE_ID_3,
+ NetworkCapabilities.NET_ENTERPRISE_ID_4,
+ NetworkCapabilities.NET_ENTERPRISE_ID_5
+ })
+
+ public @interface EnterpriseId {}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 4a5a137..ee646d9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5641,6 +5641,13 @@
"telephony_data_handover_retry_rules_string_array";
/**
+ * Indicates whether delay tearing down IMS data network until voice call ends.
+ * @hide
+ */
+ public static final String KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL =
+ "delay_ims_tear_down_until_call_end_bool";
+
+ /**
* The patterns of missed incoming call sms. This is the regular expression used for
* matching the missed incoming call's date, time, and caller id. The pattern should match
* fields for at least month, day, hour, and minute. Year is optional although it is encouraged.
@@ -6458,6 +6465,7 @@
KEY_TELEPHONY_DATA_HANDOVER_RETRY_RULES_STRING_ARRAY, new String[] {
"retry_interval=1000|2000|4000|8000|16000, maximum_retries=5"
});
+ sDefaults.putBoolean(KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL, false);
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
@@ -6469,7 +6477,7 @@
sDefaults.putBoolean(KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true);
sDefaults.putBoolean(KEY_HIDE_ENABLE_2G, false);
sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY,
- new String[]{"ia", "default", "mms", "dun"});
+ new String[]{"ia", "default"});
sDefaults.putBoolean(KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL, false);
sDefaults.putBoolean(KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL, false);
sDefaults.putBoolean(KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL, true);
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 56bf303..3a3b363 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1083,6 +1083,13 @@
*/
public static final int REQUEST_NOT_SUPPORTED = 0x1000A;
+ /**
+ * An internal setup data error initiated by telephony that no retry should be performed.
+ *
+ * @hide
+ */
+ public static final int NO_RETRY_FAILURE = 0x1000B;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
@@ -1515,6 +1522,8 @@
sFailCauseMap.put(DUPLICATE_CID, "DUPLICATE_CID");
sFailCauseMap.put(NO_DEFAULT_DATA, "NO_DEFAULT_DATA");
sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
+ sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED");
+ sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE");
}
private DataFailCause() {
@@ -1565,6 +1574,7 @@
}
/** @hide */
+ // TODO: Migrated to DataConfigManager
public static boolean isPermanentFailure(@NonNull Context context,
@DataFailureCause int failCause,
int subId) {
@@ -1621,6 +1631,7 @@
};
}
+ permanentFailureSet.add(NO_RETRY_FAILURE);
sPermanentFailureCache.put(subId, permanentFailureSet);
}
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index 957f683..1d7c18f 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -22,6 +22,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Objects;
@@ -76,7 +78,8 @@
/**
* @hide
*/
- DataSpecificRegistrationInfo(
+ @VisibleForTesting
+ public DataSpecificRegistrationInfo(
int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable,
boolean isEnDcAvailable, @Nullable VopsSupportInfo vops) {
this.maxDataCalls = maxDataCalls;
@@ -186,7 +189,7 @@
/**
* @return The VOPS (Voice over Packet Switched) support information.
*
- * The instance of {@link LTEVopsSupportInfo}, or {@link NrVopsSupportInfo},
+ * The instance of {@link LteVopsSupportInfo}, or {@link NrVopsSupportInfo},
* null if there is there is no VOPS support information available.
*/
@Nullable
diff --git a/telephony/java/android/telephony/ImsiEncryptionInfo.java b/telephony/java/android/telephony/ImsiEncryptionInfo.java
index 4978692..82333a4 100644
--- a/telephony/java/android/telephony/ImsiEncryptionInfo.java
+++ b/telephony/java/android/telephony/ImsiEncryptionInfo.java
@@ -46,16 +46,17 @@
private final int keyType;
//Date-Time in UTC when the key will expire.
private final Date expirationTime;
+ private final int carrierId;
/** @hide */
public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
- byte[] key, Date expirationTime) {
- this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime);
+ byte[] key, Date expirationTime, int carrierId) {
+ this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime, carrierId);
}
/** @hide */
public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
- PublicKey publicKey, Date expirationTime) {
+ PublicKey publicKey, Date expirationTime, int carrierId) {
// todo need to validate that ImsiEncryptionInfo is being created with the correct params.
// Including validating that the public key is in "X.509" format. This will be done in
// a subsequent CL.
@@ -65,6 +66,7 @@
this.publicKey = publicKey;
this.keyIdentifier = keyIdentifier;
this.expirationTime = expirationTime;
+ this.carrierId = carrierId;
}
/** @hide */
@@ -78,6 +80,7 @@
keyIdentifier = in.readString();
keyType = in.readInt();
expirationTime = new Date(in.readLong());
+ carrierId = in.readInt();
}
/** @hide */
@@ -90,6 +93,11 @@
return this.mcc;
}
+ /** @hide */
+ public int getCarrierId() {
+ return carrierId;
+ }
+
/**
* Returns key identifier, a string that helps the authentication server to locate the
* private key to decrypt the permanent identity, or {@code null} when uavailable.
@@ -157,6 +165,7 @@
dest.writeString(keyIdentifier);
dest.writeInt(keyType);
dest.writeLong(expirationTime.getTime());
+ dest.writeInt(carrierId);
}
@Override
@@ -164,10 +173,11 @@
return "[ImsiEncryptionInfo "
+ "mcc=" + mcc
+ " mnc=" + mnc
- + " publicKey=" + publicKey
+ + ", publicKey=" + publicKey
+ ", keyIdentifier=" + keyIdentifier
+ ", keyType=" + keyType
+ ", expirationTime=" + expirationTime
+ + ", carrier_id=" + carrierId
+ "]";
}
}
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 6a80766..1a5a5ae 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -242,13 +242,16 @@
* @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
* information is not available.
* @param rplmn the registered plmn or the last plmn for attempted registration if reg failed.
+ * @param voiceSpecificInfo Voice specific registration information.
+ * @param dataSpecificInfo Data specific registration information.
*/
private NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
- @RegistrationState int registrationState,
- @NetworkType int accessNetworkTechnology, int rejectCause,
- boolean emergencyOnly,
- @Nullable @ServiceType List<Integer> availableServices,
- @Nullable CellIdentity cellIdentity, @Nullable String rplmn) {
+ @RegistrationState int registrationState,
+ @NetworkType int accessNetworkTechnology, int rejectCause,
+ boolean emergencyOnly, @Nullable @ServiceType List<Integer> availableServices,
+ @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
+ @Nullable VoiceSpecificRegistrationInfo voiceSpecificInfo,
+ @Nullable DataSpecificRegistrationInfo dataSpecificInfo) {
mDomain = domain;
mTransportType = transportType;
mRegistrationState = registrationState;
@@ -262,6 +265,10 @@
mEmergencyOnly = emergencyOnly;
mNrState = NR_STATE_NONE;
mRplmn = rplmn;
+ mVoiceSpecificInfo = voiceSpecificInfo;
+ mDataSpecificInfo = dataSpecificInfo;
+
+ updateNrState();
}
/**
@@ -276,10 +283,9 @@
boolean cssSupported, int roamingIndicator, int systemIsInPrl,
int defaultRoamingIndicator) {
this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
- emergencyOnly, availableServices, cellIdentity, rplmn);
-
- mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
- systemIsInPrl, defaultRoamingIndicator);
+ emergencyOnly, availableServices, cellIdentity, rplmn,
+ new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
+ systemIsInPrl, defaultRoamingIndicator), null);
}
/**
@@ -295,11 +301,9 @@
boolean isNrAvailable, boolean isEndcAvailable,
@Nullable VopsSupportInfo vopsSupportInfo) {
this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
- emergencyOnly, availableServices, cellIdentity, rplmn);
- mDataSpecificInfo = new DataSpecificRegistrationInfo(
- maxDataCalls, isDcNrRestricted, isNrAvailable,
- isEndcAvailable, vopsSupportInfo);
- updateNrState();
+ emergencyOnly, availableServices, cellIdentity, rplmn, null,
+ new DataSpecificRegistrationInfo(maxDataCalls, isDcNrRestricted, isNrAvailable,
+ isEndcAvailable, vopsSupportInfo));
}
private NetworkRegistrationInfo(Parcel source) {
@@ -804,6 +808,12 @@
@NonNull
private String mRplmn = "";
+ @Nullable
+ private DataSpecificRegistrationInfo mDataSpecificRegistrationInfo;
+
+ @Nullable
+ private VoiceSpecificRegistrationInfo mVoiceSpecificRegistrationInfo;
+
/**
* Default constructor for Builder.
*/
@@ -930,6 +940,30 @@
}
/**
+ * Set voice specific registration information.
+ *
+ * @param info The voice specific registration information.
+ * @return The builder.
+ * @hide
+ */
+ public @NonNull Builder setVoiceSpecificInfo(@NonNull VoiceSpecificRegistrationInfo info) {
+ mVoiceSpecificRegistrationInfo = info;
+ return this;
+ }
+
+ /**
+ * Set data specific registration information.
+ *
+ * @param info The data specific registration information.
+ * @return The builder.
+ * @hide
+ */
+ public @NonNull Builder setDataSpecificInfo(@NonNull DataSpecificRegistrationInfo info) {
+ mDataSpecificRegistrationInfo = info;
+ return this;
+ }
+
+ /**
* Build the NetworkRegistrationInfo.
* @return the NetworkRegistrationInfo object.
* @hide
@@ -938,7 +972,8 @@
public @NonNull NetworkRegistrationInfo build() {
return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
- mCellIdentity, mRplmn);
+ mCellIdentity, mRplmn, mVoiceSpecificRegistrationInfo,
+ mDataSpecificRegistrationInfo);
}
}
}
diff --git a/telephony/java/android/telephony/PcoData.java b/telephony/java/android/telephony/PcoData.java
index bcfbcf8b..39e4f2f 100644
--- a/telephony/java/android/telephony/PcoData.java
+++ b/telephony/java/android/telephony/PcoData.java
@@ -19,6 +19,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* Contains Carrier-specific (and opaque) Protocol configuration Option
* Data. In general this is only passed on to carrier-specific applications
@@ -84,4 +87,22 @@
return "PcoData(" + cid + ", " + bearerProto + ", " + pcoId + ", contents[" +
contents.length + "])";
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PcoData pcoData = (PcoData) o;
+ return cid == pcoData.cid
+ && pcoId == pcoData.pcoId
+ && Objects.equals(bearerProto, pcoData.bearerProto)
+ && Arrays.equals(contents, pcoData.contents);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(cid, bearerProto, pcoId);
+ result = 31 * result + Arrays.hashCode(contents);
+ return result;
+ }
}
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 95448c7..d91134e 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -23,12 +23,15 @@
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
+import com.android.telephony.Rlog;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
public final class PhysicalChannelConfig implements Parcelable {
+ static final String TAG = "PhysicalChannelConfig";
// TODO(b/72993578) consolidate these enums in a central location.
/** @hide */
@@ -568,19 +571,21 @@
public @NonNull Builder setNetworkType(@NetworkType int networkType) {
if (!TelephonyManager.isNetworkTypeValid(networkType)) {
- throw new IllegalArgumentException("Network type: " + networkType + " is invalid.");
+ Rlog.e(TAG, "Builder.setNetworkType: Network type " + networkType + " is invalid.");
+ } else {
+ mNetworkType = networkType;
}
- mNetworkType = networkType;
return this;
}
public @NonNull Builder setFrequencyRange(int frequencyRange) {
if (!ServiceState.isFrequencyRangeValid(frequencyRange)
&& frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
- throw new IllegalArgumentException("Frequency range: " + frequencyRange +
- " is invalid.");
+ Rlog.e(TAG, "Builder.setFrequencyRange: Frequency range " + frequencyRange
+ + " is invalid.");
+ } else {
+ mFrequencyRange = frequencyRange;
}
- mFrequencyRange = frequencyRange;
return this;
}
@@ -596,19 +601,21 @@
public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
- throw new IllegalArgumentException("Cell downlink bandwidth(kHz): " +
- cellBandwidthDownlinkKhz + " is invalid.");
+ Rlog.e(TAG, "Builder.setCellBandwidthDownlinkKhz: Cell downlink bandwidth(kHz) "
+ + cellBandwidthDownlinkKhz + " is invalid.");
+ } else {
+ mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
}
- mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
return this;
}
public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
- throw new IllegalArgumentException("Cell uplink bandwidth(kHz): "+
- cellBandwidthUplinkKhz +" is invalid.");
+ Rlog.e(TAG, "Builder.setCellBandwidthUplinkKhz: Cell uplink bandwidth(kHz) "
+ + cellBandwidthUplinkKhz + " is invalid.");
+ } else {
+ mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
}
- mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
return this;
}
@@ -625,19 +632,20 @@
public @NonNull Builder setPhysicalCellId(int physicalCellId) {
if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
- throw new IllegalArgumentException("Physical cell Id: " + physicalCellId +
- " is over limit.");
+ Rlog.e(TAG, "Builder.setPhysicalCellId: Physical cell ID " + physicalCellId
+ + " is over limit.");
+ } else {
+ mPhysicalCellId = physicalCellId;
}
- mPhysicalCellId = physicalCellId;
return this;
}
public @NonNull Builder setBand(int band) {
if (band <= BAND_UNKNOWN) {
- throw new IllegalArgumentException("Band: " + band +
- " is invalid.");
+ Rlog.e(TAG, "Builder.setBand: Band " + band + " is invalid.");
+ } else {
+ mBand = band;
}
- mBand = band;
return this;
}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 9fd2ae4..753935a 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1205,7 +1205,15 @@
}
}
- private void init() {
+ /**
+ * Initialize the service state. Set everything to the default value.
+ *
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+ * {@link NetworkRegistrationInfo}.
+ */
+ private void init(boolean legacyMode) {
if (DBG) Rlog.d(LOG_TAG, "init");
mVoiceRegState = STATE_OUT_OF_SERVICE;
mDataRegState = STATE_OUT_OF_SERVICE;
@@ -1237,6 +1245,13 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
+ if (!legacyMode) {
+ addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+ .build());
+ }
}
mOperatorAlphaLongRaw = null;
mOperatorAlphaShortRaw = null;
@@ -1245,15 +1260,32 @@
}
public void setStateOutOfService() {
- init();
+ init(true);
}
public void setStateOff() {
- init();
+ init(true);
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
}
+ /**
+ * Set the service state to out-of-service
+ *
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+ * @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on).
+ * @hide
+ */
+ public void setOutOfService(boolean legacyMode, boolean powerOff) {
+ init(legacyMode);
+ if (powerOff) {
+ mVoiceRegState = STATE_POWER_OFF;
+ mDataRegState = STATE_POWER_OFF;
+ }
+ }
+
public void setState(int state) {
setVoiceRegState(state);
if (DBG) Rlog.e(LOG_TAG, "[ServiceState] setState deprecated use setVoiceRegState()");
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c6c797e..4b8b590 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2792,10 +2792,43 @@
* outlined above.
* @throws IllegalArgumentException if plans don't meet the requirements
* defined in {@link SubscriptionPlan}.
+ * @deprecated use {@link #setSubscriptionPlans(int, List, long)} instead.
*/
+ @Deprecated
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
+ setSubscriptionPlans(subId, plans, 0);
+ }
+
+ /**
+ * Set the description of the billing relationship plan between a carrier
+ * and a specific subscriber.
+ * <p>
+ * This method is only accessible to the following narrow set of apps:
+ * <ul>
+ * <li>The carrier app for this subscriberId, as determined by
+ * {@link TelephonyManager#hasCarrierPrivileges()}.
+ * <li>The carrier app explicitly delegated access through
+ * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+ * </ul>
+ *
+ * @param subId the subscriber this relationship applies to. An empty list
+ * may be sent to clear any existing plans.
+ * @param plans the list of plans. The first plan is always the primary and
+ * most important plan. Any additional plans are secondary and
+ * may not be displayed or used by decision making logic.
+ * @param expirationDurationMillis the duration after which the subscription plans
+ * will be automatically cleared, or {@code 0} to leave the plans until
+ * explicitly cleared, or the next reboot, whichever happens first.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
+ * @throws IllegalArgumentException if plans don't meet the requirements
+ * defined in {@link SubscriptionPlan}.
+ */
+ public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans,
+ @DurationMillisLong long expirationDurationMillis) {
getNetworkPolicyManager().setSubscriptionPlans(subId,
- plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName());
+ plans.toArray(new SubscriptionPlan[0]), expirationDurationMillis,
+ mContext.getOpPackageName());
}
/**
@@ -2814,17 +2847,17 @@
* @param subId the subscriber this override applies to.
* @param overrideUnmetered set if the billing relationship should be
* considered unmetered.
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
*/
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
setSubscriptionOverrideUnmetered(subId, overrideUnmetered,
- TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+ TelephonyManager.getAllNetworkTypes(), expirationDurationMillis);
}
/**
@@ -2846,8 +2879,8 @@
* @param networkTypes the network types this override applies to. If no
* network types are specified, override values will be ignored.
* {@see TelephonyManager#getAllNetworkTypes()}
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
@@ -2855,10 +2888,10 @@
*/
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@NonNull @Annotation.NetworkType int[] networkTypes,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0;
getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED,
- overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
+ overrideValue, networkTypes, expirationDurationMillis, mContext.getOpPackageName());
}
/**
@@ -2878,17 +2911,17 @@
* @param subId the subscriber this override applies to.
* @param overrideCongested set if the subscription should be considered
* congested.
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
*/
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
setSubscriptionOverrideCongested(subId, overrideCongested,
- TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+ TelephonyManager.getAllNetworkTypes(), expirationDurationMillis);
}
/**
@@ -2911,8 +2944,8 @@
* @param networkTypes the network types this override applies to. If no
* network types are specified, override values will be ignored.
* {@see TelephonyManager#getAllNetworkTypes()}
- * @param timeoutMillis the timeout after which the requested override will
- * be automatically cleared, or {@code 0} to leave in the
+ * @param expirationDurationMillis the duration after which the requested override
+ * will be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
@@ -2920,10 +2953,10 @@
*/
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
@NonNull @Annotation.NetworkType int[] networkTypes,
- @DurationMillisLong long timeoutMillis) {
+ @DurationMillisLong long expirationDurationMillis) {
final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0;
getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED,
- overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
+ overrideValue, networkTypes, expirationDurationMillis, mContext.getOpPackageName());
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 63ff232..8c8e203 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -140,6 +140,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
@@ -3475,15 +3476,39 @@
* @see #SIM_STATE_PRESENT
*
* @hide
+ * @deprecated instead use {@link #getSimCardState(int, int)}
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Deprecated
public @SimState int getSimCardState(int physicalSlotIndex) {
- int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
+ int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, DEFAULT_PORT_INDEX));
return getSimCardStateFromSimState(simState);
}
/**
+ * Returns a constant indicating the state of the device SIM card in a physical slot and
+ * port index.
+ *
+ * @param physicalSlotIndex physical slot index
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ *
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_ABSENT
+ * @see #SIM_STATE_CARD_IO_ERROR
+ * @see #SIM_STATE_CARD_RESTRICTED
+ * @see #SIM_STATE_PRESENT
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @SimState int getSimCardState(int physicalSlotIndex, int portIndex) {
+ int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, portIndex));
+ return getSimCardStateFromSimState(simState);
+ }
+ /**
* Converts SIM state to SIM card state.
* @param simState
* @return SIM card state
@@ -3503,13 +3528,19 @@
/**
* Converts a physical slot index to logical slot index.
* @param physicalSlotIndex physical slot index
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
* @return logical slot index
*/
- private int getLogicalSlotIndex(int physicalSlotIndex) {
+ private int getLogicalSlotIndex(int physicalSlotIndex, int portIndex) {
UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length
&& slotInfos[physicalSlotIndex] != null) {
- return slotInfos[physicalSlotIndex].getLogicalSlotIdx();
+ for (UiccPortInfo portInfo : slotInfos[physicalSlotIndex].getPorts()) {
+ if (portInfo.getPortIndex() == portIndex) {
+ return portInfo.getLogicalSlotIndex();
+ }
+ }
}
return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
@@ -3549,12 +3580,42 @@
* @see #SIM_STATE_LOADED
*
* @hide
+ * @deprecated instead use {@link #getSimApplicationState(int, int)}
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Deprecated
public @SimState int getSimApplicationState(int physicalSlotIndex) {
int simState =
- SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+ DEFAULT_PORT_INDEX));
+ return getSimApplicationStateFromSimState(simState);
+ }
+
+ /**
+ * Returns a constant indicating the state of the card applications on the device SIM card in
+ * a physical slot.
+ *
+ * @param physicalSlotIndex physical slot index
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+ *
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_PIN_REQUIRED
+ * @see #SIM_STATE_PUK_REQUIRED
+ * @see #SIM_STATE_NETWORK_LOCKED
+ * @see #SIM_STATE_NOT_READY
+ * @see #SIM_STATE_PERM_DISABLED
+ * @see #SIM_STATE_LOADED
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @SimState int getSimApplicationState(int physicalSlotIndex, int portIndex) {
+ int simState =
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+ portIndex));
return getSimApplicationStateFromSimState(simState);
}
@@ -4153,18 +4214,21 @@
* should be {@link #getPhoneCount()} if success, otherwise return an empty map.
*
* @hide
+ * @deprecated use {@link #getSimSlotMapping()} instead.
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@NonNull
+ @Deprecated
public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
Map<Integer, Integer> slotMapping = new HashMap<>();
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- int[] slotMappingArray = telephony.getSlotsMapping(mContext.getOpPackageName());
- for (int i = 0; i < slotMappingArray.length; i++) {
- slotMapping.put(i, slotMappingArray[i]);
+ List<UiccSlotMapping> simSlotsMapping = telephony.getSlotsMapping(
+ mContext.getOpPackageName());
+ for (UiccSlotMapping slotMap : simSlotsMapping) {
+ slotMapping.put(slotMap.getLogicalSlotIndex(), slotMap.getPhysicalSlotIndex());
}
}
} catch (RemoteException e) {
@@ -4173,6 +4237,33 @@
return slotMapping;
}
+ /**
+ * Get the mapping from logical slots to physical sim slots and port indexes. Initially the
+ * logical slot index was mapped to physical slot index, but with support for multi-enabled
+ * profile(MEP) logical slot is now mapped to port index.
+ *
+ * @return a collection of {@link UiccSlotMapping} which indicates the mapping from logical
+ * slots to ports and physical slots.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @NonNull
+ public Collection<UiccSlotMapping> getSimSlotMapping() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ slotMap = telephony.getSlotsMapping(mContext.getOpPackageName());
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ return slotMap;
+ }
//
//
// Subscriber Info
@@ -16138,6 +16229,8 @@
* Callback to listen for when the set of packages with carrier privileges for a SIM changes.
*
* @hide
+ * @deprecated Use {@link CarrierPrivilegesCallback} instead. This API will be removed soon
+ * prior to API finalization.
*/
@SystemApi
public interface CarrierPrivilegesListener {
@@ -16158,6 +16251,54 @@
}
/**
+ * Callbacks to listen for when the set of packages with carrier privileges for a SIM changes.
+ *
+ * <p>Of note, when multiple callbacks are registered, they may be triggered one after another.
+ * The ordering of them is not guaranteed and thus should not be depend on.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface CarrierPrivilegesCallback {
+ /**
+ * Called when the set of packages with carrier privileges has changed.
+ *
+ * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+ * switch and the same set of packages remains privileged after the switch.
+ *
+ * <p>At registration, the callback will receive the current set of privileged packages.
+ *
+ * @param privilegedPackageNames The updated set of package names that have carrier
+ * privileges
+ * @param privilegedUids The updated set of UIDs that have carrier privileges
+ */
+ void onCarrierPrivilegesChanged(
+ @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids);
+
+ /**
+ * Called when the {@link CarrierService} for the current user profile has changed.
+ *
+ * <p>This method does nothing by default. Clients that are interested in the carrier
+ * service change should override this method to get package name and UID info.
+ *
+ * <p>At registration, the callback will receive the current carrier service info.
+ *
+ * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+ * switch and the same carrier service remains after switch.
+ *
+ * @param carrierServicePackageName package name of the {@link CarrierService}. May be
+ * {@code null} when no carrier service is detected.
+ * @param carrierServiceUid UID of the {@link CarrierService}. May be
+ * {@link android.os.Process#INVALID_UID} if no carrier
+ * service is detected.
+ */
+ default void onCarrierServiceChanged(
+ @Nullable String carrierServicePackageName, int carrierServiceUid) {
+ // do nothing by default
+ }
+ }
+
+ /**
* Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
* receive callbacks when the set of packages with carrier privileges changes. The callback will
* immediately be called with the latest state.
@@ -16166,7 +16307,10 @@
* @param executor The executor where {@code listener} will be invoked
* @param listener The callback to register
* @hide
+ * @deprecated Use {@link #registerCarrierPrivilegesCallback} instead. This API will be
+ * removed prior to API finalization.
*/
+ @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void addCarrierPrivilegesListener(
@@ -16190,7 +16334,10 @@
* Unregisters an existing {@link CarrierPrivilegesListener}.
*
* @hide
+ * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
+ * removed prior to API finalization.
*/
+ @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
@@ -16205,4 +16352,36 @@
}
mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
}
+
+ /**
+ * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
+ * receive callbacks when the set of packages with carrier privileges changes. The callback will
+ * immediately be called with the latest state.
+ *
+ * @param logicalSlotIndex The SIM slot to listen on
+ * @param executor The executor where {@code callback} will be invoked
+ * @param callback The callback to register
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void registerCarrierPrivilegesCallback(
+ int logicalSlotIndex,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CarrierPrivilegesCallback callback) {
+ // TODO(b/216549778): cherry-pick implementation once merge conflict is resolved
+ throw new UnsupportedOperationException("Not implemented, yet");
+ }
+
+ /**
+ * Unregisters an existing {@link CarrierPrivilegesCallback}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void unregisterCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
+ // TODO(b/216549778): cherry-pick implementation once merge conflict is resolved
+ throw new UnsupportedOperationException("Not implemented, yet");
+ }
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index f854020..281b018 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1272,24 +1272,34 @@
*/
public boolean similar(ApnSetting other) {
return (!this.canHandleType(TYPE_DUN)
- && !other.canHandleType(TYPE_DUN)
- && Objects.equals(this.mApnName, other.mApnName)
- && !typeSameAny(this, other)
- && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
- && xorEqualsInt(this.mProxyPort, other.mProxyPort)
- && xorEquals(this.mProtocol, other.mProtocol)
- && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(this.mProfileId, other.mProfileId)
- && Objects.equals(this.mMvnoType, other.mMvnoType)
- && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
- && xorEquals(this.mMmsc, other.mMmsc)
- && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
- && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
- && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId)
- && Objects.equals(mCarrierId, other.mCarrierId)
- && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
+ && xorEqualsInt(this.mProxyPort, other.mProxyPort)
+ && xorEquals(this.mMmsc, other.mMmsc)
+ && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
+ && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
+ && xorEqualsString(this.mUser, other.mUser)
+ && xorEqualsString(this.mPassword, other.mPassword)
+ && xorEqualsInt(this.mAuthType, other.mAuthType)
+ && !typeSameAny(this, other)
+ && Objects.equals(this.mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(this.mProtocol, other.mProtocol)
+ && Objects.equals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && xorEqualsInt(this.mMtuV4, other.mMtuV4)
+ && xorEqualsInt(this.mMtuV6, other.mMtuV6)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(this.mLingeringNetworkTypeBitmask,
+ other.mLingeringNetworkTypeBitmask)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mPersistent, other.mPersistent)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(this.mApnSetId, other.mApnSetId)
+ && Objects.equals(this.mCarrierId, other.mCarrierId)
+ && Objects.equals(this.mSkip464Xlat, other.mSkip464Xlat)
+ && Objects.equals(this.mAlwaysOn, other.mAlwaysOn);
}
// Equal or one is null.
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index ec04c1a..0b361dc 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -26,10 +26,10 @@
import android.net.NetworkCapabilities;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.NetCapability;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
+import android.telephony.data.ApnSetting.ApnType;
import android.telephony.data.ApnSetting.AuthType;
import android.text.TextUtils;
@@ -245,8 +245,7 @@
* @return The supported APN types bitmask.
* @deprecated Use {@link #getApnSetting()} and {@link ApnSetting#getApnTypeBitmask()} instead.
*/
- @Deprecated
- public @ApnType int getSupportedApnTypesBitmask() {
+ @Deprecated public @ApnType int getSupportedApnTypesBitmask() {
if (mApnSetting != null) {
return mApnSetting.getApnTypeBitmask();
}
@@ -425,6 +424,12 @@
return ApnSetting.TYPE_MCX;
case NetworkCapabilities.NET_CAPABILITY_IA:
return ApnSetting.TYPE_IA;
+ case NetworkCapabilities.NET_CAPABILITY_BIP:
+ return ApnSetting.TYPE_BIP;
+ case NetworkCapabilities.NET_CAPABILITY_VSIM:
+ return ApnSetting.TYPE_VSIM;
+ case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE:
+ return ApnSetting.TYPE_ENTERPRISE;
default:
return ApnSetting.TYPE_NONE;
}
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 13d8c7b..ec73471 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -253,8 +253,10 @@
return "RESULT_ERROR_BUSY";
case RESULT_ERROR_ILLEGAL_STATE:
return "RESULT_ERROR_ILLEGAL_STATE";
+ case RESULT_ERROR_TEMPORARILY_UNAVAILABLE:
+ return "RESULT_ERROR_TEMPORARILY_UNAVAILABLE";
default:
- return "Missing case for result code=" + resultCode;
+ return "Unknown(" + resultCode + ")";
}
}
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
index 2178fc1..66dcf8f 100644
--- a/telephony/java/android/telephony/data/TrafficDescriptor.java
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -21,8 +21,13 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for UE Route Selection
@@ -31,24 +36,215 @@
* not specify the end point to be used for the data call.
*/
public final class TrafficDescriptor implements Parcelable {
+ /**
+ * The OS/App id
+ *
+ * @hide
+ */
+ public static final class OsAppId {
+ /**
+ * OSId for "Android", using UUID version 5 with namespace ISO OSI.
+ * Prepended to the OsAppId in TrafficDescriptor to use for URSP matching.
+ */
+ public static final UUID ANDROID_OS_ID =
+ UUID.fromString("97a498e3-fc92-5c94-8986-0333d06e4e47");
+
+ /**
+ * Allowed app ids.
+ */
+ // The following app ids are the only apps id Android supports. OEMs or vendors are
+ // prohibited to modify/extend the allowed list, especially passing the real package name to
+ // the network.
+ private static final Set<String> ALLOWED_APP_IDS = Set.of(
+ "ENTERPRISE", "PRIORITIZE_LATENCY", "PRIORITIZE_BANDWIDTH", "CBS"
+ );
+
+ /** OS id in UUID format. */
+ private final @NonNull UUID mOsId;
+
+ /**
+ * App id in string format. Note that Android will not allow use specific app id. This must
+ * be a category/capability identifier.
+ */
+ private final @NonNull String mAppId;
+
+ /**
+ * The differentiator when multiple traffic descriptor has the same OS and app id. Must be
+ * greater than 1.
+ */
+ private final int mDifferentiator;
+
+ /**
+ * Constructor
+ *
+ * @param osId OS id in UUID format.
+ * @param appId App id in string format. Note that Android will not allow use specific app
+ * id. This must be a category/capability identifier.
+ */
+ public OsAppId(@NonNull UUID osId, @NonNull String appId) {
+ this(osId, appId, 1);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param osId OS id in UUID format.
+ * @param appId App id in string format. Note that Android will not allow use specific app
+ * id. This must be a category/capability identifier.
+ * @param differentiator The differentiator when multiple traffic descriptor has the same
+ * OS and app id. Must be greater than 0.
+ */
+ public OsAppId(@NonNull UUID osId, @NonNull String appId, int differentiator) {
+ Objects.requireNonNull(osId);
+ Objects.requireNonNull(appId);
+ if (differentiator < 1) {
+ throw new IllegalArgumentException("Invalid differentiator " + differentiator);
+ }
+
+ mOsId = osId;
+ mAppId = appId;
+ mDifferentiator = differentiator;
+ }
+
+ /**
+ * Constructor from raw byte array.
+ *
+ * @param rawOsAppId The raw OS/App id.
+ */
+ public OsAppId(@NonNull byte[] rawOsAppId) {
+ try {
+ ByteBuffer bb = ByteBuffer.wrap(rawOsAppId);
+ // OS id is the first 16 bytes.
+ mOsId = new UUID(bb.getLong(), bb.getLong());
+ // App id length is 1 byte.
+ int appIdLen = bb.get();
+ // The remaining is the app id + differentiator.
+ byte[] appIdAndDifferentiator = new byte[appIdLen];
+ bb.get(appIdAndDifferentiator, 0, appIdLen);
+ // Extract trailing numbers, for example, "ENTERPRISE", "ENTERPRISE3".
+ String appIdAndDifferentiatorStr = new String(appIdAndDifferentiator);
+ Pattern pattern = Pattern.compile("[^0-9]+([0-9]+)$");
+ Matcher matcher = pattern.matcher(new String(appIdAndDifferentiator));
+ if (matcher.find()) {
+ mDifferentiator = Integer.parseInt(matcher.group(1));
+ mAppId = appIdAndDifferentiatorStr.replace(matcher.group(1), "");
+ } else {
+ mDifferentiator = 1;
+ mAppId = appIdAndDifferentiatorStr;
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to decode " + (rawOsAppId != null
+ ? new BigInteger(1, rawOsAppId).toString(16) : null));
+ }
+ }
+
+ /**
+ * @return The OS id in UUID format.
+ */
+ public @NonNull UUID getOsId() {
+ return mOsId;
+ }
+
+ /**
+ * @return App id in string format. Note that Android will not allow use specific app id.
+ * This must be a category/capability identifier.
+ */
+ public @NonNull String getAppId() {
+ return mAppId;
+ }
+
+ /**
+ * @return The differentiator when multiple traffic descriptor has the same OS and app id.
+ * Must be greater than 1.
+ */
+ public int getDifferentiator() {
+ return mDifferentiator;
+ }
+
+ /**
+ * @return OS/App id in raw byte format.
+ */
+ public @NonNull byte[] getBytes() {
+ byte[] osAppId = (mAppId + (mDifferentiator > 1 ? mDifferentiator : "")).getBytes();
+ // 16 bytes for UUID, 1 byte for length of osAppId, and up to 255 bytes for osAppId
+ ByteBuffer bb = ByteBuffer.allocate(16 + 1 + osAppId.length);
+ bb.putLong(mOsId.getMostSignificantBits());
+ bb.putLong(mOsId.getLeastSignificantBits());
+ bb.put((byte) osAppId.length);
+ bb.put(osAppId);
+ return bb.array();
+ }
+
+ @Override
+ public String toString() {
+ return "[OsAppId: OS=" + mOsId + ", App=" + mAppId + ", differentiator="
+ + mDifferentiator + ", raw="
+ + new BigInteger(1, getBytes()).toString(16) + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ OsAppId osAppId = (OsAppId) o;
+ return mDifferentiator == osAppId.mDifferentiator && mOsId.equals(osAppId.mOsId)
+ && mAppId.equals(osAppId.mAppId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mOsId, mAppId, mDifferentiator);
+ }
+ }
+
private final String mDnn;
- private final byte[] mOsAppId;
+ private final OsAppId mOsAppId;
private TrafficDescriptor(@NonNull Parcel in) {
mDnn = in.readString();
- mOsAppId = in.createByteArray();
+ byte[] osAppIdBytes = in.createByteArray();
+ OsAppId osAppId = null;
+ if (osAppIdBytes != null) {
+ osAppId = new OsAppId(osAppIdBytes);
+ }
+ mOsAppId = osAppId;
+
+ enforceAllowedIds();
}
/**
* Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
* @param dnn optional DNN, which must be used for traffic matching, if present
- * @param osAppId OsId + osAppId of the traffic descriptor
+ * @param osAppIdRawBytes Raw bytes of OsId + osAppId of the traffic descriptor
*
* @hide
*/
- public TrafficDescriptor(String dnn, byte[] osAppId) {
+ public TrafficDescriptor(String dnn, @Nullable byte[] osAppIdRawBytes) {
mDnn = dnn;
+ OsAppId osAppId = null;
+ if (osAppIdRawBytes != null) {
+ osAppId = new OsAppId(osAppIdRawBytes);
+ }
mOsAppId = osAppId;
+
+ enforceAllowedIds();
+ }
+
+ /**
+ * Enforce the OS id and app id are in the allowed list.
+ *
+ * @throws IllegalArgumentException if ids are not allowed.
+ */
+ private void enforceAllowedIds() {
+ if (mOsAppId != null && !mOsAppId.getOsId().equals(OsAppId.ANDROID_OS_ID)) {
+ throw new IllegalArgumentException("OS id " + mOsAppId.getOsId() + " does not match "
+ + OsAppId.ANDROID_OS_ID);
+ }
+
+ if (mOsAppId != null && !OsAppId.ALLOWED_APP_IDS.contains(mOsAppId.getAppId())) {
+ throw new IllegalArgumentException("Illegal app id " + mOsAppId.getAppId()
+ + ". Only allowing one of the following " + OsAppId.ALLOWED_APP_IDS);
+ }
}
/**
@@ -61,13 +257,13 @@
}
/**
- * OsAppId is the app id as defined in 3GPP TS 24.526 Section 5.2, and it identifies a traffic
- * category. It includes the OS Id component of the field as defined in the specs.
- * @return the OS App ID of this traffic descriptor if one is included by the network, null
- * otherwise.
+ * OsAppId identifies a broader traffic category. Although it names Os/App id, it only includes
+ * OS version with a general/broader category id used as app id.
+ *
+ * @return The id in byte format. {@code null} if not available.
*/
public @Nullable byte[] getOsAppId() {
- return mOsAppId;
+ return mOsAppId != null ? mOsAppId.getBytes() : null;
}
@Override
@@ -77,13 +273,13 @@
@NonNull @Override
public String toString() {
- return "TrafficDescriptor={mDnn=" + mDnn + ", mOsAppId=" + mOsAppId + "}";
+ return "TrafficDescriptor={mDnn=" + mDnn + ", " + mOsAppId + "}";
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mDnn);
- dest.writeByteArray(mOsAppId);
+ dest.writeByteArray(mOsAppId != null ? mOsAppId.getBytes() : null);
}
public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR =
@@ -104,7 +300,7 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrafficDescriptor that = (TrafficDescriptor) o;
- return Objects.equals(mDnn, that.mDnn) && Arrays.equals(mOsAppId, that.mOsAppId);
+ return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId);
}
@Override
@@ -148,7 +344,7 @@
}
/**
- * Set the OS App ID (including OS Id as defind in the specs).
+ * Set the OS App ID (including OS Id as defined in the specs).
*
* @return The same instance of the builder.
*/
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 683bb92..82d64ab 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -618,9 +618,9 @@
ITelephony iTelephony = getITelephony();
if (iTelephony == null) {
- throw new RuntimeException("Could not find Telephony Service.");
+ Log.w("ImsMmTelManager", "Could not find Telephony Service.");
+ return;
}
-
try {
iTelephony.unregisterMmTelCapabilityCallback(mSubId, c.getBinder());
} catch (RemoteException e) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 0ac7cf9..e1da407 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2153,9 +2153,9 @@
String callingFeatureId);
/**
- * Get the mapping from logical slots to physical slots.
+ * Get the mapping from logical slots to port index.
*/
- int[] getSlotsMapping(String callingPackage);
+ List<UiccSlotMapping> getSlotsMapping(String callingPackage);
/**
* Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown
diff --git a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
index 35f1e58..644d450 100644
--- a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
+++ b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
@@ -24,6 +24,8 @@
import android.os.Environment;
import android.util.Log;
+import libcore.io.Streams;
+
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -37,8 +39,6 @@
import java.net.URL;
import java.util.Random;
-import libcore.io.Streams;
-
/*
* Test Service that tries to connect to the web via different methods and outputs the results to
* the log and a output file.
@@ -146,7 +146,7 @@
final ConnectivityManager mCM = context.getSystemService(ConnectivityManager.class);
final Network network = mCM.getActiveNetwork();
- if (client.requestTime("0.pool.ntp.org", 10000, network)) {
+ if (client.requestTime("0.pool.ntp.org", SntpClient.STANDARD_NTP_PORT, 10000, network)) {
return true;
}
return false;
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index 816bc6b..9db19a3 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1 +1,2 @@
include /core/java/android/media/soundtrigger/OWNERS
+mdooley@google.com