diff options
48 files changed, 1251 insertions, 180 deletions
diff --git a/.prebuilt_info/OWNERS b/.prebuilt_info/OWNERS new file mode 100644 index 000000000000..eb8b89b10e83 --- /dev/null +++ b/.prebuilt_info/OWNERS @@ -0,0 +1 @@ +per-file prebuilt_info_packages_CtsShim_*.asciipb = file:/packages/CtsShim/OWNERS diff --git a/Android.bp b/Android.bp index e79248e9d974..22246f2f4e3c 100644 --- a/Android.bp +++ b/Android.bp @@ -1130,6 +1130,21 @@ aidl_interface { }, } +// Build Rust bindings for PermissionController. Needed by keystore2. +aidl_interface { + name: "android.os.permissions_aidl", + unstable: true, + local_include_dir: "core/java", + srcs: [ + "core/java/android/os/IPermissionController.aidl", + ], + backend: { + rust: { + enabled: true, + }, + }, +} + // TODO(b/77285514): remove this once the last few hidl interfaces have been // updated to use hwbinder.stubs. java_library { diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 4d9b4aafcae1..6fb9630fe847 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -56,6 +56,13 @@ package android.net { field @NonNull public final java.util.List<java.lang.String> underlyingIfaces; } + public class VpnManager { + field @Deprecated public static final int TYPE_VPN_LEGACY = 3; // 0x3 + field public static final int TYPE_VPN_NONE = -1; // 0xffffffff + field public static final int TYPE_VPN_PLATFORM = 2; // 0x2 + field public static final int TYPE_VPN_SERVICE = 1; // 0x1 + } + } package android.os { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index dc2e7a7e1a42..86a8e99f9733 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10179,7 +10179,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult setIccLockEnabled(boolean, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); - method public int setNrDualConnectivityState(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setNrDualConnectivityState(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index b0b45564d44d..a0ff97e1f338 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1604,6 +1604,10 @@ package android.telecom { method @NonNull public android.telecom.ConnectionRequest.Builder setVideoState(int); } + public abstract class ConnectionService extends android.app.Service { + method public void onBindClient(@Nullable android.content.Intent); + } + } package android.telephony { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b99d5cd13a77..65f2c02faa85 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2770,7 +2770,7 @@ public final class ActivityThread extends ClientTransactionHandler { memInfo.getTotalPrivateDirty(), memInfo.getTotalPrivateClean(), memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() : - memInfo.getTotalSwappedOut(), memInfo.getTotalPss(), + memInfo.getTotalSwappedOut(), memInfo.getTotalRss(), nativeMax+dalvikMax, nativeAllocated+dalvikAllocated, nativeFree+dalvikFree); } diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 53aaae0470e2..16413e1a1db6 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -139,7 +139,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage(trackingBug = 181103983) public static final String ACTION_CODEC_CONFIG_CHANGED = "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED"; @@ -684,7 +684,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @return the current codec status * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage(trackingBug = 181103983) @Nullable @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) { @@ -713,7 +713,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @param codecConfig the codec configuration preference * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage(trackingBug = 181103983) @RequiresPermission(Manifest.permission.BLUETOOTH) public void setCodecConfigPreference(@NonNull BluetoothDevice device, @NonNull BluetoothCodecConfig codecConfig) { diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index a5ece7b713c7..b037261f0bc2 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -179,21 +179,6 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { } /** - * Build a {@link NetworkIdentity} from the given {@link NetworkState} and - * {@code subType}, assuming that any mobile networks are using the current IMSI. - * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_* - * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. - */ - // TODO: Delete this function after NetworkPolicyManagerService finishes the migration. - public static NetworkIdentity buildNetworkIdentity(Context context, - NetworkState state, boolean defaultNetwork, @NetworkType int subType) { - final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.network, - state.networkCapabilities, state.linkProperties, state.subscriberId, - state.legacyNetworkType); - return buildNetworkIdentity(context, snapshot, defaultNetwork, subType); - } - - /** * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and * {@code subType}, assuming that any mobile networks are using the current IMSI. * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_* diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java index f472ed4381d1..77754d1256a7 100644 --- a/core/java/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -16,12 +16,15 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; @@ -56,18 +59,21 @@ import java.util.List; */ public class VpnManager { /** Type representing a lack of VPN @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_NONE = -1; /** * A VPN created by an app using the {@link VpnService} API. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_SERVICE = 1; /** * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_PLATFORM = 2; /** @@ -76,6 +82,7 @@ public class VpnManager { * @hide */ @Deprecated + @SystemApi(client = MODULE_LIBRARIES) public static final int TYPE_VPN_LEGACY = 3; /** diff --git a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java index de086f63b14d..22d7faf2fe18 100644 --- a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java +++ b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java @@ -19,11 +19,13 @@ package android.net.vcn; import static android.net.vcn.VcnControlPlaneConfig.CONFIG_TYPE_IKE; import android.annotation.NonNull; -import android.annotation.Nullable; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.TunnelModeChildSessionParams; +import android.net.vcn.persistablebundleutils.IkeSessionParamsUtils; +import android.net.vcn.persistablebundleutils.TunnelModeChildSessionParamsUtils; import android.os.PersistableBundle; import android.util.ArraySet; +import android.util.Log; import java.util.Objects; @@ -38,14 +40,11 @@ import java.util.Objects; public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig { private static final String TAG = VcnControlPlaneIkeConfig.class.getSimpleName(); - // STOPSHIP: b/163604823 Make mIkeParams and mChildParams @NonNull when it is supported to - // construct mIkeParams and mChildParams from PersistableBundles. - private static final String IKE_PARAMS_KEY = "mIkeParams"; - @Nullable private final IkeSessionParams mIkeParams; + @NonNull private final IkeSessionParams mIkeParams; private static final String CHILD_PARAMS_KEY = "mChildParams"; - @Nullable private final TunnelModeChildSessionParams mChildParams; + @NonNull private final TunnelModeChildSessionParams mChildParams; private static final ArraySet<String> BUNDLE_KEY_SET = new ArraySet<>(); @@ -80,11 +79,19 @@ public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig { final PersistableBundle ikeParamsBundle = in.getPersistableBundle(IKE_PARAMS_KEY); final PersistableBundle childParamsBundle = in.getPersistableBundle(CHILD_PARAMS_KEY); - // STOPSHIP: b/163604823 Support constructing mIkeParams and mChildParams from - // PersistableBundles. + Objects.requireNonNull(ikeParamsBundle, "IKE Session Params was null"); + Objects.requireNonNull(childParamsBundle, "Child Session Params was null"); + + mIkeParams = IkeSessionParamsUtils.fromPersistableBundle(ikeParamsBundle); + mChildParams = TunnelModeChildSessionParamsUtils.fromPersistableBundle(childParamsBundle); + + for (String key : in.keySet()) { + if (!BUNDLE_KEY_SET.contains(key)) { + Log.w(TAG, "Found an unexpected key in the PersistableBundle: " + key); + } + } - mIkeParams = null; - mChildParams = null; + validate(); } private void validate() { @@ -101,9 +108,11 @@ public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig { @NonNull public PersistableBundle toPersistableBundle() { final PersistableBundle result = super.toPersistableBundle(); - - // STOPSHIP: b/163604823 Support converting mIkeParams and mChildParams to - // PersistableBundles. + result.putPersistableBundle( + IKE_PARAMS_KEY, IkeSessionParamsUtils.toPersistableBundle(mIkeParams)); + result.putPersistableBundle( + CHILD_PARAMS_KEY, + TunnelModeChildSessionParamsUtils.toPersistableBundle(mChildParams)); return result; } @@ -134,10 +143,9 @@ public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig { VcnControlPlaneIkeConfig other = (VcnControlPlaneIkeConfig) o; - // STOPSHIP: b/163604823 Also check mIkeParams and mChildParams when it is supported to - // construct mIkeParams and mChildParams from PersistableBundles. They are not checked - // now so that VcnGatewayConnectionConfigTest and VcnConfigTest can pass. - return super.equals(o); + return super.equals(o) + && Objects.equals(mIkeParams, other.mIkeParams) + && Objects.equals(mChildParams, other.mChildParams); } /** @hide */ diff --git a/core/java/android/net/vcn/persistablebundleutils/CertUtils.java b/core/java/android/net/vcn/persistablebundleutils/CertUtils.java index b6036b4a6fd1..35b318687773 100644 --- a/core/java/android/net/vcn/persistablebundleutils/CertUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/CertUtils.java @@ -18,18 +18,24 @@ package android.net.vcn.persistablebundleutils; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; import java.util.Objects; /** - * CertUtils provides utility methods for constructing Certificate. + * CertUtils provides utility methods for constructing Certificate and PrivateKey. * * @hide */ public class CertUtils { private static final String CERT_TYPE_X509 = "X.509"; + private static final String PRIVATE_KEY_TYPE_RSA = "RSA"; /** Decodes an ASN.1 DER encoded Certificate */ public static X509Certificate certificateFromByteArray(byte[] derEncoded) { @@ -43,4 +49,18 @@ public class CertUtils { throw new IllegalArgumentException("Fail to decode certificate", e); } } + + /** Decodes a PKCS#8 encoded RSA private key */ + public static RSAPrivateKey privateKeyFromByteArray(byte[] pkcs8Encoded) { + Objects.requireNonNull(pkcs8Encoded, "pkcs8Encoded was null"); + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(pkcs8Encoded); + + try { + KeyFactory keyFactory = KeyFactory.getInstance(PRIVATE_KEY_TYPE_RSA); + + return (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new IllegalArgumentException("Fail to decode PrivateKey", e); + } + } } diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java new file mode 100644 index 000000000000..9d3462cb0b2e --- /dev/null +++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java @@ -0,0 +1,513 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn.persistablebundleutils; + +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; + +import static com.android.internal.annotations.VisibleForTesting.Visibility; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.InetAddresses; +import android.net.eap.EapSessionConfig; +import android.net.ipsec.ike.IkeSaProposal; +import android.net.ipsec.ike.IkeSessionParams; +import android.net.ipsec.ike.IkeSessionParams.ConfigRequestIpv4PcscfServer; +import android.net.ipsec.ike.IkeSessionParams.ConfigRequestIpv6PcscfServer; +import android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig; +import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig; +import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig; +import android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig; +import android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig; +import android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest; +import android.os.PersistableBundle; +import android.util.ArraySet; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.vcn.util.PersistableBundleUtils; + +import java.net.InetAddress; +import java.security.PrivateKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Abstract utility class to convert IkeSessionParams to/from PersistableBundle. + * + * @hide + */ +@VisibleForTesting(visibility = Visibility.PRIVATE) +public final class IkeSessionParamsUtils { + private static final String SERVER_HOST_NAME_KEY = "SERVER_HOST_NAME_KEY"; + private static final String SA_PROPOSALS_KEY = "SA_PROPOSALS_KEY"; + private static final String LOCAL_ID_KEY = "LOCAL_ID_KEY"; + private static final String REMOTE_ID_KEY = "REMOTE_ID_KEY"; + private static final String LOCAL_AUTH_KEY = "LOCAL_AUTH_KEY"; + private static final String REMOTE_AUTH_KEY = "REMOTE_AUTH_KEY"; + private static final String CONFIG_REQUESTS_KEY = "CONFIG_REQUESTS_KEY"; + private static final String RETRANS_TIMEOUTS_KEY = "RETRANS_TIMEOUTS_KEY"; + private static final String HARD_LIFETIME_SEC_KEY = "HARD_LIFETIME_SEC_KEY"; + private static final String SOFT_LIFETIME_SEC_KEY = "SOFT_LIFETIME_SEC_KEY"; + private static final String DPD_DELAY_SEC_KEY = "DPD_DELAY_SEC_KEY"; + private static final String NATT_KEEPALIVE_DELAY_SEC_KEY = "NATT_KEEPALIVE_DELAY_SEC_KEY"; + private static final String IKE_OPTIONS_KEY = "IKE_OPTIONS_KEY"; + + private static final Set<Integer> IKE_OPTIONS = new ArraySet<>(); + + static { + IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID); + IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH); + IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_MOBIKE); + } + + /** Serializes an IkeSessionParams to a PersistableBundle. */ + @NonNull + public static PersistableBundle toPersistableBundle(@NonNull IkeSessionParams params) { + if (params.getConfiguredNetwork() != null || params.getIke3gppExtension() != null) { + throw new IllegalStateException( + "Cannot convert a IkeSessionParams with a caller configured network or with" + + " 3GPP extension enabled"); + } + + final PersistableBundle result = new PersistableBundle(); + + result.putString(SERVER_HOST_NAME_KEY, params.getServerHostname()); + + final PersistableBundle saProposalBundle = + PersistableBundleUtils.fromList( + params.getSaProposals(), IkeSaProposalUtils::toPersistableBundle); + result.putPersistableBundle(SA_PROPOSALS_KEY, saProposalBundle); + + result.putPersistableBundle( + LOCAL_ID_KEY, + IkeIdentificationUtils.toPersistableBundle(params.getLocalIdentification())); + result.putPersistableBundle( + REMOTE_ID_KEY, + IkeIdentificationUtils.toPersistableBundle(params.getRemoteIdentification())); + + result.putPersistableBundle( + LOCAL_AUTH_KEY, AuthConfigUtils.toPersistableBundle(params.getLocalAuthConfig())); + result.putPersistableBundle( + REMOTE_AUTH_KEY, AuthConfigUtils.toPersistableBundle(params.getRemoteAuthConfig())); + + final List<ConfigRequest> reqList = new ArrayList<>(); + for (IkeConfigRequest req : params.getConfigurationRequests()) { + reqList.add(new ConfigRequest(req)); + } + final PersistableBundle configReqListBundle = + PersistableBundleUtils.fromList(reqList, ConfigRequest::toPersistableBundle); + result.putPersistableBundle(CONFIG_REQUESTS_KEY, configReqListBundle); + + result.putIntArray(RETRANS_TIMEOUTS_KEY, params.getRetransmissionTimeoutsMillis()); + result.putInt(HARD_LIFETIME_SEC_KEY, params.getHardLifetimeSeconds()); + result.putInt(SOFT_LIFETIME_SEC_KEY, params.getSoftLifetimeSeconds()); + result.putInt(DPD_DELAY_SEC_KEY, params.getDpdDelaySeconds()); + result.putInt(NATT_KEEPALIVE_DELAY_SEC_KEY, params.getNattKeepAliveDelaySeconds()); + + final List<Integer> enabledIkeOptions = new ArrayList<>(); + for (int option : IKE_OPTIONS) { + if (params.hasIkeOption(option)) { + enabledIkeOptions.add(option); + } + } + + final int[] optionArray = enabledIkeOptions.stream().mapToInt(i -> i).toArray(); + result.putIntArray(IKE_OPTIONS_KEY, optionArray); + + return result; + } + + /** Constructs an IkeSessionParams by deserializing a PersistableBundle. */ + @NonNull + public static IkeSessionParams fromPersistableBundle(@NonNull PersistableBundle in) { + Objects.requireNonNull(in, "PersistableBundle is null"); + + final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(); + + builder.setServerHostname(in.getString(SERVER_HOST_NAME_KEY)); + + PersistableBundle proposalBundle = in.getPersistableBundle(SA_PROPOSALS_KEY); + Objects.requireNonNull(in, "SA Proposals was null"); + List<IkeSaProposal> saProposals = + PersistableBundleUtils.toList( + proposalBundle, IkeSaProposalUtils::fromPersistableBundle); + for (IkeSaProposal proposal : saProposals) { + builder.addSaProposal(proposal); + } + + builder.setLocalIdentification( + IkeIdentificationUtils.fromPersistableBundle( + in.getPersistableBundle(LOCAL_ID_KEY))); + builder.setRemoteIdentification( + IkeIdentificationUtils.fromPersistableBundle( + in.getPersistableBundle(REMOTE_ID_KEY))); + + AuthConfigUtils.setBuilderByReadingPersistableBundle( + in.getPersistableBundle(LOCAL_AUTH_KEY), + in.getPersistableBundle(REMOTE_AUTH_KEY), + builder); + + builder.setRetransmissionTimeoutsMillis(in.getIntArray(RETRANS_TIMEOUTS_KEY)); + builder.setLifetimeSeconds( + in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY)); + builder.setDpdDelaySeconds(in.getInt(DPD_DELAY_SEC_KEY)); + builder.setNattKeepAliveDelaySeconds(in.getInt(NATT_KEEPALIVE_DELAY_SEC_KEY)); + + final PersistableBundle configReqListBundle = in.getPersistableBundle(CONFIG_REQUESTS_KEY); + Objects.requireNonNull(configReqListBundle, "Config request list was null"); + final List<ConfigRequest> reqList = + PersistableBundleUtils.toList(configReqListBundle, ConfigRequest::new); + for (ConfigRequest req : reqList) { + switch (req.type) { + case ConfigRequest.IPV4_P_CSCF_ADDRESS: + if (req.address == null) { + builder.addPcscfServerRequest(AF_INET); + } else { + builder.addPcscfServerRequest(req.address); + } + break; + case ConfigRequest.IPV6_P_CSCF_ADDRESS: + if (req.address == null) { + builder.addPcscfServerRequest(AF_INET6); + } else { + builder.addPcscfServerRequest(req.address); + } + break; + default: + throw new IllegalArgumentException( + "Unrecognized config request type: " + req.type); + } + } + + // Clear IKE Options that are by default enabled + for (int option : IKE_OPTIONS) { + builder.removeIkeOption(option); + } + + final int[] optionArray = in.getIntArray(IKE_OPTIONS_KEY); + for (int option : optionArray) { + builder.addIkeOption(option); + } + + return builder.build(); + } + + private static final class AuthConfigUtils { + private static final int IKE_AUTH_METHOD_PSK = 1; + private static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; + private static final int IKE_AUTH_METHOD_EAP = 3; + + private static final String AUTH_METHOD_KEY = "AUTH_METHOD_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle(@NonNull IkeAuthConfig authConfig) { + if (authConfig instanceof IkeAuthPskConfig) { + IkeAuthPskConfig config = (IkeAuthPskConfig) authConfig; + return IkeAuthPskConfigUtils.toPersistableBundle( + config, createPersistableBundle(IKE_AUTH_METHOD_PSK)); + } else if (authConfig instanceof IkeAuthDigitalSignLocalConfig) { + IkeAuthDigitalSignLocalConfig config = (IkeAuthDigitalSignLocalConfig) authConfig; + return IkeAuthDigitalSignConfigUtils.toPersistableBundle( + config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); + } else if (authConfig instanceof IkeAuthDigitalSignRemoteConfig) { + IkeAuthDigitalSignRemoteConfig config = (IkeAuthDigitalSignRemoteConfig) authConfig; + return IkeAuthDigitalSignConfigUtils.toPersistableBundle( + config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); + } else if (authConfig instanceof IkeAuthEapConfig) { + IkeAuthEapConfig config = (IkeAuthEapConfig) authConfig; + return IkeAuthEapConfigUtils.toPersistableBundle( + config, createPersistableBundle(IKE_AUTH_METHOD_EAP)); + } else { + throw new IllegalStateException("Invalid IkeAuthConfig subclass"); + } + } + + private static PersistableBundle createPersistableBundle(int type) { + final PersistableBundle result = new PersistableBundle(); + result.putInt(AUTH_METHOD_KEY, type); + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); + Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); + + final int localMethodType = localAuthBundle.getInt(AUTH_METHOD_KEY); + final int remoteMethodType = remoteAuthBundle.getInt(AUTH_METHOD_KEY); + switch (localMethodType) { + case IKE_AUTH_METHOD_PSK: + if (remoteMethodType != IKE_AUTH_METHOD_PSK) { + throw new IllegalArgumentException( + "Expect remote auth method to be PSK based, but was " + + remoteMethodType); + } + IkeAuthPskConfigUtils.setBuilderByReadingPersistableBundle( + localAuthBundle, remoteAuthBundle, builder); + return; + case IKE_AUTH_METHOD_PUB_KEY_SIGNATURE: + if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { + throw new IllegalArgumentException( + "Expect remote auth method to be digital signature based, but was " + + remoteMethodType); + } + IkeAuthDigitalSignConfigUtils.setBuilderByReadingPersistableBundle( + localAuthBundle, remoteAuthBundle, builder); + return; + case IKE_AUTH_METHOD_EAP: + if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { + throw new IllegalArgumentException( + "When using EAP for local authentication, expect remote auth" + + " method to be digital signature based, but was " + + remoteMethodType); + } + IkeAuthEapConfigUtils.setBuilderByReadingPersistableBundle( + localAuthBundle, remoteAuthBundle, builder); + return; + default: + throw new IllegalArgumentException( + "Invalid EAP method type " + localMethodType); + } + } + } + + private static final class IkeAuthPskConfigUtils { + private static final String PSK_KEY = "PSK_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle( + @NonNull IkeAuthPskConfig config, @NonNull PersistableBundle result) { + result.putPersistableBundle( + PSK_KEY, PersistableBundleUtils.fromByteArray(config.getPsk())); + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); + Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); + + final PersistableBundle localPskBundle = localAuthBundle.getPersistableBundle(PSK_KEY); + final PersistableBundle remotePskBundle = + remoteAuthBundle.getPersistableBundle(PSK_KEY); + Objects.requireNonNull(localAuthBundle, "Local PSK was null"); + Objects.requireNonNull(remoteAuthBundle, "Remote PSK was null"); + + final byte[] localPsk = PersistableBundleUtils.toByteArray(localPskBundle); + final byte[] remotePsk = PersistableBundleUtils.toByteArray(remotePskBundle); + if (!Arrays.equals(localPsk, remotePsk)) { + throw new IllegalArgumentException("Local PSK and remote PSK are different"); + } + builder.setAuthPsk(localPsk); + } + } + + private static class IkeAuthDigitalSignConfigUtils { + private static final String END_CERT_KEY = "END_CERT_KEY"; + private static final String INTERMEDIATE_CERTS_KEY = "INTERMEDIATE_CERTS_KEY"; + private static final String PRIVATE_KEY_KEY = "PRIVATE_KEY_KEY"; + private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle( + @NonNull IkeAuthDigitalSignLocalConfig config, @NonNull PersistableBundle result) { + try { + result.putPersistableBundle( + END_CERT_KEY, + PersistableBundleUtils.fromByteArray( + config.getClientEndCertificate().getEncoded())); + + final List<X509Certificate> certList = config.getIntermediateCertificates(); + final List<byte[]> encodedCertList = new ArrayList<>(certList.size()); + for (X509Certificate cert : certList) { + encodedCertList.add(cert.getEncoded()); + } + + final PersistableBundle certsBundle = + PersistableBundleUtils.fromList( + encodedCertList, PersistableBundleUtils::fromByteArray); + result.putPersistableBundle(INTERMEDIATE_CERTS_KEY, certsBundle); + } catch (CertificateEncodingException e) { + throw new IllegalArgumentException("Fail to encode certificate"); + } + + // TODO: b/170670506 Consider putting PrivateKey in Android KeyStore + result.putPersistableBundle( + PRIVATE_KEY_KEY, + PersistableBundleUtils.fromByteArray(config.getPrivateKey().getEncoded())); + return result; + } + + @NonNull + public static PersistableBundle toPersistableBundle( + @NonNull IkeAuthDigitalSignRemoteConfig config, @NonNull PersistableBundle result) { + try { + X509Certificate caCert = config.getRemoteCaCert(); + if (caCert != null) { + result.putPersistableBundle( + TRUST_CERT_KEY, + PersistableBundleUtils.fromByteArray(caCert.getEncoded())); + } + } catch (CertificateEncodingException e) { + throw new IllegalArgumentException("Fail to encode the certificate"); + } + + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); + Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); + + // Deserialize localAuth + final PersistableBundle endCertBundle = + localAuthBundle.getPersistableBundle(END_CERT_KEY); + Objects.requireNonNull(endCertBundle, "End cert was null"); + final byte[] encodedCert = PersistableBundleUtils.toByteArray(endCertBundle); + final X509Certificate endCert = CertUtils.certificateFromByteArray(encodedCert); + + final PersistableBundle certsBundle = + localAuthBundle.getPersistableBundle(INTERMEDIATE_CERTS_KEY); + Objects.requireNonNull(certsBundle, "Intermediate certs was null"); + final List<byte[]> encodedCertList = + PersistableBundleUtils.toList(certsBundle, PersistableBundleUtils::toByteArray); + final List<X509Certificate> certList = new ArrayList<>(encodedCertList.size()); + for (byte[] encoded : encodedCertList) { + certList.add(CertUtils.certificateFromByteArray(encoded)); + } + + final PersistableBundle privateKeyBundle = + localAuthBundle.getPersistableBundle(PRIVATE_KEY_KEY); + Objects.requireNonNull(privateKeyBundle, "PrivateKey bundle was null"); + final PrivateKey privateKey = + CertUtils.privateKeyFromByteArray( + PersistableBundleUtils.toByteArray(privateKeyBundle)); + + // Deserialize remoteAuth + final PersistableBundle trustCertBundle = + remoteAuthBundle.getPersistableBundle(TRUST_CERT_KEY); + + X509Certificate caCert = null; + if (trustCertBundle != null) { + final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); + caCert = CertUtils.certificateFromByteArray(encodedCaCert); + } + + builder.setAuthDigitalSignature(caCert, endCert, certList, privateKey); + } + } + + private static final class IkeAuthEapConfigUtils { + private static final String EAP_CONFIG_KEY = "EAP_CONFIG_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle( + @NonNull IkeAuthEapConfig config, @NonNull PersistableBundle result) { + result.putPersistableBundle( + EAP_CONFIG_KEY, + EapSessionConfigUtils.toPersistableBundle(config.getEapConfig())); + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + // Deserialize localAuth + final PersistableBundle eapBundle = + localAuthBundle.getPersistableBundle(EAP_CONFIG_KEY); + Objects.requireNonNull(eapBundle, "EAP Config was null"); + final EapSessionConfig eapConfig = + EapSessionConfigUtils.fromPersistableBundle(eapBundle); + + // Deserialize remoteAuth + final PersistableBundle trustCertBundle = + remoteAuthBundle.getPersistableBundle( + IkeAuthDigitalSignConfigUtils.TRUST_CERT_KEY); + + X509Certificate serverCaCert = null; + if (trustCertBundle != null) { + final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); + serverCaCert = CertUtils.certificateFromByteArray(encodedCaCert); + } + builder.setAuthEap(serverCaCert, eapConfig); + } + } + + private static final class ConfigRequest { + private static final int IPV4_P_CSCF_ADDRESS = 1; + private static final int IPV6_P_CSCF_ADDRESS = 2; + + private static final String TYPE_KEY = "type"; + private static final String ADDRESS_KEY = "address"; + + public final int type; + + // Null when it is an empty request + @Nullable public final InetAddress address; + + ConfigRequest(IkeConfigRequest config) { + if (config instanceof ConfigRequestIpv4PcscfServer) { + type = IPV4_P_CSCF_ADDRESS; + address = ((ConfigRequestIpv4PcscfServer) config).getAddress(); + } else if (config instanceof ConfigRequestIpv6PcscfServer) { + type = IPV6_P_CSCF_ADDRESS; + address = ((ConfigRequestIpv6PcscfServer) config).getAddress(); + } else { + throw new IllegalStateException("Unknown TunnelModeChildConfigRequest"); + } + } + + ConfigRequest(PersistableBundle in) { + Objects.requireNonNull(in, "PersistableBundle was null"); + + type = in.getInt(TYPE_KEY); + + String addressStr = in.getString(ADDRESS_KEY); + if (addressStr == null) { + address = null; + } else { + address = InetAddresses.parseNumericAddress(addressStr); + } + } + + @NonNull + public PersistableBundle toPersistableBundle() { + final PersistableBundle result = new PersistableBundle(); + + result.putInt(TYPE_KEY, type); + if (address != null) { + result.putString(ADDRESS_KEY, address.getHostAddress()); + } + + return result; + } + } +} diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index a4d6c3845fbf..0264d2335c4b 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1235,9 +1235,9 @@ public final class FileUtils { } /** - * Creates a directory with name {@code name} under an existing directory {@code baseDir}. - * Returns a {@code File} object representing the directory on success, {@code null} on - * failure. + * Creates a directory with name {@code name} under an existing directory {@code baseDir} if it + * doesn't exist already. Returns a {@code File} object representing the directory if it exists + * and {@code null} if not. * * @hide */ @@ -1247,13 +1247,23 @@ public final class FileUtils { return createDir(dir) ? dir : null; } - /** @hide */ + /** + * Ensure the given directory exists, creating it if needed. This method is threadsafe. + * + * @return false if the directory doesn't exist and couldn't be created + * + * @hide + */ public static boolean createDir(File dir) { + if (dir.mkdir()) { + return true; + } + if (dir.exists()) { return dir.isDirectory(); } - return dir.mkdir(); + return false; } /** diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 6c49b365c4f3..d9665953dceb 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -54,7 +54,7 @@ per-file HwRemoteBinder.java = file:platform/system/libhwbinder:/OWNERS per-file IHwBinder.java = file:platform/system/libhwbinder:/OWNERS per-file IHwInterface.java = file:platform/system/libhwbinder:/OWNERS -per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com +per-file GraphicsEnvironment.java = file:platform/frameworks/native:/opengl/OWNERS per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 769a34eed1dc..13871c51afe2 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -1083,7 +1083,8 @@ public abstract class VibrationEffect implements Parcelable { * * @param primitiveId The primitive to add * @param scale The scale to apply to the intensity of the primitive. - * @param delay The amount of time in milliseconds to wait before playing this primitive + * @param delay The amount of time in milliseconds to wait before playing this primitive, + * starting at the time the previous element in this composition is finished. * @return The {@link Composition} object to enable adding multiple primitives in one chain. */ @NonNull diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 10f6c610d5d3..96818fa26a73 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -67,7 +67,7 @@ import java.util.function.Consumer; * <p>Content capture provides real-time, continuous capture of application activity, display and * events to an intelligence service that is provided by the Android system. The intelligence * service then uses that info to mediate and speed user journey through different apps. For - * example, when the user receives a restaurant address in a chat app and switchs to a map app + * example, when the user receives a restaurant address in a chat app and switches to a map app * to search for that restaurant, the intelligence service could offer an autofill dialog to * let the user automatically select its address. * diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index fe87b64940fb..c220428df58b 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -648,8 +648,6 @@ public class ZygoteInit { */ private static void performSystemServerDexOpt(String classPath) { final String[] classPathElements = classPath.split(":"); - final IInstalld installd = IInstalld.Stub - .asInterface(ServiceManager.getService("installd")); final String instructionSet = VMRuntime.getRuntime().vmInstructionSet(); String classPathForElement = ""; @@ -686,6 +684,10 @@ public class ZygoteInit { final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; final String seInfo = null; final int targetSdkVersion = 0; // SystemServer targets the system's SDK version + // Wait for installd to be made available + IInstalld installd = IInstalld.Stub.asInterface( + ServiceManager.waitForService("installd")); + try { installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, instructionSet, dexoptNeeded, outputPath, dexFlags, systemServerFilter, diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 0e3db46bd0c9..f379ba0ddebb 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -902,7 +902,7 @@ static jlong android_os_Debug_getDmabufMappedSizeKb(JNIEnv* env, jobject clazz) continue; } - if (!AppendDmaBufInfo(pid, &dmabufs, false)) { + if (!ReadDmaBufMapRefs(pid, &dmabufs)) { LOG(ERROR) << "Failed to read maps for pid " << pid; } } diff --git a/packages/CtsShim/OWNERS b/packages/CtsShim/OWNERS new file mode 100644 index 000000000000..ba9f2b97678a --- /dev/null +++ b/packages/CtsShim/OWNERS @@ -0,0 +1,2 @@ +ioffe@google.com +toddke@google.com
\ No newline at end of file diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index dc1ce825368f..3fed29ac3ce2 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -285,6 +285,9 @@ <!-- Permission needed for CTS test - MusicRecognitionManagerTest --> <uses-permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION" /> + <!-- Permission needed for CTS test - CtsVoiceRecognitionTestCases --> + <uses-permission android:name="android.permission.MANAGE_SPEECH_RECOGNITION" /> + <!-- Permissions required to test ambient display. --> <uses-permission android:name="android.permission.READ_DREAM_STATE"/> <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/> diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index a26c6cad279c..709f5b2106f3 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -215,7 +215,6 @@ import com.android.server.connectivity.PermissionMonitor; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; import com.android.server.net.NetworkPolicyManagerInternal; -import com.android.server.utils.PriorityDump; import libcore.io.IoUtils; @@ -882,27 +881,59 @@ public class ConnectivityService extends IConnectivityManager.Stub } private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this); + final LocalPriorityDump mPriorityDumper = new LocalPriorityDump(); /** * Helper class which parses out priority arguments and dumps sections according to their * priority. If priority arguments are omitted, function calls the legacy dump command. */ - private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { - @Override - public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { - doDump(fd, pw, new String[] {DIAG_ARG}, asProto); - doDump(fd, pw, new String[] {SHORT_ARG}, asProto); + private class LocalPriorityDump { + private static final String PRIORITY_ARG = "--dump-priority"; + private static final String PRIORITY_ARG_HIGH = "HIGH"; + private static final String PRIORITY_ARG_NORMAL = "NORMAL"; + + LocalPriorityDump() {} + + private void dumpHigh(FileDescriptor fd, PrintWriter pw) { + doDump(fd, pw, new String[] {DIAG_ARG}); + doDump(fd, pw, new String[] {SHORT_ARG}); } - @Override - public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { - doDump(fd, pw, args, asProto); + private void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, args); } - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { - doDump(fd, pw, args, asProto); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (args == null) { + dumpNormal(fd, pw, args); + return; + } + + String priority = null; + for (int argIndex = 0; argIndex < args.length; argIndex++) { + if (args[argIndex].equals(PRIORITY_ARG) && argIndex + 1 < args.length) { + argIndex++; + priority = args[argIndex]; + } + } + + if (PRIORITY_ARG_HIGH.equals(priority)) { + dumpHigh(fd, pw); + } else if (PRIORITY_ARG_NORMAL.equals(priority)) { + dumpNormal(fd, pw, args); + } else { + // ConnectivityService publishes binder service using publishBinderService() with + // no priority assigned will be treated as NORMAL priority. Dumpsys does not send + // "--dump-priority" arguments to the service. Thus, dump both NORMAL and HIGH to + // align the legacy design. + // TODO: Integrate into signal dump. + dumpNormal(fd, pw, args); + pw.println(); + pw.println("DUMP OF SERVICE HIGH connectivity"); + pw.println(); + dumpHigh(fd, pw); + } } - }; + } /** * Keeps track of the number of requests made under different uids. @@ -2597,7 +2628,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { - PriorityDump.dump(mPriorityDumper, fd, writer, args); + mPriorityDumper.dump(fd, writer, args); } private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { @@ -2612,10 +2643,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) { + private void doDump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); if (!checkDumpPermission(mContext, TAG, pw)) return; - if (asProto) return; if (CollectionUtils.contains(args, DIAG_ARG)) { dumpNetworkDiagnostics(pw); @@ -3608,11 +3638,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // pendingIntent => NetworkRequestInfo map. // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo. private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) { - Intent intent = pendingIntent.getIntent(); for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) { PendingIntent existingPendingIntent = entry.getValue().mPendingIntent; if (existingPendingIntent != null && - existingPendingIntent.getIntent().filterEquals(intent)) { + existingPendingIntent.intentFilterEquals(pendingIntent)) { return entry.getValue(); } } @@ -3655,6 +3684,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } + // If this NRI has a satisfier already, it is replacing an older request that + // has been removed. Track it. + final NetworkRequest activeRequest = nri.getActiveRequest(); + if (null != activeRequest) { + // If there is an active request, then for sure there is a satisfier. + nri.getSatisfier().addRequest(activeRequest); + } } rematchAllNetworksAndRequests(); @@ -5275,14 +5311,26 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureAllNetworkRequestsHaveType(r); mRequests = initializeRequests(r); mNetworkRequestForCallback = nri.getNetworkRequestForCallback(); - // Note here that the satisfier may have corresponded to an old request, that - // this code doesn't try to take over. While it is a small discrepancy in the - // structure of these requests, it will be fixed by the next rematch and it's - // not as bad as having an NRI not storing its real satisfier. - // Fixing this discrepancy would require figuring out in the copying code what - // is the new request satisfied by this, which is a bit complex and not very - // useful as no code is using it until rematch fixes it. - mSatisfier = nri.mSatisfier; + final NetworkAgentInfo satisfier = nri.getSatisfier(); + if (null != satisfier) { + // If the old NRI was satisfied by an NAI, then it may have had an active request. + // The active request is necessary to figure out what callbacks to send, in + // particular then a network updates its capabilities. + // As this code creates a new NRI with a new set of requests, figure out which of + // the list of requests should be the active request. It is always the first + // request of the list that can be satisfied by the satisfier since the order of + // requests is a priority order. + // Note even in the presence of a satisfier there may not be an active request, + // when the satisfier is the no-service network. + NetworkRequest activeRequest = null; + for (final NetworkRequest candidate : r) { + if (candidate.canBeSatisfiedBy(satisfier.networkCapabilities)) { + activeRequest = candidate; + break; + } + } + setSatisfier(satisfier, activeRequest); + } mMessenger = nri.mMessenger; mBinder = nri.mBinder; mPid = nri.mPid; diff --git a/services/core/java/com/android/server/ConnectivityServiceInitializer.java b/services/core/java/com/android/server/ConnectivityServiceInitializer.java index b9922087109f..2465479aadd8 100644 --- a/services/core/java/com/android/server/ConnectivityServiceInitializer.java +++ b/services/core/java/com/android/server/ConnectivityServiceInitializer.java @@ -16,9 +16,6 @@ package com.android.server; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; - import android.content.Context; import android.util.Log; @@ -42,6 +39,6 @@ public final class ConnectivityServiceInitializer extends SystemService { public void onStart() { Log.i(TAG, "Registering " + Context.CONNECTIVITY_SERVICE); publishBinderService(Context.CONNECTIVITY_SERVICE, mConnectivity, - /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); + /* allowIsolated= */ false); } } diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java b/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java new file mode 100644 index 000000000000..b0335fe404f4 --- /dev/null +++ b/services/core/java/com/android/server/apphibernation/AppHibernationManagerInternal.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.apphibernation; + +/** + * App hibernation manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class AppHibernationManagerInternal { + + /** + * @see AppHibernationService#isHibernatingForUser + */ + public abstract boolean isHibernatingForUser(String packageName, int userId); + + /** + * @see AppHibernationService#setHibernatingForUser + */ + public abstract void setHibernatingForUser(String packageName, int userId, + boolean isHibernating); + + /** + * @see AppHibernationService#isHibernatingGlobally + */ + public abstract boolean isHibernatingGlobally(String packageName); + + /** + * @see AppHibernationService#setHibernatingGlobally + */ + public abstract void setHibernatingGlobally(String packageName, boolean isHibernating); +} diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index 32ae87898085..968cf5f1df91 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -59,6 +59,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.LocalServices; import com.android.server.SystemService; import java.io.File; @@ -134,6 +135,8 @@ public final class AppHibernationService extends SystemService { intentFilter.addAction(ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); userAllContext.registerReceiver(mBroadcastReceiver, intentFilter); + + LocalServices.addService(AppHibernationManagerInternal.class, mLocalService); } @Override @@ -545,6 +548,36 @@ public final class AppHibernationService extends SystemService { } } + private final AppHibernationManagerInternal mLocalService = new LocalService(this); + + private static final class LocalService extends AppHibernationManagerInternal { + private final AppHibernationService mService; + + LocalService(AppHibernationService service) { + mService = service; + } + + @Override + public boolean isHibernatingForUser(String packageName, int userId) { + return mService.isHibernatingForUser(packageName, userId); + } + + @Override + public void setHibernatingForUser(String packageName, int userId, boolean isHibernating) { + mService.setHibernatingForUser(packageName, userId, isHibernating); + } + + @Override + public void setHibernatingGlobally(String packageName, boolean isHibernating) { + mService.setHibernatingGlobally(packageName, isHibernating); + } + + @Override + public boolean isHibernatingGlobally(String packageName) { + return mService.isHibernatingGlobally(packageName); + } + } + private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this); static final class AppHibernationServiceStub extends IAppHibernationService.Stub { diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 364aa2cb41ae..240464a560af 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -207,7 +207,7 @@ class RebootEscrowManager { public void reportMetric(boolean success) { // TODO(b/179105110) design error code; and report the true value for other fields. FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, 0, 1, 1, - -1, 0); + -1, 0, -1); } public RebootEscrowEventLog getEventLog() { @@ -251,6 +251,8 @@ class RebootEscrowManager { } if (rebootEscrowUsers.isEmpty()) { + Slog.i(TAG, "No reboot escrow data found for users," + + " skipping loading escrow data"); return; } diff --git a/services/core/java/com/android/server/locksettings/TEST_MAPPING b/services/core/java/com/android/server/locksettings/TEST_MAPPING index 56f5cc034f05..8c19c541b86f 100644 --- a/services/core/java/com/android/server/locksettings/TEST_MAPPING +++ b/services/core/java/com/android/server/locksettings/TEST_MAPPING @@ -10,6 +10,17 @@ "exclude-annotation": "android.platform.test.annotations.FlakyTest" } ] + }, + { + "name": "FrameworksServicesTests", + "options": [ + { + "include-filter": "com.android.server.locksettings." + }, + { + "exclude-annotation": "android.platform.test.annotations.FlakyTest" + } + ] } ] } diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java index bf99bd6248cd..0659bc389b3c 100644 --- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java +++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java @@ -114,7 +114,7 @@ final class OverlayManagerShellCommand extends ShellCommand { out.println(" 'lowest', change priority of PACKAGE to the lowest priority."); out.println(" If PARENT is the special keyword 'highest', change priority of"); out.println(" PACKAGE to the highest priority."); - out.println(" lookup [--verbose] PACKAGE-TO-LOAD PACKAGE:TYPE/NAME"); + out.println(" lookup [--user USER_ID] [--verbose] PACKAGE-TO-LOAD PACKAGE:TYPE/NAME"); out.println(" Load a package and print the value of a given resource"); out.println(" applying the current configuration and enabled overlays."); out.println(" For a more fine-grained alernative, use 'idmap2 lookup'."); @@ -274,7 +274,22 @@ final class OverlayManagerShellCommand extends ShellCommand { final PrintWriter out = getOutPrintWriter(); final PrintWriter err = getErrPrintWriter(); - final boolean verbose = "--verbose".equals(getNextOption()); + int userId = UserHandle.USER_SYSTEM; + boolean verbose = false; + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--user": + userId = UserHandle.parseUserArg(getNextArgRequired()); + break; + case "--verbose": + verbose = true; + break; + default: + err.println("Error: Unknown option: " + opt); + return 1; + } + } final String packageToLoad = getNextArgRequired(); @@ -286,17 +301,15 @@ final class OverlayManagerShellCommand extends ShellCommand { return 1; } - final PackageManager pm = mContext.getPackageManager(); - if (pm == null) { - err.println("Error: failed to get package manager"); - return 1; - } - final Resources res; try { - res = pm.getResourcesForApplication(packageToLoad); + res = mContext + .createContextAsUser(UserHandle.of(userId), /* flags */ 0) + .getPackageManager() + .getResourcesForApplication(packageToLoad); } catch (PackageManager.NameNotFoundException e) { - err.println("Error: failed to get resources for package " + packageToLoad); + err.println(String.format("Error: failed to get resources for package %s for user %d", + packageToLoad, userId)); return 1; } final AssetManager assets = res.getAssets(); diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index b2db9f5af07e..8dcc547508ec 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -23,7 +23,6 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkCapabilities.NetCapability; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; import android.os.Handler; @@ -115,33 +114,61 @@ public class UnderlyingNetworkTracker { getWifiNetworkRequest(), mHandler, mWifiBringupCallback); updateSubIdsAndCellularRequests(); - // register Network-selection request used to decide selected underlying Network + // Register Network-selection request used to decide selected underlying Network. All + // underlying networks must be VCN managed in order to be used. mConnectivityManager.requestBackgroundNetwork( - getNetworkRequestBase().build(), mHandler, mRouteSelectionCallback); + getBaseNetworkRequest(true /* requireVcnManaged */).build(), + mHandler, + mRouteSelectionCallback); } private NetworkRequest getWifiNetworkRequest() { - return getNetworkRequestBase().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(); + // Request exclusively VCN managed networks to ensure that we only ever keep carrier wifi + // alive. + return getBaseNetworkRequest(true /* requireVcnManaged */) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .build(); } private NetworkRequest getCellNetworkRequestForSubId(int subId) { - return getNetworkRequestBase() + // Do not request NOT_VCN_MANAGED to ensure that the TelephonyNetworkFactory has a + // fulfillable request to bring up underlying cellular Networks even if the VCN is already + // connected. + return getBaseNetworkRequest(false /* requireVcnManaged */) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)) .build(); } - private NetworkRequest.Builder getNetworkRequestBase() { - NetworkRequest.Builder requestBase = new NetworkRequest.Builder(); - for (@NetCapability int capability : mRequiredUnderlyingNetworkCapabilities) { + /** + * Builds and returns a NetworkRequest builder common to all Underlying Network requests + * + * <p>A NetworkRequest may either (1) Require the presence of a capability by using + * addCapability(), (2) require the absence of a capability using unwanted capabilities, or (3) + * allow any state. Underlying networks are never desired to have the NOT_VCN_MANAGED + * capability, and only cases (2) and (3) are used. + * + * @param requireVcnManaged whether the underlying network is required to be VCN managed to + * match this request. If {@code true}, the NOT_VCN_MANAGED capability will be set as + * unwanted. Else, the NOT_VCN_MANAGED capability will be removed, and any state is + * acceptable. + */ + private NetworkRequest.Builder getBaseNetworkRequest(boolean requireVcnManaged) { + NetworkRequest.Builder requestBase = + new NetworkRequest.Builder() + .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + + for (int capability : mRequiredUnderlyingNetworkCapabilities) { requestBase.addCapability(capability); } - return requestBase - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + if (requireVcnManaged) { + requestBase.addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + return requestBase; } /** diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index c55913e2e547..3f74938005a7 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -299,9 +299,7 @@ public class Vcn extends Handler { for (VcnGatewayConnectionConfig gatewayConnectionConfig : mConfig.getGatewayConnectionConfigs()) { if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { - Slog.v( - getLogTag(), - "Bringing up new VcnGatewayConnection for request " + request.requestId); + Slog.v(getLogTag(), "Bringing up new VcnGatewayConnection for request " + request); final VcnGatewayConnection vcnGatewayConnection = mDeps.newVcnGatewayConnection( diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 6bc9978a0731..69a153f79a1b 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR; @@ -59,6 +60,7 @@ import android.net.ipsec.ike.exceptions.AuthenticationFailedException; import android.net.ipsec.ike.exceptions.IkeException; import android.net.ipsec.ike.exceptions.IkeInternalException; import android.net.ipsec.ike.exceptions.IkeProtocolException; +import android.net.vcn.VcnControlPlaneIkeConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnTransportInfo; import android.net.wifi.WifiInfo; @@ -979,7 +981,7 @@ public class VcnGatewayConnection extends StateMachine { // IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed() if (exception != null) { mGatewayStatusCallback.onGatewayConnectionError( - mConnectionConfig.getRequiredUnderlyingCapabilities(), + mConnectionConfig.getExposedCapabilities(), VCN_ERROR_CODE_INTERNAL_ERROR, RuntimeException.class.getName(), "Received " @@ -1016,7 +1018,7 @@ public class VcnGatewayConnection extends StateMachine { } mGatewayStatusCallback.onGatewayConnectionError( - mConnectionConfig.getRequiredUnderlyingCapabilities(), + mConnectionConfig.getExposedCapabilities(), errorCode, exceptionClass, exceptionMessage); @@ -1348,7 +1350,7 @@ public class VcnGatewayConnection extends StateMachine { mIkeSession = null; } - mIkeSession = buildIkeSession(); + mIkeSession = buildIkeSession(mUnderlying.network); } @Override @@ -1726,6 +1728,7 @@ public class VcnGatewayConnection extends StateMachine { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); builder.addTransportType(TRANSPORT_CELLULAR); + builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); builder.addCapability(NET_CAPABILITY_NOT_CONGESTED); builder.addCapability(NET_CAPABILITY_NOT_SUSPENDED); @@ -1939,23 +1942,29 @@ public class VcnGatewayConnection extends StateMachine { new EventDisconnectRequestedInfo(reason, shouldQuit)); } - private IkeSessionParams buildIkeParams() { - // TODO: Implement this once IkeSessionParams is persisted - return null; + private IkeSessionParams buildIkeParams(@NonNull Network network) { + final VcnControlPlaneIkeConfig controlPlaneConfig = + (VcnControlPlaneIkeConfig) mConnectionConfig.getControlPlaneConfig(); + final IkeSessionParams.Builder builder = + new IkeSessionParams.Builder(controlPlaneConfig.getIkeSessionParams()); + builder.setConfiguredNetwork(network); + + return builder.build(); } private ChildSessionParams buildChildParams() { - // TODO: Implement this once IkeSessionParams is persisted - return null; + final VcnControlPlaneIkeConfig controlPlaneConfig = + (VcnControlPlaneIkeConfig) mConnectionConfig.getControlPlaneConfig(); + return controlPlaneConfig.getChildSessionParams(); } @VisibleForTesting(visibility = Visibility.PRIVATE) - VcnIkeSession buildIkeSession() { + VcnIkeSession buildIkeSession(@NonNull Network network) { final int token = ++mCurrentToken; return mDeps.newIkeSession( mVcnContext, - buildIkeParams(), + buildIkeParams(network), buildChildParams(), new IkeSessionCallbackImpl(token), new VcnChildSessionCallback(token)); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java b/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java index b9af82b64c02..f3a38e6ec79c 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java @@ -19,12 +19,12 @@ package com.android.server.locksettings; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.Manifest; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -53,12 +53,9 @@ public class ResumeOnRebootServiceProviderTests { Context mMockContext; @Mock PackageManager mMockPackageManager; - @Mock - ResolveInfo mMockResolvedInfo; - @Mock - ServiceInfo mMockServiceInfo; - @Mock - ComponentName mMockComponentName; + + ResolveInfo mFakeResolvedInfo; + ServiceInfo mFakeServiceInfo; @Captor ArgumentCaptor<Intent> mIntentArgumentCaptor; @@ -66,8 +63,13 @@ public class ResumeOnRebootServiceProviderTests { public void setUp() { MockitoAnnotations.initMocks(this); when(mMockContext.getUserId()).thenReturn(0); - when(mMockResolvedInfo.serviceInfo).thenReturn(mMockServiceInfo); - when(mMockServiceInfo.getComponentName()).thenReturn(mMockComponentName); + + mFakeServiceInfo = new ServiceInfo(); + mFakeServiceInfo.packageName = "fakePackageName"; + mFakeServiceInfo.name = "fakeName"; + + mFakeResolvedInfo = new ResolveInfo(); + mFakeResolvedInfo.serviceInfo = mFakeServiceInfo; } @Test @@ -82,10 +84,9 @@ public class ResumeOnRebootServiceProviderTests { @Test public void serviceNotGuardedWithPermission() throws Exception { ArrayList<ResolveInfo> resultList = new ArrayList<>(); - when(mMockServiceInfo.permission).thenReturn(""); - resultList.add(mMockResolvedInfo); - when(mMockPackageManager.queryIntentServices(any(), any())).thenReturn( - resultList); + mFakeServiceInfo.permission = ""; + resultList.add(mFakeResolvedInfo); + when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenReturn(resultList); assertThat(new ResumeOnRebootServiceProvider(mMockContext, mMockPackageManager).getServiceConnection()).isNull(); } @@ -93,18 +94,15 @@ public class ResumeOnRebootServiceProviderTests { @Test public void serviceResolved() throws Exception { ArrayList<ResolveInfo> resultList = new ArrayList<>(); - resultList.add(mMockResolvedInfo); - when(mMockServiceInfo.permission).thenReturn( - Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE); - when(mMockPackageManager.queryIntentServices(any(), - eq(PackageManager.MATCH_SYSTEM_ONLY))).thenReturn( - resultList); + resultList.add(mFakeResolvedInfo); + mFakeServiceInfo.permission = Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE; + when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenReturn(resultList); assertThat(new ResumeOnRebootServiceProvider(mMockContext, mMockPackageManager).getServiceConnection()).isNotNull(); verify(mMockPackageManager).queryIntentServices(mIntentArgumentCaptor.capture(), - eq(PackageManager.MATCH_SYSTEM_ONLY)); + eq(PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_SERVICES)); assertThat(mIntentArgumentCaptor.getValue().getAction()).isEqualTo( ResumeOnRebootService.SERVICE_INTERFACE); } diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS b/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 580513c12453..b022154ea917 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.Service; import android.content.ComponentName; import android.content.Intent; @@ -1887,6 +1888,7 @@ public abstract class ConnectionService extends Service { /** {@inheritDoc} */ @Override public final IBinder onBind(Intent intent) { + onBindClient(intent); return mBinder; } @@ -1897,6 +1899,13 @@ public abstract class ConnectionService extends Service { return super.onUnbind(intent); } + /** + * Used for testing to let the test suite know when the connection service has been bound. + * @hide + */ + @TestApi + public void onBindClient(@Nullable Intent intent) { + } /** * This can be used by telecom to either create a new outgoing conference call or attach diff --git a/telephony/java/android/telephony/CarrierBandwidth.java b/telephony/java/android/telephony/CarrierBandwidth.java index b153fefce6e3..9e1dee0162b9 100644 --- a/telephony/java/android/telephony/CarrierBandwidth.java +++ b/telephony/java/android/telephony/CarrierBandwidth.java @@ -101,7 +101,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the upstream bandwidth for the primary network in Kbps. This always only refers to + * Retrieves the upstream bandwidth for the primary network in kbps. This always only refers to * the estimated first hop transport bandwidth. * This will be {@link #INVALID} if the network is not connected * @@ -112,7 +112,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the downstream bandwidth for the primary network in Kbps. This always only refers + * Retrieves the downstream bandwidth for the primary network in kbps. This always only refers * to the estimated first hop transport bandwidth. * This will be {@link #INVALID} if the network is not connected * @@ -123,7 +123,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the upstream bandwidth for the secondary network in Kbps. This always only refers + * Retrieves the upstream bandwidth for the secondary network in kbps. This always only refers * to the estimated first hop transport bandwidth. * <p/> * This will be {@link #INVALID} if either are the case: @@ -143,7 +143,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the downstream bandwidth for the secondary network in Kbps. This always only + * Retrieves the downstream bandwidth for the secondary network in kbps. This always only * refers to the estimated first hop transport bandwidth. * <p/> * This will be {@link #INVALID} if either are the case: diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index e3853fabfd7a..23dcee6387b8 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -14120,12 +14120,11 @@ public class TelephonyManager { * {@link #NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE} * </ol> * @return operation result. - * <p>Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * @throws IllegalStateException if the Telephony process is not currently available. * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public @EnableNrDualConnectivityResult int setNrDualConnectivityState( @NrDualConnectivityState int nrDualConnectivityState) { try { diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 76243a5799c3..3eda7482117f 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -522,8 +522,8 @@ public interface RILConstants { int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219; int RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES = 220; int RIL_REQUEST_SET_DATA_THROTTLING = 221; - int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP = 222; - int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP = 223; + int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP = 222; + int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP = 223; /* Responses begin */ int RIL_RESPONSE_ACKNOWLEDGEMENT = 800; diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING index 89fc6ea2c47b..d659688700d3 100644 --- a/tests/net/TEST_MAPPING +++ b/tests/net/TEST_MAPPING @@ -9,6 +9,23 @@ "name": "FrameworksNetDeflakeTest" } ], + "auto-postsubmit": [ + // Test tag for automotive targets. These are only running in postsubmit so as to harden the + // automotive targets to avoid introducing additional test flake and build time. The plan for + // presubmit testing for auto is to augment the existing tests to cover auto use cases as well. + // Additionally, this tag is used in targeted test suites to limit resource usage on the test + // infra during the hardening phase. + // TODO: this tag to be removed once the above is no longer an issue. + { + "name": "FrameworksNetTests" + }, + { + "name": "FrameworksNetIntegrationTests" + }, + { + "name": "FrameworksNetDeflakeTest" + } + ], "imports": [ { "path": "cts/tests/tests/net" diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 526e190aaa78..dfebb281c6ea 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -72,6 +72,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; @@ -5571,7 +5572,7 @@ public class ConnectivityServiceTest { reset(mStatsManager); // Temp metered change shouldn't update ifaces - mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); waitForIdle(); verify(mStatsManager, never()).notifyNetworkStatus(eq(Arrays.asList(onlyCell)), any(List.class), eq(MOBILE_IFNAME), any(List.class)); @@ -10646,7 +10647,7 @@ public class ConnectivityServiceTest { null, null); - // default NCs will be unregistered in tearDown + // default callbacks will be unregistered in tearDown } /** @@ -10703,7 +10704,7 @@ public class ConnectivityServiceTest { null, mService.mNoServiceNetwork.network()); - // default NCs will be unregistered in tearDown + // default callbacks will be unregistered in tearDown } /** @@ -10762,7 +10763,7 @@ public class ConnectivityServiceTest { null, mService.mNoServiceNetwork.network()); - // default NCs will be unregistered in tearDown + // default callbacks will be unregistered in tearDown } /** @@ -10821,7 +10822,28 @@ public class ConnectivityServiceTest { null, mService.mNoServiceNetwork.network()); - // default NCs will be unregistered in tearDown + // default callbacks will be unregistered in tearDown + } + + @Test + public void testCapabilityWithOemNetworkPreference() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref); + registerDefaultNetworkCallbacks(); + + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + + // default callbacks will be unregistered in tearDown } @Test diff --git a/tests/vcn/assets/client-end-cert.pem b/tests/vcn/assets/client-end-cert.pem new file mode 100644 index 000000000000..e82da85c50ab --- /dev/null +++ b/tests/vcn/assets/client-end-cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDaDCCAlCgAwIBAgIIcorRI3n29E4wDQYJKoZIhvcNAQELBQAwQTELMAkGA1UE +BhMCVVMxEDAOBgNVBAoTB0FuZHJvaWQxIDAeBgNVBAMTF3R3by5jYS50ZXN0LmFu +ZHJvaWQubmV0MB4XDTIwMDQxNDA1MDM0OVoXDTIzMDQxNDA1MDM0OVowRTELMAkG +A1UEBhMCVVMxEDAOBgNVBAoTB0FuZHJvaWQxJDAiBgNVBAMTG2NsaWVudC50ZXN0 +LmlrZS5hbmRyb2lkLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AK/cK+sIaiQlJYvy5+Dq70sJbgR7PO1uS2qkLRP7Wb3z5SNvz94nQvZRrFn1AFIE +CpfESh5kUF6gJe7t7NR3mpQ98iEosCRBMDJT8qB+EeHiL4wkrmCE9sYMTyvaApRc +6Qzozn/9kKma7Qpj/25AvoPluTERqhZ6AQ77BJeb6FNOAoO1Aoe9GJuB1xmRxjRw +D0mwusL+ciQ/7uKlsFP5VO5XqACcohXSerzO8jcD9necBvka3SDepqqzn1K0NPRC +25fMmS5kSjddKtKOif7w2NI3OpVsmP3kHv66If73VURsy0lgXPYyKkq8lAMrtmXG +R7svFGPbEl+Swkpr3b+dzF8CAwEAAaNgMF4wHwYDVR0jBBgwFoAUcqSu1uRYT/DL +bLoDNUz38nGvCKQwJgYDVR0RBB8wHYIbY2xpZW50LnRlc3QuaWtlLmFuZHJvaWQu +bmV0MBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCa53tK +I9RM9/MutZ5KNG2Gfs2cqaPyv8ZRhs90HDWZhkFVu7prywJAxOd2hxxHPsvgurio +4bKAxnT4EXevgz5YoCbj2TPIL9TdFYh59zZ97XXMxk+SRdypgF70M6ETqKPs3hDP +ZRMMoHvvYaqaPvp4StSBX9A44gSyjHxVYJkrjDZ0uffKg5lFL5IPvqfdmSRSpGab +SyGTP4OLTy0QiNV3pBsJGdl0h5BzuTPR9OTl4xgeqqBQy2bDjmfJBuiYyCSCkPi7 +T3ohDYCymhuSkuktHPNG1aKllUJaw0tuZuNydlgdAveXPYfM36uvK0sfd9qr9pAy +rmkYV2MAWguFeckh +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/tests/vcn/assets/client-private-key.key b/tests/vcn/assets/client-private-key.key new file mode 100644 index 000000000000..22736e98e030 --- /dev/null +++ b/tests/vcn/assets/client-private-key.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCv3CvrCGokJSWL +8ufg6u9LCW4EezztbktqpC0T+1m98+Ujb8/eJ0L2UaxZ9QBSBAqXxEoeZFBeoCXu +7ezUd5qUPfIhKLAkQTAyU/KgfhHh4i+MJK5ghPbGDE8r2gKUXOkM6M5//ZCpmu0K +Y/9uQL6D5bkxEaoWegEO+wSXm+hTTgKDtQKHvRibgdcZkcY0cA9JsLrC/nIkP+7i +pbBT+VTuV6gAnKIV0nq8zvI3A/Z3nAb5Gt0g3qaqs59StDT0QtuXzJkuZEo3XSrS +jon+8NjSNzqVbJj95B7+uiH+91VEbMtJYFz2MipKvJQDK7Zlxke7LxRj2xJfksJK +a92/ncxfAgMBAAECggEAQztaMvW5lm35J8LKsWs/5qEJRX9T8LWs8W0oqq36Riub +G2wgvR6ndAIPcSjAYZqX7iOl7m6NZ0+0kN63HxdGqovwKIskpAekBGmhpYftED1n +zh0r6UyMB3UnQ22KdOv8UOokIDxxdNX8728BdUYdT9Ggdkj5jLRB+VcwD0IUlNvo +zzTpURV9HEd87uiLqd4AAHXSI0lIHI5U43z24HI/J6/YbYHT3Rlh6CIa/LuwO6vL +gFkgqg0/oy6yJtjrHtzNVA67F0UaH62hR4YFgbC0d955SJnDidWOv/0j2DMpfdCc +9kFAcPwUSyykvUSLnGIKWSG4D+6gzIeAeUx4oO7kMQKBgQDVNRkX8AGTHyLg+NXf +spUWWcodwVioXl30Q7h6+4bt8OI61UbhQ7wX61wvJ1cySpa2KOYa2UdagQVhGhhL +ADu363R77uXF/jZgzVfmjjyJ2nfDqRgHWRTlSkuq/jCOQCz7VIPHRZg5WL/9D4ms +TAqMjpzqeMfFZI+w4/+xpcJIuQKBgQDTKBy+ZuerWrVT9icWKvLU58o5EVj/2yFy +GJvKm+wRAAX2WzjNnR4HVd4DmMREVz1BPYby0j5gqjvtDsxYYu39+NT7JvMioLLK +QPj+7k5geYgNqVgCxB1vP89RhY2X1RLrN9sTXOodgFPeXOQWNYITkGp3eQpx4nTJ ++K/al3oB1wKBgAjnc8nVIyuyxDEjE0OJYMKTM2a0uXAmqMPXxC+Wq5bqVXhhidlE +i+lv0eTCPtkB1nN7F8kNQ/aaps/cWCFhvBy9P5shagUvzbOTP9WIIS0cq53HRRKh +fMbqqGhWv05hjb9dUzeSR341n6cA7B3++v3Nwu3j52vt/DZF/1q68nc5AoGAS0SU +ImbKE/GsizZGLoe2sZ/CHN+LKwCwhlwxRGKaHmE0vuE7eUeVSaYZEo0lAPtb8WJ+ +NRYueASWgeTxgFwbW5mUScZTirdfo+rPFwhZVdhcYApKPgosN9i2DOgfVcz1BnWN +mPRY25U/0BaqkyQVruWeneG+kGPZn5kPDktKiVcCgYEAkzwU9vCGhm7ZVALvx/zR +wARz2zsL9ImBc0P4DK1ld8g90FEnHrEgeI9JEwz0zFHOCMLwlk7kG0Xev7vfjZ7G +xSqtQYOH33Qp6rtBOgdt8hSyDFvakvDl6bqhAw52gelO3MTpAB1+ZsfZ5gFx13Jf +idNFcaIrC52PtZIH7QCzdDY= +-----END PRIVATE KEY-----
\ No newline at end of file diff --git a/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java b/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java index 36f5e41462e8..2333718d0cab 100644 --- a/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnControlPlaneIkeConfigTest.java @@ -99,6 +99,13 @@ public class VcnControlPlaneIkeConfigTest { } @Test + public void testPersistableBundle() { + final VcnControlPlaneIkeConfig config = buildTestConfig(); + + assertEquals(config, new VcnControlPlaneIkeConfig(config.toPersistableBundle())); + } + + @Test public void testConstructConfigWithoutIkeParams() { try { new VcnControlPlaneIkeConfig(null, CHILD_PARAMS); diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java new file mode 100644 index 000000000000..546d957d417e --- /dev/null +++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn.persistablebundleutils; + +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.telephony.TelephonyManager.APPTYPE_USIM; + +import static org.junit.Assert.assertEquals; + +import android.net.InetAddresses; +import android.net.eap.EapSessionConfig; +import android.net.ipsec.ike.IkeFqdnIdentification; +import android.net.ipsec.ike.IkeSessionParams; +import android.os.PersistableBundle; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.org.bouncycastle.util.io.pem.PemObject; +import com.android.internal.org.bouncycastle.util.io.pem.PemReader; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class IkeSessionParamsUtilsTest { + private static IkeSessionParams.Builder createBuilderMinimum() { + final InetAddress serverAddress = InetAddresses.parseNumericAddress("192.0.2.100"); + + return new IkeSessionParams.Builder() + .setServerHostname(serverAddress.getHostAddress()) + .addSaProposal(SaProposalUtilsTest.buildTestIkeSaProposal()) + .setLocalIdentification(new IkeFqdnIdentification("client.test.android.net")) + .setRemoteIdentification(new IkeFqdnIdentification("server.test.android.net")) + .setAuthPsk("psk".getBytes()); + } + + private static void verifyPersistableBundleEncodeDecodeIsLossless(IkeSessionParams params) { + final PersistableBundle bundle = IkeSessionParamsUtils.toPersistableBundle(params); + final IkeSessionParams result = IkeSessionParamsUtils.fromPersistableBundle(bundle); + + assertEquals(result, params); + } + + @Test + public void testEncodeRecodeParamsWithLifetimes() throws Exception { + final int hardLifetime = (int) TimeUnit.HOURS.toSeconds(20L); + final int softLifetime = (int) TimeUnit.HOURS.toSeconds(10L); + final IkeSessionParams params = + createBuilderMinimum().setLifetimeSeconds(hardLifetime, softLifetime).build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithDpdDelay() throws Exception { + final int dpdDelay = (int) TimeUnit.MINUTES.toSeconds(10L); + final IkeSessionParams params = createBuilderMinimum().setDpdDelaySeconds(dpdDelay).build(); + + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithNattKeepalive() throws Exception { + final int nattKeepAliveDelay = (int) TimeUnit.MINUTES.toSeconds(5L); + final IkeSessionParams params = + createBuilderMinimum().setNattKeepAliveDelaySeconds(nattKeepAliveDelay).build(); + + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithRetransmissionTimeouts() throws Exception { + final int[] retransmissionTimeout = new int[] {500, 500, 500, 500, 500, 500}; + final IkeSessionParams params = + createBuilderMinimum() + .setRetransmissionTimeoutsMillis(retransmissionTimeout) + .build(); + + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithConfigRequests() throws Exception { + final Inet4Address ipv4Address = + (Inet4Address) InetAddresses.parseNumericAddress("192.0.2.100"); + final Inet6Address ipv6Address = + (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::1"); + + final IkeSessionParams params = + createBuilderMinimum() + .addPcscfServerRequest(AF_INET) + .addPcscfServerRequest(AF_INET6) + .addPcscfServerRequest(ipv4Address) + .addPcscfServerRequest(ipv6Address) + .build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithAuthPsk() throws Exception { + final IkeSessionParams params = createBuilderMinimum().setAuthPsk("psk".getBytes()).build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithIkeOptions() throws Exception { + final IkeSessionParams params = + createBuilderMinimum() + .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID) + .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) + .build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + private static InputStream openAssetsFile(String fileName) throws Exception { + return InstrumentationRegistry.getContext().getResources().getAssets().open(fileName); + } + + private static X509Certificate createCertFromPemFile(String fileName) throws Exception { + final CertificateFactory factory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) factory.generateCertificate(openAssetsFile(fileName)); + } + + private static RSAPrivateKey createRsaPrivateKeyFromKeyFile(String fileName) throws Exception { + final PemObject pemObject = + new PemReader(new InputStreamReader(openAssetsFile(fileName))).readPemObject(); + return (RSAPrivateKey) CertUtils.privateKeyFromByteArray(pemObject.getContent()); + } + + @Test + public void testEncodeRecodeParamsWithDigitalSignAuth() throws Exception { + final X509Certificate serverCaCert = createCertFromPemFile("self-signed-ca.pem"); + final X509Certificate clientEndCert = createCertFromPemFile("client-end-cert.pem"); + final RSAPrivateKey clientPrivateKey = + createRsaPrivateKeyFromKeyFile("client-private-key.key"); + + final IkeSessionParams params = + createBuilderMinimum() + .setAuthDigitalSignature(serverCaCert, clientEndCert, clientPrivateKey) + .build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithEapAuth() throws Exception { + final X509Certificate serverCaCert = createCertFromPemFile("self-signed-ca.pem"); + + final byte[] eapId = "test@android.net".getBytes(StandardCharsets.US_ASCII); + final int subId = 1; + final EapSessionConfig eapConfig = + new EapSessionConfig.Builder() + .setEapIdentity(eapId) + .setEapSimConfig(subId, APPTYPE_USIM) + .setEapAkaConfig(subId, APPTYPE_USIM) + .build(); + + final IkeSessionParams params = + createBuilderMinimum().setAuthEap(serverCaCert, eapConfig).build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } +} diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java index 8ae8692b4f75..664044a9e7d4 100644 --- a/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java +++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java @@ -32,21 +32,25 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class SaProposalUtilsTest { + /** Package private so that IkeSessionParamsUtilsTest can use it */ + static IkeSaProposal buildTestIkeSaProposal() { + return new IkeSaProposal.Builder() + .addEncryptionAlgorithm( + SaProposal.ENCRYPTION_ALGORITHM_3DES, SaProposal.KEY_LEN_UNUSED) + .addEncryptionAlgorithm( + SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) + .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) + .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128) + .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) + .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256) + .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) + .addDhGroup(SaProposal.DH_GROUP_3072_BIT_MODP) + .build(); + } + @Test public void testPersistableBundleEncodeDecodeIsLosslessIkeProposal() throws Exception { - final IkeSaProposal proposal = - new IkeSaProposal.Builder() - .addEncryptionAlgorithm( - SaProposal.ENCRYPTION_ALGORITHM_3DES, SaProposal.KEY_LEN_UNUSED) - .addEncryptionAlgorithm( - SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) - .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) - .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128) - .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) - .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256) - .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) - .addDhGroup(SaProposal.DH_GROUP_3072_BIT_MODP) - .build(); + final IkeSaProposal proposal = buildTestIkeSaProposal(); final PersistableBundle bundle = IkeSaProposalUtils.toPersistableBundle(proposal); final SaProposal resultProposal = IkeSaProposalUtils.fromPersistableBundle(bundle); diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java index 1d459a347526..1ef1a61f17ea 100644 --- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java @@ -194,29 +194,35 @@ public class UnderlyingNetworkTrackerTest { } private NetworkRequest getWifiRequest() { - return getExpectedRequestBase() + return getExpectedRequestBase(true) .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); } private NetworkRequest getCellRequestForSubId(int subId) { - return getExpectedRequestBase() + return getExpectedRequestBase(false) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)) .build(); } private NetworkRequest getRouteSelectionRequest() { - return getExpectedRequestBase().build(); + return getExpectedRequestBase(true).build(); } - private NetworkRequest.Builder getExpectedRequestBase() { - return new NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + private NetworkRequest.Builder getExpectedRequestBase(boolean requireVcnManaged) { + final NetworkRequest.Builder builder = + new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + + if (requireVcnManaged) { + builder.addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + return builder; } @Test diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 69b2fb135a8d..0e5f5e43f282 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -73,7 +73,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1); - mIkeSession = mGatewayConnection.buildIkeSession(); + mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network); mGatewayConnection.setIkeSession(mIkeSession); mGatewayConnection.transitionTo(mGatewayConnection.mConnectedState); @@ -241,7 +241,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verify(mGatewayStatusCallback) .onGatewayConnectionError( - eq(mConfig.getRequiredUnderlyingCapabilities()), + eq(mConfig.getExposedCapabilities()), eq(VCN_ERROR_CODE_INTERNAL_ERROR), any(), any()); @@ -275,10 +275,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verify(mGatewayStatusCallback) .onGatewayConnectionError( - eq(mConfig.getRequiredUnderlyingCapabilities()), - eq(expectedErrorType), - any(), - any()); + eq(mConfig.getExposedCapabilities()), eq(expectedErrorType), any(), any()); } @Test diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index d07d2cf4f1bb..7afa4494ee8b 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -25,12 +25,15 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.net.ipsec.ike.IkeSessionParams; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; /** Tests for VcnGatewayConnection.ConnectingState */ @RunWith(AndroidJUnit4.class) @@ -51,7 +54,12 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio @Test public void testEnterStateCreatesNewIkeSession() throws Exception { - verify(mDeps).newIkeSession(any(), any(), any(), any(), any()); + final ArgumentCaptor<IkeSessionParams> paramsCaptor = + ArgumentCaptor.forClass(IkeSessionParams.class); + verify(mDeps).newIkeSession(any(), paramsCaptor.capture(), any(), any(), any()); + assertEquals( + TEST_UNDERLYING_NETWORK_RECORD_1.network, + paramsCaptor.getValue().getConfiguredNetwork()); } @Test diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java index 661e03af4f84..99feffdebc8e 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java @@ -38,7 +38,8 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec public void setUp() throws Exception { super.setUp(); - mGatewayConnection.setIkeSession(mGatewayConnection.buildIkeSession()); + mGatewayConnection.setIkeSession( + mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_2.network)); // ensure that mGatewayConnection has an underlying Network before entering // DisconnectingState diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java index 748c7924685d..d08af9dd3370 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java @@ -18,6 +18,7 @@ package com.android.server.vcn; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; @@ -87,6 +88,7 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { private void verifyBuildNetworkCapabilitiesCommon(int transportType) { final NetworkCapabilities underlyingCaps = new NetworkCapabilities(); underlyingCaps.addTransportType(transportType); + underlyingCaps.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); underlyingCaps.addCapability(NET_CAPABILITY_NOT_METERED); underlyingCaps.addCapability(NET_CAPABILITY_NOT_ROAMING); |