summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-08-08 01:03:19 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-08-08 01:03:19 +0000
commit78c75400d1ce7f7c9c2268f9021e1a72a5359893 (patch)
tree2cc96d713d11badba01eb3a1f325c039617ea30c
parent06a1af507d8d3c22451853df8857ab7d37168fcb (diff)
parent1315f1105e22066579f009facf60bc538d21d9fd (diff)
downloadbase-78c75400d1ce7f7c9c2268f9021e1a72a5359893.tar.gz
Snap for 6747166 from 1315f1105e22066579f009facf60bc538d21d9fd to rvc-d1-release
Change-Id: Ia2f2d5d765fdac515751afee9b09537f64482ec1
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java7
-rw-r--r--core/java/android/os/PowerManagerInternal.java4
-rw-r--r--core/jni/android_view_DisplayEventReceiver.cpp1
-rw-r--r--framework-jarjar-rules.txt4
-rw-r--r--packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java8
-rw-r--r--packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java10
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java45
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java261
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java7
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java73
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java5
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java29
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java189
13 files changed, 546 insertions, 97 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index ad9bf0745779..8d6e937488e4 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -260,6 +260,13 @@ public abstract class DisplayManagerInternal {
int displayId, long maxFrames, long timestamp);
/**
+ * Temporarily ignore proximity-sensor-based display behavior until there is a change
+ * to the proximity sensor state. This allows the display to turn back on even if something
+ * is obstructing the proximity sensor.
+ */
+ public abstract void ignoreProximitySensorUntilChanged();
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 653a5594f495..f9e146a9dbdc 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -17,6 +17,7 @@
package android.os;
import android.view.Display;
+import android.view.KeyEvent;
import java.util.function.Consumer;
@@ -319,4 +320,7 @@ public abstract class PowerManagerInternal {
/** Returns information about the last wakeup event. */
public abstract PowerManager.WakeData getLastWakeup();
+
+ /** Allows power button to intercept a power key button press. */
+ public abstract boolean interceptPowerKeyDown(KeyEvent event);
}
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 7daefd3e6544..26e862f4c03d 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -63,6 +63,7 @@ private:
void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
int32_t configId, nsecs_t vsyncPeriod) override;
+ void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) override {}
};
diff --git a/framework-jarjar-rules.txt b/framework-jarjar-rules.txt
index d8af726ffa72..70dedb8179b0 100644
--- a/framework-jarjar-rules.txt
+++ b/framework-jarjar-rules.txt
@@ -1,2 +1,6 @@
rule android.hidl.** android.internal.hidl.@1
rule android.net.wifi.WifiAnnotations* android.internal.wifi.WifiAnnotations@1
+
+# Hide media mainline module implementation classes to avoid collisions with
+# app-bundled ExoPlayer classes.
+rule com.google.android.exoplayer2.** android.media.internal.exo.@1
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
index 1e4c7cac4404..52d2b3c919d9 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
@@ -376,8 +376,12 @@ public abstract class Tile implements Parcelable {
* Check whether tile only has primary profile.
*/
public boolean isPrimaryProfileOnly() {
- String profile = mMetaData != null
- ? mMetaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
+ return isPrimaryProfileOnly(mMetaData);
+ }
+
+ static boolean isPrimaryProfileOnly(Bundle metaData) {
+ String profile = metaData != null
+ ? metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
profile = (profile != null ? profile : PROFILE_ALL);
return TextUtils.equals(profile, PROFILE_PRIMARY);
}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index ace50f30663d..49f6bd8c3334 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -339,6 +339,16 @@ public class TileUtils {
private static void loadTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, List<Tile> outTiles, Intent intent, Bundle metaData,
ComponentInfo componentInfo) {
+ // Skip loading tile if the component is tagged primary_profile_only but not running on
+ // the current user.
+ if (user.getIdentifier() != ActivityManager.getCurrentUser()
+ && Tile.isPrimaryProfileOnly(componentInfo.metaData)) {
+ Log.w(LOG_TAG, "Found " + componentInfo.name + " for intent "
+ + intent + " is primary profile only, skip loading tile for uid "
+ + user.getIdentifier());
+ return;
+ }
+
String categoryKey = defaultCategory;
// Load category
if ((metaData == null || !metaData.containsKey(EXTRA_CATEGORY_KEY))
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 9b4b97e7f55d..176905305506 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -17,11 +17,14 @@
package com.android.settingslib.drawer;
import static com.android.settingslib.drawer.TileUtils.IA_SETTINGS_ACTION;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
+import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
+import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
import static com.google.common.truth.Truth.assertThat;
@@ -189,7 +192,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, "my title", 0);
+ URI_GET_SUMMARY, "my title", 0, PROFILE_ALL);
info.add(resolveInfo);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
@@ -211,7 +214,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
info.add(resolveInfo);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
@@ -235,7 +238,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
resolveInfo.activityInfo.packageName = "com.android.settings";
resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
info.add(resolveInfo);
@@ -258,7 +261,7 @@ public class TileUtilsTest {
final List<Tile> outTiles = new ArrayList<>();
final List<ResolveInfo> info = new ArrayList<>();
final ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
resolveInfo.activityInfo.packageName = "com.android.settings";
resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
info.add(resolveInfo);
@@ -290,7 +293,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
resolveInfo.activityInfo.metaData
.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
info.add(resolveInfo);
@@ -327,6 +330,26 @@ public class TileUtilsTest {
assertThat(outTiles).hasSize(2);
}
+ @Test
+ public void loadTilesForAction_isPrimaryProfileOnly_shouldSkipNonPrimaryUserTiles() {
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123, PROFILE_PRIMARY);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+ .thenReturn(info);
+ when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
+ anyInt())).thenReturn(info);
+
+ TileUtils.loadTilesForAction(mContext, new UserHandle(10), IA_SETTINGS_ACTION,
+ addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+
+ assertThat(outTiles).isEmpty();
+ }
+
public static ResolveInfo newInfo(boolean systemApp, String category) {
return newInfo(systemApp, category, null);
}
@@ -337,14 +360,14 @@ public class TileUtilsTest {
private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint,
String iconUri, String summaryUri) {
- return newInfo(systemApp, category, keyHint, iconUri, summaryUri, null, 0);
+ return newInfo(systemApp, category, keyHint, iconUri, summaryUri, null, 0, PROFILE_ALL);
}
private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint,
- String iconUri, String summaryUri, String title, int titleResId) {
+ String iconUri, String summaryUri, String title, int titleResId, String profile) {
final Bundle metaData = newMetaData(category, keyHint, iconUri, summaryUri, title,
- titleResId);
+ titleResId, profile);
final ResolveInfo info = new ResolveInfo();
info.system = systemApp;
@@ -358,6 +381,7 @@ public class TileUtilsTest {
info.providerInfo.packageName = "abc";
info.providerInfo.name = "456";
info.providerInfo.authority = "auth";
+ info.providerInfo.metaData = metaData;
ShadowTileUtils.setMetaData(metaData);
info.providerInfo.applicationInfo = new ApplicationInfo();
@@ -369,7 +393,7 @@ public class TileUtilsTest {
}
private static Bundle newMetaData(String category, String keyHint, String iconUri,
- String summaryUri, String title, int titleResId) {
+ String summaryUri, String title, int titleResId, String profile) {
final Bundle metaData = new Bundle();
metaData.putString("com.android.settings.category", category);
metaData.putInt(META_DATA_PREFERENCE_ICON, 314159);
@@ -388,6 +412,9 @@ public class TileUtilsTest {
} else if (title != null) {
metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title);
}
+ if (profile != null) {
+ metaData.putString(META_DATA_KEY_PROFILE, profile);
+ }
return metaData;
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1f85d1046523..1c93d4eb599b 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -48,6 +48,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
+import android.net.DnsResolver;
import android.net.INetworkManagementEventObserver;
import android.net.Ikev2VpnProfile;
import android.net.IpPrefix;
@@ -79,6 +80,7 @@ import android.net.ipsec.ike.IkeSessionParams;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -123,6 +125,7 @@ import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
@@ -134,6 +137,8 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -190,6 +195,7 @@ public class Vpn {
// automated reconnection
private final Context mContext;
+ @VisibleForTesting final Dependencies mDeps;
private final NetworkInfo mNetworkInfo;
@VisibleForTesting protected String mPackage;
private int mOwnerUID;
@@ -252,17 +258,143 @@ public class Vpn {
// Handle of the user initiating VPN.
private final int mUserHandle;
+ interface RetryScheduler {
+ void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException;
+ }
+
+ static class Dependencies {
+ public void startService(final String serviceName) {
+ SystemService.start(serviceName);
+ }
+
+ public void stopService(final String serviceName) {
+ SystemService.stop(serviceName);
+ }
+
+ public boolean isServiceRunning(final String serviceName) {
+ return SystemService.isRunning(serviceName);
+ }
+
+ public boolean isServiceStopped(final String serviceName) {
+ return SystemService.isStopped(serviceName);
+ }
+
+ public File getStateFile() {
+ return new File("/data/misc/vpn/state");
+ }
+
+ public void sendArgumentsToDaemon(
+ final String daemon, final LocalSocket socket, final String[] arguments,
+ final RetryScheduler retryScheduler) throws IOException, InterruptedException {
+ final LocalSocketAddress address = new LocalSocketAddress(
+ daemon, LocalSocketAddress.Namespace.RESERVED);
+
+ // Wait for the socket to connect.
+ while (true) {
+ try {
+ socket.connect(address);
+ break;
+ } catch (Exception e) {
+ // ignore
+ }
+ retryScheduler.checkInterruptAndDelay(true /* sleepLonger */);
+ }
+ socket.setSoTimeout(500);
+
+ final OutputStream out = socket.getOutputStream();
+ for (String argument : arguments) {
+ byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
+ if (bytes.length >= 0xFFFF) {
+ throw new IllegalArgumentException("Argument is too large");
+ }
+ out.write(bytes.length >> 8);
+ out.write(bytes.length);
+ out.write(bytes);
+ retryScheduler.checkInterruptAndDelay(false /* sleepLonger */);
+ }
+ out.write(0xFF);
+ out.write(0xFF);
+
+ // Wait for End-of-File.
+ final InputStream in = socket.getInputStream();
+ while (true) {
+ try {
+ if (in.read() == -1) {
+ break;
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ retryScheduler.checkInterruptAndDelay(true /* sleepLonger */);
+ }
+ }
+
+ @NonNull
+ public InetAddress resolve(final String endpoint)
+ throws ExecutionException, InterruptedException {
+ try {
+ return InetAddress.parseNumericAddress(endpoint);
+ } catch (IllegalArgumentException e) {
+ // Endpoint is not numeric : fall through and resolve
+ }
+
+ final CancellationSignal cancellationSignal = new CancellationSignal();
+ try {
+ final DnsResolver resolver = DnsResolver.getInstance();
+ final CompletableFuture<InetAddress> result = new CompletableFuture();
+ final DnsResolver.Callback<List<InetAddress>> cb =
+ new DnsResolver.Callback<List<InetAddress>>() {
+ @Override
+ public void onAnswer(@NonNull final List<InetAddress> answer,
+ final int rcode) {
+ if (answer.size() > 0) {
+ result.complete(answer.get(0));
+ } else {
+ result.completeExceptionally(
+ new UnknownHostException(endpoint));
+ }
+ }
+
+ @Override
+ public void onError(@Nullable final DnsResolver.DnsException error) {
+ // Unfortunately UnknownHostException doesn't accept a cause, so
+ // print a message here instead. Only show the summary, not the
+ // full stack trace.
+ Log.e(TAG, "Async dns resolver error : " + error);
+ result.completeExceptionally(new UnknownHostException(endpoint));
+ }
+ };
+ resolver.query(null /* network, null for default */, endpoint,
+ DnsResolver.FLAG_EMPTY, r -> r.run(), cancellationSignal, cb);
+ return result.get();
+ } catch (final ExecutionException e) {
+ Log.e(TAG, "Cannot resolve VPN endpoint : " + endpoint + ".", e);
+ throw e;
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "Legacy VPN was interrupted while resolving the endpoint", e);
+ cancellationSignal.cancel();
+ throw e;
+ }
+ }
+
+ public boolean checkInterfacePresent(final Vpn vpn, final String iface) {
+ return vpn.jniCheck(iface) == 0;
+ }
+ }
+
public Vpn(Looper looper, Context context, INetworkManagementService netService,
@UserIdInt int userHandle, @NonNull KeyStore keyStore) {
- this(looper, context, netService, userHandle, keyStore,
+ this(looper, context, new Dependencies(), netService, userHandle, keyStore,
new SystemServices(context), new Ikev2SessionCreator());
}
@VisibleForTesting
- protected Vpn(Looper looper, Context context, INetworkManagementService netService,
+ protected Vpn(Looper looper, Context context, Dependencies deps,
+ INetworkManagementService netService,
int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices,
Ikev2SessionCreator ikev2SessionCreator) {
mContext = context;
+ mDeps = deps;
mNetd = netService;
mUserHandle = userHandle;
mLooper = looper;
@@ -2129,7 +2261,8 @@ public class Vpn {
}
/** This class represents the common interface for all VPN runners. */
- private abstract class VpnRunner extends Thread {
+ @VisibleForTesting
+ abstract class VpnRunner extends Thread {
protected VpnRunner(String name) {
super(name);
@@ -2638,7 +2771,7 @@ public class Vpn {
} catch (InterruptedException e) {
}
for (String daemon : mDaemons) {
- SystemService.stop(daemon);
+ mDeps.stopService(daemon);
}
}
agentDisconnect();
@@ -2655,21 +2788,55 @@ public class Vpn {
}
}
+ private void checkAndFixupArguments(@NonNull final InetAddress endpointAddress) {
+ final String endpointAddressString = endpointAddress.getHostAddress();
+ // Perform some safety checks before inserting the address in place.
+ // Position 0 in mDaemons and mArguments must be racoon, and position 1 must be mtpd.
+ if (!"racoon".equals(mDaemons[0]) || !"mtpd".equals(mDaemons[1])) {
+ throw new IllegalStateException("Unexpected daemons order");
+ }
+
+ // Respectively, the positions at which racoon and mtpd take the server address
+ // argument are 1 and 2. Not all types of VPN require both daemons however, and
+ // in that case the corresponding argument array is null.
+ if (mArguments[0] != null) {
+ if (!mProfile.server.equals(mArguments[0][1])) {
+ throw new IllegalStateException("Invalid server argument for racoon");
+ }
+ mArguments[0][1] = endpointAddressString;
+ }
+
+ if (mArguments[1] != null) {
+ if (!mProfile.server.equals(mArguments[1][2])) {
+ throw new IllegalStateException("Invalid server argument for mtpd");
+ }
+ mArguments[1][2] = endpointAddressString;
+ }
+ }
+
private void bringup() {
// Catch all exceptions so we can clean up a few things.
try {
+ // resolve never returns null. If it does because of some bug, it will be
+ // caught by the catch() block below and cleanup gracefully.
+ final InetAddress endpointAddress = mDeps.resolve(mProfile.server);
+
+ // Big hack : dynamically replace the address of the server in the arguments
+ // with the resolved address.
+ checkAndFixupArguments(endpointAddress);
+
// Initialize the timer.
mBringupStartTime = SystemClock.elapsedRealtime();
// Wait for the daemons to stop.
for (String daemon : mDaemons) {
- while (!SystemService.isStopped(daemon)) {
+ while (!mDeps.isServiceStopped(daemon)) {
checkInterruptAndDelay(true);
}
}
// Clear the previous state.
- File state = new File("/data/misc/vpn/state");
+ final File state = mDeps.getStateFile();
state.delete();
if (state.exists()) {
throw new IllegalStateException("Cannot delete the state");
@@ -2696,57 +2863,19 @@ public class Vpn {
// Start the daemon.
String daemon = mDaemons[i];
- SystemService.start(daemon);
+ mDeps.startService(daemon);
// Wait for the daemon to start.
- while (!SystemService.isRunning(daemon)) {
+ while (!mDeps.isServiceRunning(daemon)) {
checkInterruptAndDelay(true);
}
// Create the control socket.
mSockets[i] = new LocalSocket();
- LocalSocketAddress address = new LocalSocketAddress(
- daemon, LocalSocketAddress.Namespace.RESERVED);
-
- // Wait for the socket to connect.
- while (true) {
- try {
- mSockets[i].connect(address);
- break;
- } catch (Exception e) {
- // ignore
- }
- checkInterruptAndDelay(true);
- }
- mSockets[i].setSoTimeout(500);
-
- // Send over the arguments.
- OutputStream out = mSockets[i].getOutputStream();
- for (String argument : arguments) {
- byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
- if (bytes.length >= 0xFFFF) {
- throw new IllegalArgumentException("Argument is too large");
- }
- out.write(bytes.length >> 8);
- out.write(bytes.length);
- out.write(bytes);
- checkInterruptAndDelay(false);
- }
- out.write(0xFF);
- out.write(0xFF);
-
- // Wait for End-of-File.
- InputStream in = mSockets[i].getInputStream();
- while (true) {
- try {
- if (in.read() == -1) {
- break;
- }
- } catch (Exception e) {
- // ignore
- }
- checkInterruptAndDelay(true);
- }
+
+ // Wait for the socket to connect and send over the arguments.
+ mDeps.sendArgumentsToDaemon(daemon, mSockets[i], arguments,
+ this::checkInterruptAndDelay);
}
// Wait for the daemons to create the new state.
@@ -2754,7 +2883,7 @@ public class Vpn {
// Check if a running daemon is dead.
for (int i = 0; i < mDaemons.length; ++i) {
String daemon = mDaemons[i];
- if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
+ if (mArguments[i] != null && !mDeps.isServiceRunning(daemon)) {
throw new IllegalStateException(daemon + " is dead");
}
}
@@ -2764,7 +2893,8 @@ public class Vpn {
// Now we are connected. Read and parse the new state.
String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
if (parameters.length != 7) {
- throw new IllegalStateException("Cannot parse the state");
+ throw new IllegalStateException("Cannot parse the state: '"
+ + String.join("', '", parameters) + "'");
}
// Set the interface and the addresses in the config.
@@ -2793,20 +2923,15 @@ public class Vpn {
}
// Add a throw route for the VPN server endpoint, if one was specified.
- String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5];
- if (!endpoint.isEmpty()) {
- try {
- InetAddress addr = InetAddress.parseNumericAddress(endpoint);
- if (addr instanceof Inet4Address) {
- mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
- } else if (addr instanceof Inet6Address) {
- mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
- } else {
- Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
- }
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
- }
+ if (endpointAddress instanceof Inet4Address) {
+ mConfig.routes.add(new RouteInfo(
+ new IpPrefix(endpointAddress, 32), RTN_THROW));
+ } else if (endpointAddress instanceof Inet6Address) {
+ mConfig.routes.add(new RouteInfo(
+ new IpPrefix(endpointAddress, 128), RTN_THROW));
+ } else {
+ Log.e(TAG, "Unknown IP address family for VPN endpoint: "
+ + endpointAddress);
}
// Here is the last step and it must be done synchronously.
@@ -2818,7 +2943,7 @@ public class Vpn {
checkInterruptAndDelay(false);
// Check if the interface is gone while we are waiting.
- if (jniCheck(mConfig.interfaze) == 0) {
+ if (mDeps.checkInterfacePresent(Vpn.this, mConfig.interfaze)) {
throw new IllegalStateException(mConfig.interfaze + " is gone");
}
@@ -2849,7 +2974,7 @@ public class Vpn {
while (true) {
Thread.sleep(2000);
for (int i = 0; i < mDaemons.length; i++) {
- if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
+ if (mArguments[i] != null && mDeps.isServiceStopped(mDaemons[i])) {
return;
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 1058000e0b68..24661d69a78e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2548,8 +2548,7 @@ public final class DisplayManagerService extends SystemService {
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
- return mDisplayPowerController.requestPowerState(request,
- waitForNegativeProximity);
+ return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity);
}
}
@@ -2677,6 +2676,10 @@ public final class DisplayManagerService extends SystemService {
return getDisplayedContentSampleInternal(displayId, maxFrames, timestamp);
}
+ @Override
+ public void ignoreProximitySensorUntilChanged() {
+ mDisplayPowerController.ignoreProximitySensorUntilChanged();
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9411c5629457..7c0f4197363b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -117,6 +117,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int MSG_CONFIGURE_BRIGHTNESS = 5;
private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 6;
private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 7;
+ private static final int MSG_IGNORE_PROXIMITY = 8;
private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0;
@@ -263,6 +264,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// go to sleep by the user. While true, the screen remains off.
private boolean mWaitingForNegativeProximity;
+ // True if the device should not take into account the proximity sensor
+ // until either the proximity sensor state changes, or there is no longer a
+ // request to listen to proximity sensor.
+ private boolean mIgnoreProximityUntilChanged;
+
// The actual proximity sensor threshold value.
private float mProximityThreshold;
@@ -760,8 +766,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
- mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
- mPendingWaitForNegativeProximityLocked = false;
+ updatePendingProximityRequestsLocked();
mPendingRequestChangedLocked = false;
mustInitialize = true;
// Assume we're on and bright until told otherwise, since that's the state we turn
@@ -770,8 +775,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else if (mPendingRequestChangedLocked) {
previousPolicy = mPowerRequest.policy;
mPowerRequest.copyFrom(mPendingRequestLocked);
- mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
- mPendingWaitForNegativeProximityLocked = false;
+ updatePendingProximityRequestsLocked();
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
} else {
@@ -822,9 +826,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Apply the proximity sensor.
if (mProximitySensor != null) {
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
+ // At this point the policy says that the screen should be on, but we've been
+ // asked to listen to the prox sensor to adjust the display state, so lets make
+ // sure the sensor is on.
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
- && mProximity == PROXIMITY_POSITIVE) {
+ && mProximity == PROXIMITY_POSITIVE
+ && !mIgnoreProximityUntilChanged) {
+ // Prox sensor already reporting "near" so we should turn off the screen.
+ // Also checked that we aren't currently set to ignore the proximity sensor
+ // temporarily.
mScreenOffBecauseOfProximity = true;
sendOnProximityPositiveWithWakelock();
}
@@ -832,18 +843,28 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& state != Display.STATE_OFF) {
+ // The policy says that we should have the screen on, but it's off due to the prox
+ // and we've been asked to wait until the screen is far from the user to turn it
+ // back on. Let keep the prox sensor on so we can tell when it's far again.
setProximitySensorEnabled(true);
} else {
+ // We haven't been asked to use the prox sensor and we're not waiting on the screen
+ // to turn back on...so lets shut down the prox sensor.
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
+
if (mScreenOffBecauseOfProximity
- && mProximity != PROXIMITY_POSITIVE) {
+ && (mProximity != PROXIMITY_POSITIVE || mIgnoreProximityUntilChanged)) {
+ // The screen *was* off due to prox being near, but now it's "far" so lets turn
+ // the screen back on. Also turn it back on if we've been asked to ignore the
+ // prox sensor temporarily.
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
+ mIgnoreProximityUntilChanged = false;
}
if (mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
@@ -1181,6 +1202,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
sendUpdatePowerState();
}
+ /**
+ * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
+ * currently enabled and forcing the screen to be dark.
+ */
+ public void ignoreProximitySensorUntilChanged() {
+ mHandler.sendEmptyMessage(MSG_IGNORE_PROXIMITY);
+ }
+
public void setBrightnessConfiguration(BrightnessConfiguration c) {
Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS, c);
msg.sendToTarget();
@@ -1529,6 +1558,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Register the listener.
// Proximity sensor state already cleared initially.
mProximitySensorEnabled = true;
+ mIgnoreProximityUntilChanged = false;
mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
}
@@ -1538,6 +1568,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Clear the proximity sensor state for next time.
mProximitySensorEnabled = false;
mProximity = PROXIMITY_UNKNOWN;
+ mIgnoreProximityUntilChanged = false;
mPendingProximity = PROXIMITY_UNKNOWN;
mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
mSensorManager.unregisterListener(mProximitySensorListener);
@@ -1580,6 +1611,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
&& mPendingProximityDebounceTime >= 0) {
final long now = SystemClock.uptimeMillis();
if (mPendingProximityDebounceTime <= now) {
+ if (mProximity != mPendingProximity) {
+ // if the status of the sensor changed, stop ignoring.
+ mIgnoreProximityUntilChanged = false;
+ Slog.i(TAG, "No longer ignoring proximity [" + mPendingProximity + "]");
+ }
// Sensor reading accepted. Apply the change then release the wake lock.
mProximity = mPendingProximity;
updatePowerState();
@@ -1723,6 +1759,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
+ private void updatePendingProximityRequestsLocked() {
+ mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
+ mPendingWaitForNegativeProximityLocked = false;
+
+ if (mIgnoreProximityUntilChanged) {
+ // Also, lets stop waiting for negative proximity if we're ignoring it.
+ mWaitingForNegativeProximity = false;
+ }
+ }
+
+ private void ignoreProximitySensorUntilChangedInternal() {
+ if (!mIgnoreProximityUntilChanged
+ && mPowerRequest.useProximitySensor
+ && mProximity == PROXIMITY_POSITIVE) {
+ // Only ignore if it is still reporting positive (near)
+ mIgnoreProximityUntilChanged = true;
+ Slog.i(TAG, "Ignoring proximity");
+ updatePowerState();
+ }
+ }
+
private final Runnable mOnStateChangedRunnable = new Runnable() {
@Override
public void run() {
@@ -1961,6 +2018,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTemporaryAutoBrightnessAdjustment = Float.intBitsToFloat(msg.arg1);
updatePowerState();
break;
+
+ case MSG_IGNORE_PROXIMITY:
+ ignoreProximitySensorUntilChangedInternal();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0890b9212d2c..a4ed4e316ac3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -934,6 +934,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event);
+
GestureLauncherService gestureService = LocalServices.getService(
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
@@ -953,7 +955,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
- || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
+ || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted
+ || handledByPowerManager;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 764ac969e188..f965e5815f1b 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -85,6 +85,7 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import android.view.KeyEvent;
import com.android.internal.BrightnessSynchronizer;
import com.android.internal.annotations.VisibleForTesting;
@@ -5425,6 +5426,29 @@ public final class PowerManagerService extends SystemService
}
}
+ /**
+ * If the user presses power while the proximity sensor is enabled and keeping
+ * the screen off, then turn the screen back on by telling display manager to
+ * ignore the proximity sensor. We don't turn off the proximity sensor because
+ * we still want it to be reenabled if it's state changes.
+ *
+ * @return True if the proximity sensor was successfully ignored and we should
+ * consume the key event.
+ */
+ private boolean interceptPowerKeyDownInternal(KeyEvent event) {
+ synchronized (mLock) {
+ // DisplayPowerController only reports proximity positive (near) if it's
+ // positive and the proximity wasn't already being ignored. So it reliably
+ // also tells us that we're not already ignoring the proximity sensor.
+ if (mDisplayPowerRequest.useProximitySensor && mProximityPositive) {
+ mDisplayManagerInternal.ignoreProximitySensorUntilChanged();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@VisibleForTesting
final class LocalService extends PowerManagerInternal {
@Override
@@ -5561,5 +5585,10 @@ public final class PowerManagerService extends SystemService
public WakeData getLastWakeup() {
return getLastWakeupInternal();
}
+
+ @Override
+ public boolean interceptPowerKeyDown(KeyEvent event) {
+ return interceptPowerKeyDownInternal(event);
+ }
}
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 4ccf79a0cb37..de1c5759ee87 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -30,6 +30,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -49,6 +50,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.NotificationManager;
@@ -65,6 +67,7 @@ import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.IpSecManager;
import android.net.LinkProperties;
+import android.net.LocalSocket;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
@@ -74,6 +77,7 @@ import android.net.VpnManager;
import android.net.VpnService;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
+import android.os.ConditionVariable;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Process;
@@ -101,13 +105,20 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.net.Inet4Address;
+import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
/**
@@ -133,7 +144,8 @@ public class VpnTest {
managedProfileA.profileGroupId = primaryUser.id;
}
- static final String TEST_VPN_PKG = "com.dummy.vpn";
+ static final String EGRESS_IFACE = "wlan0";
+ static final String TEST_VPN_PKG = "com.testvpn.vpn";
private static final String TEST_VPN_SERVER = "1.2.3.4";
private static final String TEST_VPN_IDENTITY = "identity";
private static final byte[] TEST_VPN_PSK = "psk".getBytes();
@@ -1012,31 +1024,190 @@ public class VpnTest {
// a subsequent CL.
}
- @Test
- public void testStartLegacyVpn() throws Exception {
+ public Vpn startLegacyVpn(final VpnProfile vpnProfile) throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
setMockedUsers(primaryUser);
// Dummy egress interface
- final String egressIface = "DUMMY0";
final LinkProperties lp = new LinkProperties();
- lp.setInterfaceName(egressIface);
+ lp.setInterfaceName(EGRESS_IFACE);
final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- InetAddresses.parseNumericAddress("192.0.2.0"), egressIface);
+ InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE);
lp.addRoute(defaultRoute);
- vpn.startLegacyVpn(mVpnProfile, mKeyStore, lp);
+ vpn.startLegacyVpn(vpnProfile, mKeyStore, lp);
+ return vpn;
+ }
+ @Test
+ public void testStartPlatformVpn() throws Exception {
+ startLegacyVpn(mVpnProfile);
// TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
- // a subsequent CL.
+ // a subsequent patch.
+ }
+
+ @Test
+ public void testStartRacoonNumericAddress() throws Exception {
+ startRacoon("1.2.3.4", "1.2.3.4");
+ }
+
+ @Test
+ public void testStartRacoonHostname() throws Exception {
+ startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve
+ }
+
+ public void startRacoon(final String serverAddr, final String expectedAddr)
+ throws Exception {
+ final ConditionVariable legacyRunnerReady = new ConditionVariable();
+ final VpnProfile profile = new VpnProfile("testProfile" /* key */);
+ profile.type = VpnProfile.TYPE_L2TP_IPSEC_PSK;
+ profile.name = "testProfileName";
+ profile.username = "userName";
+ profile.password = "thePassword";
+ profile.server = serverAddr;
+ profile.ipsecIdentifier = "id";
+ profile.ipsecSecret = "secret";
+ profile.l2tpSecret = "l2tpsecret";
+ when(mConnectivityManager.getAllNetworks())
+ .thenReturn(new Network[] { new Network(101) });
+ when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(),
+ anyInt(), any(), anyInt())).thenAnswer(invocation -> {
+ // The runner has registered an agent and is now ready.
+ legacyRunnerReady.open();
+ return new Network(102);
+ });
+ final Vpn vpn = startLegacyVpn(profile);
+ final TestDeps deps = (TestDeps) vpn.mDeps;
+ try {
+ // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK
+ assertArrayEquals(
+ new String[] { EGRESS_IFACE, expectedAddr, "udppsk",
+ profile.ipsecIdentifier, profile.ipsecSecret, "1701" },
+ deps.racoonArgs.get(10, TimeUnit.SECONDS));
+ // literal values are hardcoded in Vpn.java for mtpd args
+ assertArrayEquals(
+ new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret,
+ "name", profile.username, "password", profile.password,
+ "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns",
+ "idle", "1800", "mtu", "1400", "mru", "1400" },
+ deps.mtpdArgs.get(10, TimeUnit.SECONDS));
+ // Now wait for the runner to be ready before testing for the route.
+ legacyRunnerReady.block(10_000);
+ // In this test the expected address is always v4 so /32
+ final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"),
+ RouteInfo.RTN_THROW);
+ assertTrue("Routes lack the expected throw route (" + expectedRoute + ") : "
+ + vpn.mConfig.routes,
+ vpn.mConfig.routes.contains(expectedRoute));
+ } finally {
+ // Now interrupt the thread, unblock the runner and clean up.
+ vpn.mVpnRunner.exitVpnRunner();
+ deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier
+ vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup
+ }
+ }
+
+ private static final class TestDeps extends Vpn.Dependencies {
+ public final CompletableFuture<String[]> racoonArgs = new CompletableFuture();
+ public final CompletableFuture<String[]> mtpdArgs = new CompletableFuture();
+ public final File mStateFile;
+
+ private final HashMap<String, Boolean> mRunningServices = new HashMap<>();
+
+ TestDeps() {
+ try {
+ mStateFile = File.createTempFile("vpnTest", ".tmp");
+ mStateFile.deleteOnExit();
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void startService(final String serviceName) {
+ mRunningServices.put(serviceName, true);
+ }
+
+ @Override
+ public void stopService(final String serviceName) {
+ mRunningServices.put(serviceName, false);
+ }
+
+ @Override
+ public boolean isServiceRunning(final String serviceName) {
+ return mRunningServices.getOrDefault(serviceName, false);
+ }
+
+ @Override
+ public boolean isServiceStopped(final String serviceName) {
+ return !isServiceRunning(serviceName);
+ }
+
+ @Override
+ public File getStateFile() {
+ return mStateFile;
+ }
+
+ @Override
+ public void sendArgumentsToDaemon(
+ final String daemon, final LocalSocket socket, final String[] arguments,
+ final Vpn.RetryScheduler interruptChecker) throws IOException {
+ if ("racoon".equals(daemon)) {
+ racoonArgs.complete(arguments);
+ } else if ("mtpd".equals(daemon)) {
+ writeStateFile(arguments);
+ mtpdArgs.complete(arguments);
+ } else {
+ throw new UnsupportedOperationException("Unsupported daemon : " + daemon);
+ }
+ }
+
+ private void writeStateFile(final String[] arguments) throws IOException {
+ mStateFile.delete();
+ mStateFile.createNewFile();
+ mStateFile.deleteOnExit();
+ final BufferedWriter writer = new BufferedWriter(
+ new FileWriter(mStateFile, false /* append */));
+ writer.write(EGRESS_IFACE);
+ writer.write("\n");
+ // addresses
+ writer.write("10.0.0.1/24\n");
+ // routes
+ writer.write("192.168.6.0/24\n");
+ // dns servers
+ writer.write("192.168.6.1\n");
+ // search domains
+ writer.write("vpn.searchdomains.com\n");
+ // endpoint - intentionally empty
+ writer.write("\n");
+ writer.flush();
+ writer.close();
+ }
+
+ @Override
+ @NonNull
+ public InetAddress resolve(final String endpoint) {
+ try {
+ // If a numeric IP address, return it.
+ return InetAddress.parseNumericAddress(endpoint);
+ } catch (IllegalArgumentException e) {
+ // Otherwise, return some token IP to test for.
+ return InetAddress.parseNumericAddress("5.6.7.8");
+ }
+ }
+
+ @Override
+ public boolean checkInterfacePresent(final Vpn vpn, final String iface) {
+ return true;
+ }
}
/**
* Mock some methods of vpn object.
*/
private Vpn createVpn(@UserIdInt int userId) {
- return new Vpn(Looper.myLooper(), mContext, mNetService,
+ return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService,
userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
}