Merge "Even more libcore benchmark tests."
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
index b5466b6..49f4bf7 100644
--- a/core/java/android/permission/OWNERS
+++ b/core/java/android/permission/OWNERS
@@ -5,10 +5,14 @@
ewol@google.com
guojing@google.com
jaysullivan@google.com
+kvakil@google.com
+mrulhania@google.com
+narayan@google.com
+ntmyren@google.com
olekarg@google.com
pyuli@google.com
-ntmyren@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+raphk@google.com
+rmacgregor@google.com
+sergeynv@google.com
theianchen@google.com
zhanghai@google.com
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
index 32f4822..462d8be 100644
--- a/core/java/android/speech/OWNERS
+++ b/core/java/android/speech/OWNERS
@@ -1,3 +1,4 @@
volnov@google.com
eugeniom@google.com
schfan@google.com
+andreaambu@google.com
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 86e97d5..f4f9f94 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1177,38 +1177,40 @@
}
/**
- * Make other apps data directory not visible in CE, DE storage.
+ * Hide the CE and DE data directories of non-related apps.
*
- * Apps without app data isolation can detect if another app is installed on system,
- * by "touching" other apps data directory like /data/data/com.whatsapp, if it returns
- * "Permission denied" it means apps installed, otherwise it returns "File not found".
- * Traditional file permissions or SELinux can only block accessing those directories but
- * can't fix fingerprinting like this.
- * We fix it by "overlaying" data directory, and only relevant app data packages exists
- * in data directories.
+ * Without this, apps can detect if any app is installed by trying to "touch" the app's CE
+ * or DE data directory, e.g. /data/data/com.whatsapp. This fails with EACCES if the app
+ * is installed, or ENOENT if it's not. Traditional file permissions or SELinux can only
+ * block accessing those directories but can't fix fingerprinting like this.
+ *
+ * Instead, we hide non-related apps' data directories from the filesystem entirely by
+ * mounting tmpfs instances over their parent directories and bind-mounting in just the
+ * needed app data directories. This is done in a private mount namespace.
*
* Steps:
- * 1). Collect a list of all related apps (apps with same uid and allowlisted apps) data info
- * (package name, data stored volume uuid, and inode number of its CE data directory)
- * 2). Mount tmpfs on /data/data, /data/user(_de) and /mnt/expand, so apps no longer
- * able to access apps data directly.
- * 3). For each related app, create its app data directory and bind mount the actual content
- * from apps data mirror directory. This works on both CE and DE storage, as DE storage
- * is always available even storage is FBE locked, while we use inode number to find
- * the encrypted DE directory in mirror so we can still bind mount it successfully.
+ * (1) Collect a list of all related apps (apps with same uid and allowlisted apps) data info
+ * (package name, data stored volume uuid, and inode number of its CE data directory)
+ * (2) Mount tmpfs on /data/data and /data/user{,_de}, and on /mnt/expand/$volume/user{,_de}
+ * for all adoptable storage volumes. This hides all app data directories.
+ * (3) For each related app, create stubs for its data directories in the relevant tmpfs
+ * instances, then bind mount in the actual directories from /data_mirror. This works
+ * for both the CE and DE directories. DE storage is always unlocked, whereas the
+ * app's CE directory can be found via inode number if CE storage is locked.
*
- * Example:
- * 0). Assuming com.android.foo CE data is stored in /data/data and no shared uid
- * 1). Mount a tmpfs on /data/data, /data/user, /data/user_de, /mnt/expand
- * List = ["com.android.foo", "null" (volume uuid "null"=default),
- * 123456 (inode number)]
- * 2). On DE storage, we create a directory /data/user_de/0/com.com.android.foo, and bind
- * mount (in the app's mount namespace) it from /data_mirror/data_de/0/com.android.foo.
- * 3). We do similar for CE storage. But in direct boot mode, as /data_mirror/data_ce/0/ is
- * encrypted, we can't find a directory with name com.android.foo on it, so we will
- * use the inode number to find the right directory instead, which that directory content will
- * be decrypted after storage is decrypted.
- *
+ * Example assuming user 0, app "com.android.foo", no shared uid, and no adoptable storage:
+ * (1) Info = ["com.android.foo", "null" (volume uuid "null"=default), "123456" (inode number)]
+ * (2) Mount tmpfs on /data/data, /data/user, and /data/user_de.
+ * (3) For DE storage, create a directory /data/user_de/0/com.android.foo and bind mount
+ * /data_mirror/data_de/0/com.android.foo onto it.
+ * (4) Do similar for CE storage. But if the device is in direct boot mode, then CE
+ * storage will be locked, so the app's CE data directory won't exist at the usual
+ * path /data_mirror/data_ce/0/com.android.foo. It will still exist in
+ * /data_mirror/data_ce/0, but its filename will be an unpredictable no-key name. In
+ * this case, we use the inode number to find the right directory instead. Note that
+ * the bind-mounted app CE data directory will remain locked. It will be unlocked
+ * automatically if/when the user's CE storage is unlocked, since adding an encryption
+ * key takes effect on a whole filesystem instance including all its mounts.
*/
static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
uid_t uid, const char* process_name,
diff --git a/core/tests/PackageInstallerSessions/Android.bp b/core/tests/PackageInstallerSessions/Android.bp
index c112cbb..de2a013 100644
--- a/core/tests/PackageInstallerSessions/Android.bp
+++ b/core/tests/PackageInstallerSessions/Android.bp
@@ -51,6 +51,5 @@
],
platform_apis: true,
- sdk_version: "core_platform",
test_suites: ["device-tests"],
}
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index f87797a..43a9679 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -35,7 +35,6 @@
"truth-prebuilt",
],
test_suites: ["general-tests"],
- sdk_version: "test_current",
platform_apis: true,
}
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 05ec00f..b521184 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -73,7 +73,6 @@
],
platform_apis: true,
- sdk_version: "core_platform",
test_suites: ["device-tests"],
certificate: "platform",
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 40662536..4a3350e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -320,7 +320,7 @@
info.className = Switch::class.java.name
}
- override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean {
+ override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean {
if (super.performAccessibilityAction(host, action, args)) {
return true
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b49654e..64ec12f 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -86,7 +86,10 @@
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
+import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
+import android.net.ipsec.ike.exceptions.IkeTimeoutException;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -122,6 +125,7 @@
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.NetworkStackConstants;
import com.android.server.DeviceIdleInternal;
@@ -207,7 +211,9 @@
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
private final NetworkInfo mNetworkInfo;
+ @GuardedBy("this")
private int mLegacyState;
+ @GuardedBy("this")
@VisibleForTesting protected String mPackage;
private int mOwnerUID;
private boolean mIsPackageTargetingAtLeastQ;
@@ -245,6 +251,7 @@
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
* only applies to {@link VpnService} connections.
*/
+ @GuardedBy("this")
@VisibleForTesting protected boolean mAlwaysOn = false;
/**
@@ -252,6 +259,7 @@
* apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is
* not set. Applies to all types of VPNs.
*/
+ @GuardedBy("this")
@VisibleForTesting protected boolean mLockdown = false;
/**
@@ -604,7 +612,7 @@
}
/** Returns the package name that is currently prepared. */
- public String getPackage() {
+ public synchronized String getPackage() {
return mPackage;
}
@@ -685,6 +693,36 @@
return true;
}
+ private boolean sendEventToVpnManagerApp(@NonNull String category, int errorClass,
+ int errorCode, @NonNull final String packageName, @Nullable final String sessionKey,
+ @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork,
+ @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) {
+ final Intent intent = new Intent(VpnManager.ACTION_VPN_MANAGER_EVENT);
+ intent.setPackage(packageName);
+ intent.addCategory(category);
+ intent.putExtra(VpnManager.EXTRA_VPN_PROFILE_STATE, profileState);
+ intent.putExtra(VpnManager.EXTRA_SESSION_KEY, sessionKey);
+ intent.putExtra(VpnManager.EXTRA_UNDERLYING_NETWORK, underlyingNetwork);
+ intent.putExtra(VpnManager.EXTRA_UNDERLYING_NETWORK_CAPABILITIES, nc);
+ intent.putExtra(VpnManager.EXTRA_UNDERLYING_LINK_PROPERTIES, lp);
+ intent.putExtra(VpnManager.EXTRA_TIMESTAMP_MILLIS, System.currentTimeMillis());
+ if (!VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER.equals(category)
+ || !VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED.equals(category)) {
+ intent.putExtra(VpnManager.EXTRA_ERROR_CLASS, errorClass);
+ intent.putExtra(VpnManager.EXTRA_ERROR_CODE, errorCode);
+ }
+ try {
+ return mUserIdContext.startService(intent) != null;
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e);
+ return false;
+ }
+ }
+
+ private boolean isVpnApp(String packageName) {
+ return packageName != null && !VpnConfig.LEGACY_VPN.equals(packageName);
+ }
+
/**
* Configures an always-on VPN connection through a specific application. This connection is
* automatically granted and persisted after a reboot.
@@ -707,9 +745,40 @@
boolean lockdown,
@Nullable List<String> lockdownAllowlist) {
enforceControlPermissionOrInternalCaller();
+ // Store mPackage since it might be reset or might be replaced with the other VPN app.
+ final String oldPackage = mPackage;
+ final boolean isPackageChanged = !Objects.equals(packageName, oldPackage);
+ // TODO: Remove "SdkLevel.isAtLeastT()" check once VpnManagerService is decoupled from
+ // ConnectivityServiceTest.
+ // Only notify VPN apps that were already always-on, and only if the always-on provider
+ // changed, or the lockdown mode changed.
+ final boolean shouldNotifyOldPkg = isVpnApp(oldPackage) && mAlwaysOn
+ && (lockdown != mLockdown || isPackageChanged);
+ // Also notify the new package if there was a provider change.
+ final boolean shouldNotifyNewPkg = isVpnApp(packageName) && isPackageChanged;
if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) {
saveAlwaysOnPackage();
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (shouldNotifyOldPkg && SdkLevel.isAtLeastT()) {
+ // If both of shouldNotifyOldPkg & isPackageChanged are true, which means the
+ // always-on of old package is disabled or the old package is replaced with the new
+ // package. In this case, VpnProfileState should be disconnected.
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
+ -1 /* errorClass */, -1 /* errorCode*/, oldPackage,
+ null /* sessionKey */, isPackageChanged ? makeDisconnectedVpnProfileState()
+ : makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (shouldNotifyNewPkg && SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
+ -1 /* errorClass */, -1 /* errorCode*/, packageName,
+ getSessionKeyLocked(), makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
return true;
}
return false;
@@ -1006,6 +1075,7 @@
return true;
}
+ @GuardedBy("this")
private boolean isCurrentPreparedPackage(String packageName) {
// We can't just check that packageName matches mPackage, because if the app was uninstalled
// and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the
@@ -1043,6 +1113,17 @@
if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
mAppOpsManager.finishOp(
AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null);
+ // The underlying network, NetworkCapabilities and LinkProperties are not
+ // necessary to send to VPN app since the purpose of this event is to notify
+ // VPN app that VPN is deactivated by the user.
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
+ -1 /* errorClass */, -1 /* errorCode*/, mPackage,
+ getSessionKeyLocked(), makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
}
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
@@ -1299,6 +1380,7 @@
return true;
}
+ @GuardedBy("this")
private void agentConnect() {
LinkProperties lp = makeLinkProperties();
@@ -1993,6 +2075,7 @@
return isIkev2VpnRunner() ? VpnManager.TYPE_VPN_PLATFORM : VpnManager.TYPE_VPN_LEGACY;
}
+ @GuardedBy("this")
private void updateAlwaysOnNotification(DetailedState networkState) {
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
@@ -2431,6 +2514,21 @@
}
}
+ @Nullable
+ protected synchronized NetworkCapabilities getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ NetworkCapabilities nc) {
+ if (nc == null) return null;
+ return mConnectivityManager.getRedactedNetworkCapabilitiesForPackage(
+ nc, mOwnerUID, mPackage);
+ }
+
+ @Nullable
+ protected synchronized LinkProperties getRedactedLinkPropertiesOfUnderlyingNetwork(
+ LinkProperties lp) {
+ if (lp == null) return null;
+ return mConnectivityManager.getRedactedLinkPropertiesForPackage(lp, mOwnerUID, mPackage);
+ }
+
/** This class represents the common interface for all VPN runners. */
@VisibleForTesting
abstract class VpnRunner extends Thread {
@@ -2465,6 +2563,10 @@
interface IkeV2VpnRunnerCallback {
void onDefaultNetworkChanged(@NonNull Network network);
+ void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc);
+
+ void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp);
+
void onChildOpened(
@NonNull Network network, @NonNull ChildSessionConfiguration childConfig);
@@ -2521,6 +2623,8 @@
@Nullable private IpSecTunnelInterface mTunnelIface;
@Nullable private IkeSession mSession;
@Nullable private Network mActiveNetwork;
+ @Nullable private NetworkCapabilities mNetworkCapabilities;
+ @Nullable private LinkProperties mLinkProperties;
private final String mSessionKey;
IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
@@ -2748,6 +2852,16 @@
}
}
+ /** Called when the NetworkCapabilities of underlying network is changed */
+ public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
+ mNetworkCapabilities = nc;
+ }
+
+ /** Called when the LinkProperties of underlying network is changed */
+ public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) {
+ mLinkProperties = lp;
+ }
+
/** Marks the state as FAILED, and disconnects. */
private void markFailedAndDisconnect(Exception exception) {
synchronized (Vpn.this) {
@@ -2778,28 +2892,120 @@
return;
}
- if (exception instanceof IkeProtocolException) {
- final IkeProtocolException ikeException = (IkeProtocolException) exception;
+ synchronized (Vpn.this) {
+ if (exception instanceof IkeProtocolException) {
+ final IkeProtocolException ikeException = (IkeProtocolException) exception;
- switch (ikeException.getErrorType()) {
- case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE:
- // All the above failures are configuration errors, and are terminal
- markFailedAndDisconnect(exception);
- return;
- // All other cases possibly recoverable.
+ switch (ikeException.getErrorType()) {
+ case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE:
+ // All the above failures are configuration errors, and are terminal
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
+ VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
+ ikeException.getErrorType(),
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ this.mNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ this.mLinkProperties));
+ }
+ markFailedAndDisconnect(exception);
+ return;
+ // All other cases possibly recoverable.
+ default:
+ // All the above failures are configuration errors, and are terminal
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ ikeException.getErrorType(),
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ this.mNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ this.mLinkProperties));
+ }
+ }
+ } else if (exception instanceof IllegalArgumentException) {
+ // Failed to build IKE/ChildSessionParams; fatal profile configuration error
+ markFailedAndDisconnect(exception);
+ return;
+ } else if (exception instanceof IkeNetworkLostException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_LOST,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ this.mNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ this.mLinkProperties));
+ }
+ } else if (exception instanceof IkeNonProtocolException) {
+ if (exception.getCause() instanceof UnknownHostException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ this.mNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ this.mLinkProperties));
+ }
+ } else if (exception.getCause() instanceof IkeTimeoutException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ this.mNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ this.mLinkProperties));
+ }
+ } else if (exception.getCause() instanceof IOException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_IO,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ this.mNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ this.mLinkProperties));
+ }
+ }
+ } else if (exception != null) {
+ Log.wtf(TAG, "onSessionLost: exception = " + exception);
}
- } else if (exception instanceof IllegalArgumentException) {
- // Failed to build IKE/ChildSessionParams; fatal profile configuration error
- markFailedAndDisconnect(exception);
- return;
}
mActiveNetwork = null;
+ mNetworkCapabilities = null;
+ mLinkProperties = null;
// Close all obsolete state, but keep VPN alive incase a usable network comes up.
// (Mirrors VpnService behavior)
@@ -2864,6 +3070,8 @@
*/
private void disconnectVpnRunner() {
mActiveNetwork = null;
+ mNetworkCapabilities = null;
+ mLinkProperties = null;
mIsRunning = false;
resetIkeState();
@@ -3490,11 +3698,19 @@
}
}
- private VpnProfileState makeVpnProfileState() {
+ @GuardedBy("this")
+ @NonNull
+ private VpnProfileState makeVpnProfileStateLocked() {
return new VpnProfileState(getStateFromLegacyState(mLegacyState),
isIkev2VpnRunner() ? getSessionKeyLocked() : null, mAlwaysOn, mLockdown);
}
+ @NonNull
+ private VpnProfileState makeDisconnectedVpnProfileState() {
+ return new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, null /* sessionKey */,
+ false /* alwaysOn */, false /* lockdown */);
+ }
+
/**
* Retrieve the VpnProfileState for the profile provisioned by the given package.
*
@@ -3506,7 +3722,7 @@
@NonNull String packageName) {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
- return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileState() : null;
+ return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileStateLocked() : null;
}
/**
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index 6982d60..e1e488d 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -50,7 +50,9 @@
import android.net.IpPrefix;
import android.net.IpSecAlgorithm;
import android.net.IpSecTransform;
+import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.RouteInfo;
import android.net.eap.EapSessionConfig;
import android.net.ipsec.ike.ChildSaProposal;
@@ -393,6 +395,22 @@
}
@Override
+ public void onCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ Log.d(mTag, "NC changed for net " + network + " : " + networkCapabilities);
+ mExecutor.execute(
+ () -> mCallback.onDefaultNetworkCapabilitiesChanged(networkCapabilities));
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(@NonNull Network network,
+ @NonNull LinkProperties linkProperties) {
+ Log.d(mTag, "LP changed for net " + network + " : " + linkProperties);
+ mExecutor.execute(
+ () -> mCallback.onDefaultNetworkLinkPropertiesChanged(linkProperties));
+ }
+
+ @Override
public void onLost(@NonNull Network network) {
Log.d(mTag, "Tearing down; lost network: " + network);
mExecutor.execute(() -> mCallback.onSessionLost(network, null));
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index 7e4f0e7..0a03338 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -25,7 +25,6 @@
android_test_helper_app {
name: "PackageManagerServiceDeviceSideTests",
- sdk_version: "test_current",
srcs: ["src/**/*.kt"],
libs: [
"android.test.base",