Merge "APIs to measure and delete contributed files."
diff --git a/api/current.txt b/api/current.txt
index 8919257..784f454 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6664,7 +6664,7 @@
method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
method public void setEndUserSessionMessage(android.content.ComponentName, java.lang.CharSequence);
- method public void setGlobalPrivateDns(android.content.ComponentName, int, java.lang.String);
+ method public int setGlobalPrivateDns(android.content.ComponentName, int, java.lang.String);
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
method public boolean setKeyPairCertificate(android.content.ComponentName, java.lang.String, java.util.List<java.security.cert.Certificate>, boolean);
@@ -6845,6 +6845,9 @@
field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2
field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
field public static final int PRIVATE_DNS_MODE_UNKNOWN = 0; // 0x0
+ field public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2; // 0x2
+ field public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1; // 0x1
+ field public static final int PRIVATE_DNS_SET_SUCCESS = 0; // 0x0
field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e826250..8e54961 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -49,6 +49,8 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
+import android.net.NetworkUtils;
+import android.net.PrivateDnsConnectivityChecker;
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.Binder;
@@ -79,6 +81,7 @@
import android.service.restrictions.RestrictionsReceiver;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -2032,6 +2035,35 @@
public @interface InstallUpdateCallbackErrorConstants {}
/**
+ * The selected mode has been set successfully. If the mode is
+ * {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} then it implies the supplied host is valid
+ * and reachable.
+ */
+ public static final int PRIVATE_DNS_SET_SUCCESS = 0;
+
+ /**
+ * If the {@code privateDnsHost} provided was of a valid hostname but that host was found
+ * to not support DNS-over-TLS.
+ */
+ public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1;
+
+ /**
+ * General failure to set the Private DNS mode, not due to one of the reasons listed above.
+ */
+ public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = {"PRIVATE_DNS_SET_"}, value = {
+ PRIVATE_DNS_SET_SUCCESS,
+ PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING,
+ PRIVATE_DNS_SET_ERROR_FAILURE_SETTING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SetPrivateDnsModeResultConstants {}
+
+ /**
* Return true if the given administrator component is currently active (enabled) in the system.
*
* @param admin The administrator component to check for.
@@ -9897,6 +9929,16 @@
* Sets the global Private DNS mode and host to be used.
* May only be called by the device owner.
*
+ * <p>Note that in case a Private DNS resolver is specified, the method is blocking as it
+ * will perform a connectivity check to the resolver, to ensure it is valid. Because of that,
+ * the method should not be called on any thread that relates to user interaction, such as the
+ * UI thread.
+ *
+ * <p>In case a VPN is used in conjunction with Private DNS resolver, the Private DNS resolver
+ * must be reachable both from within and outside the VPN. Otherwise, the device may lose
+ * the ability to resolve hostnames as system traffic to the resolver may not go through the
+ * VPN.
+ *
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @param mode Which mode to set - either {@code PRIVATE_DNS_MODE_OPPORTUNISTIC} or
* {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}.
@@ -9906,6 +9948,9 @@
* @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858), if
* {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} was specified as the mode,
* null otherwise.
+ *
+ * @return One of the values in {@link SetPrivateDnsModeResultConstants}.
+ *
* @throws IllegalArgumentException in the following cases: if a {@code privateDnsHost} was
* provided but the mode was not {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}, if the mode
* specified was {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} but {@code privateDnsHost} does
@@ -9913,15 +9958,23 @@
*
* @throws SecurityException if the caller is not the device owner.
*/
- public void setGlobalPrivateDns(@NonNull ComponentName admin,
+ public int setGlobalPrivateDns(@NonNull ComponentName admin,
@PrivateDnsMode int mode, @Nullable String privateDnsHost) {
throwIfParentInstance("setGlobalPrivateDns");
+
if (mService == null) {
- return;
+ return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
+ }
+
+ if (mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME && !TextUtils.isEmpty(privateDnsHost)
+ && NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+ if (!PrivateDnsConnectivityChecker.canConnectToPrivateDnsServer(privateDnsHost)) {
+ return PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING;
+ }
}
try {
- mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
+ return mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index fcf74ee..1148685 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -415,7 +415,7 @@
boolean isMeteredDataDisabledPackageForUser(in ComponentName admin, String packageName, int userId);
- void setGlobalPrivateDns(in ComponentName admin, int mode, in String privateDnsHost);
+ int setGlobalPrivateDns(in ComponentName admin, int mode, in String privateDnsHost);
int getGlobalPrivateDnsMode(in ComponentName admin);
String getGlobalPrivateDnsHost(in ComponentName admin);
diff --git a/core/java/android/net/PrivateDnsConnectivityChecker.java b/core/java/android/net/PrivateDnsConnectivityChecker.java
new file mode 100644
index 0000000..cfd458c
--- /dev/null
+++ b/core/java/android/net/PrivateDnsConnectivityChecker.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * Class for testing connectivity to DNS-over-TLS servers.
+ * {@hide}
+ */
+public class PrivateDnsConnectivityChecker {
+ private static final String TAG = "NetworkUtils";
+
+ private static final int PRIVATE_DNS_PORT = 853;
+ private static final int CONNECTION_TIMEOUT_MS = 5000;
+
+ private PrivateDnsConnectivityChecker() { }
+
+ /**
+ * checks that a provided host can perform a TLS handshake on port 853.
+ * @param hostname host to connect to.
+ */
+ public static boolean canConnectToPrivateDnsServer(@NonNull String hostname) {
+ final SocketFactory factory = SSLSocketFactory.getDefault();
+ TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_APP);
+
+ try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
+ socket.setSoTimeout(CONNECTION_TIMEOUT_MS);
+ socket.connect(new InetSocketAddress(hostname, PRIVATE_DNS_PORT));
+ if (!socket.isConnected()) {
+ Log.w(TAG, String.format("Connection to %s failed.", hostname));
+ return false;
+ }
+ socket.startHandshake();
+ Log.w(TAG, String.format("TLS handshake to %s succeeded.", hostname));
+ return true;
+ } catch (IOException e) {
+ Log.w(TAG, String.format("TLS handshake to %s failed.", hostname), e);
+ return false;
+ }
+ }
+}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 8cafbde..7abe913 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -16,14 +16,13 @@
package android.os;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.opengl.EGL14;
-import android.os.Build;
-import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
@@ -37,6 +36,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/** @hide */
public class GraphicsEnvironment {
@@ -67,7 +71,7 @@
*/
public void setup(Context context, Bundle coreSettings) {
setupGpuLayers(context, coreSettings);
- setupAngle(context, coreSettings);
+ setupAngle(context, context.getPackageName());
chooseDriver(context, coreSettings);
}
@@ -192,24 +196,101 @@
setLayerPaths(mClassLoader, layerPaths);
}
+ enum OpenGlDriverChoice {
+ DEFAULT,
+ NATIVE,
+ ANGLE
+ }
+
+ private static final Map<OpenGlDriverChoice, String> sDriverMap = buildMap();
+ private static Map<OpenGlDriverChoice, String> buildMap() {
+ Map<OpenGlDriverChoice, String> map = new HashMap<>();
+ map.put(OpenGlDriverChoice.DEFAULT, "default");
+ map.put(OpenGlDriverChoice.ANGLE, "angle");
+ map.put(OpenGlDriverChoice.NATIVE, "native");
+
+ return map;
+ }
+
+
+ private static List<String> getGlobalSettingsString(Context context, String globalSetting) {
+ List<String> valueList = null;
+ ContentResolver contentResolver = context.getContentResolver();
+ String settingsValue = Settings.Global.getString(contentResolver, globalSetting);
+
+ if (settingsValue != null) {
+ valueList = new ArrayList<>(Arrays.asList(settingsValue.split(",")));
+ } else {
+ valueList = new ArrayList<>();
+ }
+
+ return valueList;
+ }
+
+ private static int getGlobalSettingsPkgIndex(String pkgName,
+ List<String> globalSettingsDriverPkgs) {
+ for (int pkgIndex = 0; pkgIndex < globalSettingsDriverPkgs.size(); pkgIndex++) {
+ if (globalSettingsDriverPkgs.get(pkgIndex).equals(pkgName)) {
+ return pkgIndex;
+ }
+ }
+
+ return -1;
+ }
+
+ private static String getDriverForPkg(Context context, String packageName) {
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ int allUseAngle = Settings.Global.getInt(contentResolver,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+ if (allUseAngle == 1) {
+ return sDriverMap.get(OpenGlDriverChoice.ANGLE);
+ }
+ } catch (Settings.SettingNotFoundException e) {
+ // Do nothing and move on
+ }
+
+ List<String> globalSettingsDriverPkgs =
+ getGlobalSettingsString(context,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS);
+ List<String> globalSettingsDriverValues =
+ getGlobalSettingsString(context,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES);
+
+ // Make sure we have a good package name
+ if ((packageName == null) || (packageName.isEmpty())) {
+ return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
+ }
+ // Make sure we have good settings to use
+ if (globalSettingsDriverPkgs.isEmpty() || globalSettingsDriverValues.isEmpty()
+ || (globalSettingsDriverPkgs.size() != globalSettingsDriverValues.size())) {
+ Log.w(TAG,
+ "Global.Settings values are invalid: "
+ + "globalSettingsDriverPkgs.size = "
+ + globalSettingsDriverPkgs.size() + ", "
+ + "globalSettingsDriverValues.size = "
+ + globalSettingsDriverValues.size());
+ return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
+ }
+
+ int pkgIndex = getGlobalSettingsPkgIndex(packageName, globalSettingsDriverPkgs);
+
+ if (pkgIndex < 0) {
+ return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
+ }
+
+ return globalSettingsDriverValues.get(pkgIndex);
+ }
+
/**
* Pass ANGLE details down to trigger enable logic
*/
- private static void setupAngle(Context context, Bundle coreSettings) {
+ private void setupAngle(Context context, String packageName) {
+ String devOptIn = getDriverForPkg(context, packageName);
- String angleEnabledApp =
- coreSettings.getString(Settings.Global.ANGLE_ENABLED_APP);
-
- String packageName = context.getPackageName();
-
- boolean devOptIn = false;
- if ((angleEnabledApp != null && packageName != null)
- && (!angleEnabledApp.isEmpty() && !packageName.isEmpty())
- && angleEnabledApp.equals(packageName)) {
-
- Log.i(TAG, packageName + " opted in for ANGLE via Developer Setting");
-
- devOptIn = true;
+ if (DEBUG) {
+ Log.v(TAG, "ANGLE Developer option for '" + packageName + "' "
+ + "set to: '" + devOptIn + "'");
}
ApplicationInfo angleInfo;
@@ -303,8 +384,7 @@
// Further opt-in logic is handled in native, so pass relevant info down
// TODO: Move the ANGLE selection logic earlier so we don't need to keep these
// file descriptors open.
- setAngleInfo(paths, packageName, devOptIn,
- rulesFd, rulesOffset, rulesLength);
+ setAngleInfo(paths, packageName, devOptIn, rulesFd, rulesOffset, rulesLength);
}
/**
@@ -452,6 +532,6 @@
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPath(String path);
private static native void setAngleInfo(String path, String appPackage,
- boolean devOptIn, FileDescriptor rulesFd,
+ String devOptIn, FileDescriptor rulesFd,
long rulesOffset, long rulesLength);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 98a1701..3437e1d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11878,10 +11878,26 @@
public static final String GPU_DEBUG_APP = "gpu_debug_app";
/**
- * App should try to use ANGLE
+ * Force all PKGs to use ANGLE, regardless of any other settings
+ * The value is a boolean (1 or 0).
* @hide
*/
- public static final String ANGLE_ENABLED_APP = "angle_enabled_app";
+ public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE =
+ "angle_gl_driver_all_angle";
+
+ /**
+ * List of PKGs that have an OpenGL driver selected
+ * @hide
+ */
+ public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS =
+ "angle_gl_driver_selection_pkgs";
+
+ /**
+ * List of selected OpenGL drivers, corresponding to the PKGs in GLOBAL_SETTINGS_DRIVER_PKGS
+ * @hide
+ */
+ public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES =
+ "angle_gl_driver_selection_values";
/**
* App that is selected to use updated graphics driver.
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index b1a9866..06625b3 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,15 +32,16 @@
android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
}
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jboolean devOptIn,
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring devOptIn,
jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
ScopedUtfChars pathChars(env, path);
ScopedUtfChars appNameChars(env, appName);
+ ScopedUtfChars devOptInChars(env, devOptIn);
int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd);
android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
- devOptIn, rulesFd_native, rulesOffset, rulesLength);
+ devOptInChars.c_str(), rulesFd_native, rulesOffset, rulesLength);
}
void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
@@ -67,7 +68,7 @@
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
- { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
+ { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
{ "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
{ "setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayersGLES_native) },
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index ca8da55..da6e208 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -417,16 +417,20 @@
// Ordered GPU debug layer list for Vulkan
// i.e. <layer1>:<layer2>:...:<layerN>
optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // App will load ANGLE instead of native GLES drivers.
- optional SettingProto angle_enabled_app = 3;
+ // ANGLE - Force all PKGs to use ANGLE, regardless of any other settings
+ optional SettingProto angle_gl_driver_all_angle = 3;
+ // ANGLE - List of PKGs that specify an OpenGL driver
+ optional SettingProto angle_gl_driver_selection_pkgs = 4;
+ // ANGLE - Corresponding OpenGL driver selection for the PKG
+ optional SettingProto angle_gl_driver_selection_values = 5;
// App that can provide layer libraries.
- optional SettingProto debug_layer_app = 4;
+ optional SettingProto debug_layer_app = 6;
// Ordered GPU debug layer list for GLES
// i.e. <layer1>:<layer2>:...:<layerN>
- optional SettingProto debug_layers_gles = 5;
+ optional SettingProto debug_layers_gles = 7;
// App opt in to load updated graphics driver instead of
// native graphcis driver through developer options.
- optional SettingProto updated_gfx_driver_dev_opt_in_app = 6;
+ optional SettingProto updated_gfx_driver_dev_opt_in_app = 8;
}
optional Gpu gpu = 59;
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 1d72a03..79eaab8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -470,7 +470,9 @@
Settings.Global.GPU_DEBUG_APP,
Settings.Global.GPU_DEBUG_LAYERS,
Settings.Global.GPU_DEBUG_LAYERS_GLES,
- Settings.Global.ANGLE_ENABLED_APP,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
Settings.Global.GPU_DEBUG_LAYER_APP,
Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 5e7fb85..533956f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -685,8 +685,14 @@
Settings.Global.GPU_DEBUG_LAYERS,
GlobalSettingsProto.Gpu.DEBUG_LAYERS);
dumpSetting(s, p,
- Settings.Global.ANGLE_ENABLED_APP,
- GlobalSettingsProto.Gpu.ANGLE_ENABLED_APP);
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+ GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_ALL_ANGLE);
+ dumpSetting(s, p,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
+ GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_PKGS);
+ dumpSetting(s, p,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
+ GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_VALUES);
dumpSetting(s, p,
Settings.Global.GPU_DEBUG_LAYER_APP,
GlobalSettingsProto.Gpu.DEBUG_LAYER_APP);
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8e0bfb6..b6c9b8c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -23,6 +23,8 @@
<dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen>
<!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. -->
<dimen name="navigation_bar_min_swipe_distance">48dp</dimen>
+ <!-- The distance from a side of device of the navigation bar to start an edge swipe -->
+ <dimen name="navigation_bar_edge_swipe_threshold">60dp</dimen>
<!-- thickness (height) of the dead zone at the top of the navigation bar,
reducing false presses on navbar buttons; approx 2mm -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
index b83ebc7..9c8b1b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
@@ -56,6 +56,11 @@
}
@Override
+ public boolean allowHitTargetToMoveOverDrag() {
+ return true;
+ }
+
+ @Override
public boolean canPerformAction() {
return mProxySender.getBackButtonAlpha() > 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index cd6e1d7..e215c31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -154,6 +154,7 @@
private QuickScrubAction mQuickScrubAction;
private QuickStepAction mQuickStepAction;
private NavigationBackAction mBackAction;
+ private QuickSwitchAction mQuickSwitchAction;
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -326,9 +327,10 @@
mQuickScrubAction = new QuickScrubAction(this, mOverviewProxyService);
mQuickStepAction = new QuickStepAction(this, mOverviewProxyService);
mBackAction = new NavigationBackAction(this, mOverviewProxyService);
+ mQuickSwitchAction = new QuickSwitchAction(this, mOverviewProxyService);
mDefaultGestureMap = new NavigationGestureAction[] {
mQuickStepAction, null /* swipeDownAction*/, null /* swipeLeftAction */,
- mQuickScrubAction
+ mQuickScrubAction, null /* swipeLeftEdgeAction */, null /* swipeRightEdgeAction */
};
mPrototypeController = new NavigationPrototypeController(mHandler, mContext);
@@ -359,7 +361,9 @@
getNavigationActionFromType(assignedMap[0], mDefaultGestureMap[0]),
getNavigationActionFromType(assignedMap[1], mDefaultGestureMap[1]),
getNavigationActionFromType(assignedMap[2], mDefaultGestureMap[2]),
- getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]));
+ getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]),
+ getNavigationActionFromType(assignedMap[4], mDefaultGestureMap[4]),
+ getNavigationActionFromType(assignedMap[5], mDefaultGestureMap[5]));
}
}
@@ -372,6 +376,8 @@
return mQuickScrubAction;
case NavigationPrototypeController.ACTION_BACK:
return mBackAction;
+ case NavigationPrototypeController.ACTION_QUICKSWITCH:
+ return mQuickSwitchAction;
default:
return defaultAction;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
index a8d00c4..8c57fc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
@@ -112,7 +112,7 @@
/**
* @return whether or not to move the button that started gesture over with user input drag
*/
- public boolean requiresDragWithHitTarget() {
+ public boolean allowHitTargetToMoveOverDrag() {
return false;
}
@@ -139,9 +139,9 @@
* Tell if action is enabled. Compared to {@link #canPerformAction()} this is based on settings
* if the action is disabled for a particular gesture. For example a back action can be enabled
* however if there is nothing to back to then {@link #canPerformAction()} should return false.
- * In this way if the action requires {@link #requiresDragWithHitTarget()} then if enabled, the
- * button can be dragged with a large dampening factor during the gesture but will not activate
- * the action.
+ * In this way if the action requires {@link #allowHitTargetToMoveOverDrag()} then if enabled,
+ * the button can be dragged with a large dampening factor during the gesture but will not
+ * activate the action.
* @return true if this action is enabled and can run
*/
public abstract boolean isEnabled();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
index e8c0bf1..b11b6d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -24,7 +24,6 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
-import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -46,6 +45,7 @@
static final int ACTION_QUICKSTEP = 1;
static final int ACTION_QUICKSCRUB = 2;
static final int ACTION_BACK = 3;
+ static final int ACTION_QUICKSWITCH = 4;
private OnPrototypeChangedListener mListener;
@@ -53,7 +53,7 @@
* Each index corresponds to a different action set in QuickStepController
* {@see updateSwipeLTRBackSetting}
*/
- private int[] mActionMap = new int[4];
+ private int[] mActionMap = new int[6];
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
index 2b202eb..bbfd51a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
@@ -18,8 +18,6 @@
import static com.android.systemui.Interpolators.ALPHA_IN;
import static com.android.systemui.Interpolators.ALPHA_OUT;
-import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -31,11 +29,8 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RadialGradient;
-import android.graphics.Rect;
import android.graphics.Shader;
-import android.os.RemoteException;
import android.util.FloatProperty;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -46,7 +41,7 @@
/**
* QuickScrub action to send to launcher to start quickscrub gesture
*/
-public class QuickScrubAction extends NavigationGestureAction {
+public class QuickScrubAction extends QuickSwitchAction {
private static final String TAG = "QuickScrubAction";
private static final float TRACK_SCALE = 0.95f;
@@ -65,7 +60,6 @@
private final int mTrackThickness;
private final int mTrackEndPadding;
private final Paint mTrackPaint = new Paint();
- private final Rect mTrackRect = new Rect();
private final FloatProperty<QuickScrubAction> mTrackAlphaProperty =
new FloatProperty<QuickScrubAction>("TrackAlpha") {
@@ -177,7 +171,7 @@
x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
x2 = x1 + width - 2 * mTrackEndPadding;
}
- mTrackRect.set(x1, y1, x2, y2);
+ mDragOverRect.set(x1, y1, x2, y2);
}
@Override
@@ -194,15 +188,16 @@
mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
// Scale the track, but apply the inverse scale from the nav bar
- final float radius = mTrackRect.height() / 2;
+ final float radius = mDragOverRect.height() / 2;
canvas.save();
- float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
+ float translate = Utilities.clamp(mHighlightCenter, mDragOverRect.left,
+ mDragOverRect.right);
canvas.translate(translate, 0);
canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
1f / mNavigationBarView.getScaleY(),
- mTrackRect.centerX(), mTrackRect.centerY());
- canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
- mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
+ mDragOverRect.centerX(), mDragOverRect.centerY());
+ canvas.drawRoundRect(mDragOverRect.left - translate, mDragOverRect.top,
+ mDragOverRect.right - translate, mDragOverRect.bottom, radius, radius, mTrackPaint);
canvas.restore();
}
@@ -212,11 +207,6 @@
}
@Override
- public boolean disableProxyEvents() {
- return true;
- }
-
- @Override
protected void onGestureStart(MotionEvent event) {
updateHighlight();
ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
@@ -231,42 +221,12 @@
mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
mTrackAnimator.start();
- // Disable slippery for quick scrub to not cancel outside the nav bar
- mNavigationBarView.updateSlippery();
-
- try {
- mProxySender.getProxy().onQuickScrubStart();
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub Start");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send start of quick scrub.", e);
- }
- mProxySender.notifyQuickScrubStarted();
+ startQuickGesture(event);
}
@Override
public void onGestureMove(int x, int y) {
- int trackSize, offset;
- if (isNavBarVertical()) {
- trackSize = mTrackRect.height();
- offset = y - mTrackRect.top;
- } else {
- offset = x - mTrackRect.left;
- trackSize = mTrackRect.width();
- }
- if (!mDragHorizontalPositive || !mDragVerticalPositive) {
- offset -= isNavBarVertical() ? mTrackRect.height() : mTrackRect.width();
- }
- float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
- try {
- mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send progress of quick scrub.", e);
- }
+ super.onGestureMove(x, y);
mHighlightCenter = x;
mNavigationBarView.invalidate();
}
@@ -278,14 +238,7 @@
private void endQuickScrub(boolean animate) {
animateEnd();
- try {
- mProxySender.getProxy().onQuickScrubEnd();
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub End");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send end of quick scrub.", e);
- }
+ endQuickGesture(animate);
if (!animate) {
if (mTrackAnimator != null) {
mTrackAnimator.end();
@@ -295,7 +248,7 @@
}
private void updateHighlight() {
- if (mTrackRect.isEmpty()) {
+ if (mDragOverRect.isEmpty()) {
return;
}
int colorBase, colorGrad;
@@ -306,8 +259,8 @@
colorBase = getContext().getColor(R.color.quick_step_track_background_background_light);
colorGrad = getContext().getColor(R.color.quick_step_track_background_foreground_light);
}
- final RadialGradient mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
- mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
+ final RadialGradient mHighlight = new RadialGradient(0, mDragOverRect.height() / 2,
+ mDragOverRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
Shader.TileMode.CLAMP);
mTrackPaint.setShader(mHighlight);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 4983618..9eb5737a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -76,7 +76,9 @@
private static final int ACTION_SWIPE_DOWN_INDEX = 1;
private static final int ACTION_SWIPE_LEFT_INDEX = 2;
private static final int ACTION_SWIPE_RIGHT_INDEX = 3;
- private static final int MAX_GESTURES = 4;
+ private static final int ACTION_SWIPE_LEFT_FROM_EDGE_INDEX = 4;
+ private static final int ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX = 5;
+ private static final int MAX_GESTURES = 6;
private NavigationBarView mNavigationBarView;
@@ -97,6 +99,7 @@
private float mMaxDragLimit;
private float mMinDragLimit;
private float mDragDampeningFactor;
+ private float mEdgeSwipeThreshold;
private NavigationGestureAction mCurrentAction;
private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES];
@@ -128,15 +131,21 @@
* @param swipeDownAction action after swiping down
* @param swipeLeftAction action after swiping left
* @param swipeRightAction action after swiping right
+ * @param swipeLeftFromEdgeAction action swiping left starting from the right side
+ * @param swipeRightFromEdgeAction action swiping right starting from the left side
*/
public void setGestureActions(@Nullable NavigationGestureAction swipeUpAction,
@Nullable NavigationGestureAction swipeDownAction,
@Nullable NavigationGestureAction swipeLeftAction,
- @Nullable NavigationGestureAction swipeRightAction) {
+ @Nullable NavigationGestureAction swipeRightAction,
+ @Nullable NavigationGestureAction swipeLeftFromEdgeAction,
+ @Nullable NavigationGestureAction swipeRightFromEdgeAction) {
mGestureActions[ACTION_SWIPE_UP_INDEX] = swipeUpAction;
mGestureActions[ACTION_SWIPE_DOWN_INDEX] = swipeDownAction;
mGestureActions[ACTION_SWIPE_LEFT_INDEX] = swipeLeftAction;
mGestureActions[ACTION_SWIPE_RIGHT_INDEX] = swipeRightAction;
+ mGestureActions[ACTION_SWIPE_LEFT_FROM_EDGE_INDEX] = swipeLeftFromEdgeAction;
+ mGestureActions[ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX] = swipeRightFromEdgeAction;
// Set the current state to all actions
for (NavigationGestureAction action: mGestureActions) {
@@ -233,6 +242,8 @@
mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
mAllowGestureDetection = true;
mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed();
+ mEdgeSwipeThreshold = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold);
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -284,13 +295,17 @@
}
} else if (exceededSwipeHorizontalTouchSlop) {
if (mDragHPositive ? (posH < touchDownH) : (posH > touchDownH)) {
- // Swiping left (ltr) gesture
- tryToStartGesture(mGestureActions[ACTION_SWIPE_LEFT_INDEX],
- true /* alignedWithNavBar */, event);
+ // Swiping left (rtl) gesture
+ int index = isEdgeSwipeAlongNavBar(touchDownH, !mDragHPositive)
+ ? ACTION_SWIPE_LEFT_FROM_EDGE_INDEX : ACTION_SWIPE_LEFT_INDEX;
+ tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */,
+ event);
} else {
// Swiping right (ltr) gesture
- tryToStartGesture(mGestureActions[ACTION_SWIPE_RIGHT_INDEX],
- true /* alignedWithNavBar */, event);
+ int index = isEdgeSwipeAlongNavBar(touchDownH, mDragHPositive)
+ ? ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX : ACTION_SWIPE_RIGHT_INDEX;
+ tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */,
+ event);
}
}
}
@@ -333,6 +348,17 @@
return mCurrentAction != null || deadZoneConsumed;
}
+ private boolean isEdgeSwipeAlongNavBar(int touchDown, boolean dragPositiveDirection) {
+ // Detect edge swipe from side of 0 -> threshold
+ if (dragPositiveDirection) {
+ return touchDown < mEdgeSwipeThreshold;
+ }
+ // Detect edge swipe from side of size -> (size - threshold)
+ final int largeSide = isNavBarVertical()
+ ? mNavigationBarView.getHeight() : mNavigationBarView.getWidth();
+ return touchDown > largeSide - mEdgeSwipeThreshold;
+ }
+
private void handleDragHitTarget(int position, int touchDown) {
// Drag the hit target if gesture action requires it
if (mHitTarget != null && (mGestureVerticalDragsButton || mGestureHorizontalDragsButton)) {
@@ -480,7 +506,7 @@
event.transform(mTransformLocalMatrix);
// Calculate the bounding limits of drag to avoid dragging off nav bar's window
- if (action.requiresDragWithHitTarget() && mHitTarget != null) {
+ if (action.allowHitTargetToMoveOverDrag() && mHitTarget != null) {
final int[] buttonCenter = new int[2];
View button = mHitTarget.getCurrentView();
button.getLocationInWindow(buttonCenter);
@@ -505,7 +531,7 @@
// Handle direction of the hit target drag from the axis that started the gesture
// Also calculate the dampening factor, weaker dampening if there is an active action
- if (action.requiresDragWithHitTarget()) {
+ if (action.allowHitTargetToMoveOverDrag()) {
if (alignedWithNavBar) {
mGestureHorizontalDragsButton = true;
mGestureVerticalDragsButton = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java
new file mode 100644
index 0000000..40f2392
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 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.systemui.statusbar.phone;
+
+import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.recents.utilities.Utilities;
+
+/**
+ * QuickSwitch action to send to launcher
+ */
+public class QuickSwitchAction extends NavigationGestureAction {
+ private static final String TAG = "QuickSwitchAction";
+ private static final String QUICKSWITCH_ENABLED_SETTING = "QUICK_SWITCH";
+
+ protected final Rect mDragOverRect = new Rect();
+
+ public QuickSwitchAction(@NonNull NavigationBarView navigationBar,
+ @NonNull OverviewProxyService service) {
+ super(navigationBar, service);
+ }
+
+ @Override
+ public void setBarState(boolean changed, int navBarPos, boolean dragHorPositive,
+ boolean dragVerPositive) {
+ super.setBarState(changed, navBarPos, dragHorPositive, dragVerPositive);
+ if (changed && isActive()) {
+ // End quickscrub if the state changes mid-transition
+ endQuickGesture(false /* animate */);
+ }
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mNavigationBarView.isQuickScrubEnabled();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ mDragOverRect.set(top, left, right, bottom);
+ }
+
+ @Override
+ public boolean disableProxyEvents() {
+ return true;
+ }
+
+ @Override
+ protected void onGestureStart(MotionEvent event) {
+ // Temporarily enable launcher to allow quick switch instead of quick scrub
+ Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(),
+ QUICKSWITCH_ENABLED_SETTING, 1 /* enabled */);
+
+ startQuickGesture(event);
+ }
+
+ @Override
+ public void onGestureMove(int x, int y) {
+ int dragLength, offset;
+ if (isNavBarVertical()) {
+ dragLength = mDragOverRect.height();
+ offset = y - mDragOverRect.top;
+ } else {
+ offset = x - mDragOverRect.left;
+ dragLength = mDragOverRect.width();
+ }
+ if (!mDragHorizontalPositive || !mDragVerticalPositive) {
+ offset -= dragLength;
+ }
+ float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / dragLength, 0, 1);
+ try {
+ mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Switch Progress:" + scrubFraction);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send progress of quick switch.", e);
+ }
+ }
+
+ @Override
+ protected void onGestureEnd() {
+ endQuickGesture(true /* animate */);
+
+ // Disable launcher to use quick switch instead of quick scrub
+ Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(),
+ QUICKSWITCH_ENABLED_SETTING, 0 /* disabled */);
+ }
+
+ protected void startQuickGesture(MotionEvent event) {
+ // Disable slippery for quick scrub to not cancel outside the nav bar
+ mNavigationBarView.updateSlippery();
+
+ try {
+ mProxySender.getProxy().onQuickScrubStart();
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub Start");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send start of quick scrub.", e);
+ }
+ mProxySender.notifyQuickScrubStarted();
+ }
+
+ protected void endQuickGesture(boolean animate) {
+ try {
+ mProxySender.getProxy().onQuickScrubEnd();
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub End");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send end of quick scrub.", e);
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
index cdaa242..abb8c79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
@@ -61,6 +61,10 @@
@RunWithLooper
@SmallTest
public class QuickStepControllerTest extends SysuiTestCase {
+ private static final int NAVBAR_WIDTH = 1000;
+ private static final int NAVBAR_HEIGHT = 300;
+ private static final int EDGE_THRESHOLD = 100;
+
private QuickStepController mController;
private NavigationBarView mNavigationBarView;
private StatusBar mStatusBar;
@@ -73,6 +77,8 @@
MockitoAnnotations.initMocks(this);
final ButtonDispatcher backButton = mock(ButtonDispatcher.class);
mResources = mock(Resources.class);
+ doReturn(EDGE_THRESHOLD).when(mResources)
+ .getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold);
mProxyService = mock(OverviewProxyService.class);
mProxy = mock(IOverviewProxy.Stub.class);
@@ -109,7 +115,8 @@
public void testNoGesturesWhenSwipeUpDisabled() throws Exception {
doReturn(false).when(mProxyService).shouldShowSwipeUpUI();
mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
assertFalse(mController.onInterceptTouchEvent(ev));
@@ -124,7 +131,8 @@
// Add enabled gesture action
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
assertFalse(mController.onInterceptTouchEvent(ev));
verify(mNavigationBarView, times(1)).requestUnbufferedDispatch(ev);
@@ -140,7 +148,8 @@
// Add enabled gesture action
mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
// Set the gesture on deadzone
doReturn(null).when(mProxyService).getProxy();
@@ -165,7 +174,8 @@
@Test
public void testOnTouchIgnoredDownEventAfterOnIntercept() {
mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
assertFalse(touch(ev));
@@ -178,29 +188,45 @@
@Test
public void testGesturesCallCorrectAction() throws Exception {
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
+
NavigationGestureAction swipeUp = mockAction(true);
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
- mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+ NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+ NavigationGestureAction swipeRightFromEdge = mockAction(true);
+ mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+ swipeRightFromEdge);
// Swipe Up
assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
// Swipe Down
assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
// Swipe Left
- assertGestureTriggersAction(swipeLeft, 100, 1, 5, 1);
+ assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, 5, 1);
// Swipe Right
- assertGestureTriggersAction(swipeRight, 1, 1, 100, 5);
+ assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 5);
+ // Swipe Left from Edge
+ assertGestureTriggersAction(swipeLeftFromEdge, NAVBAR_WIDTH, 1, 5, 1);
+ // Swipe Right from Edge
+ assertGestureTriggersAction(swipeRightFromEdge, 0, 1, NAVBAR_WIDTH, 5);
}
@Test
public void testGesturesCallCorrectActionLandscape() throws Exception {
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
+
NavigationGestureAction swipeUp = mockAction(true);
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
- mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+ NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+ NavigationGestureAction swipeRightFromEdge = mockAction(true);
+ mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+ swipeRightFromEdge);
// In landscape
mController.setBarState(false /* isRTL */, NAV_BAR_RIGHT);
@@ -208,34 +234,50 @@
// Swipe Up
assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
// Swipe Down
- assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
+ assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
+ // Swipe Up from Edge
+ assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+ // Swipe Down from Edge
+ assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
public void testGesturesCallCorrectActionSeascape() throws Exception {
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
+
mController.setBarState(false /* isRTL */, NAV_BAR_LEFT);
NavigationGestureAction swipeUp = mockAction(true);
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
- mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+ NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+ NavigationGestureAction swipeRightFromEdge = mockAction(true);
+ mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+ swipeRightFromEdge);
// Swipe Up
- assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
+ assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1);
// Swipe Down
- assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
+ assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
+ // Swipe Up from Edge
+ assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+ // Swipe Down from Edge
+ assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
public void testGesturesCallCorrectActionRTL() throws Exception {
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
mController.setBarState(true /* isRTL */, NAV_BAR_BOTTOM);
// The swipe gestures below are for LTR, so RTL in portrait will be swapped
@@ -243,20 +285,29 @@
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
- mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+ NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+ NavigationGestureAction swipeRightFromEdge = mockAction(true);
+ mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+ swipeRightFromEdge);
// Swipe Up in RTL
assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
// Swipe Down in RTL
assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
// Swipe Left in RTL
- assertGestureTriggersAction(swipeRight, 100, 1, 5, 1);
+ assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, 5, 1);
// Swipe Right in RTL
- assertGestureTriggersAction(swipeLeft, 1, 1, 100, 5);
+ assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 0);
+ // Swipe Left from Edge
+ assertGestureTriggersAction(swipeRightFromEdge, NAVBAR_WIDTH, 1, 5, 1);
+ // Swipe Right from Edge
+ assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, NAVBAR_WIDTH, 5);
}
@Test
public void testGesturesCallCorrectActionLandscapeRTL() throws Exception {
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
mController.setBarState(true /* isRTL */, NAV_BAR_RIGHT);
// The swipe gestures below are for LTR, so RTL in landscape will be swapped
@@ -264,20 +315,29 @@
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
- mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+ NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+ NavigationGestureAction swipeRightFromEdge = mockAction(true);
+ mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+ swipeRightFromEdge);
// Swipe Up
- assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
+ assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1);
// Swipe Down
- assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
+ assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
+ // Swipe Up from Edge
+ assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+ // Swipe Down from Edge
+ assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
public void testGesturesCallCorrectActionSeascapeRTL() throws Exception {
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
mController.setBarState(true /* isRTL */, NAV_BAR_LEFT);
// The swipe gestures below are for LTR, so RTL in seascape will be swapped
@@ -285,16 +345,23 @@
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
- mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+ NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+ NavigationGestureAction swipeRightFromEdge = mockAction(true);
+ mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+ swipeRightFromEdge);
// Swipe Up
- assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
+ assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, 1);
// Swipe Down
- assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
+ assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
+ // Swipe Up from Edge
+ assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+ // Swipe Down from Edge
+ assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
@@ -305,7 +372,8 @@
// Add enabled gesture action
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
// Touch down to begin swipe
MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 1, 100);
@@ -326,7 +394,8 @@
NavigationGestureAction action = mockAction(true);
doReturn(false).when(action).canRunWhenNotificationsShowing();
mController.setGestureActions(action, null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
// Show the notifications
doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
@@ -351,7 +420,8 @@
public void testActionCannotPerform() throws Exception {
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
// Cannot perform action
doReturn(false).when(action).canPerformAction();
@@ -374,13 +444,17 @@
@Test
public void testQuickScrub() throws Exception {
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
QuickScrubAction action = spy(new QuickScrubAction(mNavigationBarView, mProxyService));
mController.setGestureActions(null /* swipeUpAction */, null /* swipeDownAction */,
- null /* swipeLeftAction */, action);
+ null /* swipeLeftAction */, action, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
+ int x = NAVBAR_WIDTH / 2;
int y = 20;
// Set the layout and other padding to make sure the scrub fraction is calculated correctly
- action.onLayout(true, 0, 0, 400, 100);
+ action.onLayout(true, 0, 0, NAVBAR_WIDTH, NAVBAR_HEIGHT);
doReturn(0).when(mNavigationBarView).getPaddingLeft();
doReturn(0).when(mNavigationBarView).getPaddingRight();
doReturn(0).when(mNavigationBarView).getPaddingStart();
@@ -393,14 +467,14 @@
doReturn(true).when(mNavigationBarView).isQuickScrubEnabled();
// Touch down
- MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 0, y);
+ MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, x, y);
assertFalse(touch(downEvent));
assertNull(mController.getCurrentAction());
verify(mProxy, times(1)).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
verify(mProxy, times(1)).onMotionEvent(downEvent);
// Move to start trigger action from gesture
- MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, 100, y);
+ MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, x + 100, y);
assertTrue(touch(moveEvent1));
assertEquals(action, mController.getCurrentAction());
verify(action, times(1)).onGestureStart(moveEvent1);
@@ -410,11 +484,13 @@
verify(mProxy, never()).onMotionEvent(moveEvent1);
// Move again for scrub
- MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, 200, y);
+ float fraction = 3f / 4;
+ x = (int) (NAVBAR_WIDTH * fraction);
+ MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, x, y);
assertTrue(touch(moveEvent2));
assertEquals(action, mController.getCurrentAction());
- verify(action, times(1)).onGestureMove(200, y);
- verify(mProxy, times(1)).onQuickScrubProgress(1f / 2);
+ verify(action, times(1)).onGestureMove(x, y);
+ verify(mProxy, times(1)).onQuickScrubProgress(fraction);
verify(mProxy, never()).onMotionEvent(moveEvent2);
// Action up
@@ -430,7 +506,8 @@
public void testQuickStep() throws Exception {
QuickStepAction action = new QuickStepAction(mNavigationBarView, mProxyService);
mController.setGestureActions(action, null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
// Notifications are up, should prevent quickstep
doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
@@ -466,7 +543,8 @@
public void testLongPressPreventDetection() throws Exception {
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
- null /* swipeLeftAction */, null /* swipeRightAction */);
+ null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+ null /* rightEdgeSwipe */);
// Start the drag up
assertFalse(touch(MotionEvent.ACTION_DOWN, 100, 1));
@@ -488,23 +566,21 @@
@Test
public void testHitTargetDragged() throws Exception {
- final int navbarWidth = 1000;
- final int navbarHeight = 1000;
ButtonDispatcher button = mock(ButtonDispatcher.class);
- FakeLocationView buttonView = spy(new FakeLocationView(mContext, navbarWidth / 2,
- navbarHeight / 2));
+ FakeLocationView buttonView = spy(new FakeLocationView(mContext, NAVBAR_WIDTH / 2,
+ NAVBAR_HEIGHT / 2));
doReturn(buttonView).when(button).getCurrentView();
NavigationGestureAction action = mockAction(true);
- mController.setGestureActions(action, action, action, action);
+ mController.setGestureActions(action, action, action, action, action, action);
// Setup getting the hit target
doReturn(HIT_TARGET_HOME).when(action).requiresTouchDownHitTarget();
- doReturn(true).when(action).requiresDragWithHitTarget();
+ doReturn(true).when(action).allowHitTargetToMoveOverDrag();
doReturn(HIT_TARGET_HOME).when(mNavigationBarView).getDownHitTarget();
doReturn(button).when(mNavigationBarView).getHomeButton();
- doReturn(navbarWidth).when(mNavigationBarView).getWidth();
- doReturn(navbarHeight).when(mNavigationBarView).getHeight();
+ doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+ doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
// Portrait
assertGestureDragsHitTargetAllDirections(buttonView, false /* isRTL */, NAV_BAR_BOTTOM);
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 9cfd39c..65cd329 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -55,7 +55,12 @@
// add other system settings here...
sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
- sGlobalSettingToTypeMap.put(Settings.Global.ANGLE_ENABLED_APP, String.class);
+ sGlobalSettingToTypeMap.put(
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class);
+ sGlobalSettingToTypeMap.put(
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
+ sGlobalSettingToTypeMap.put(
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 65d3245..c44f306 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -81,7 +81,8 @@
}
@Override
- public void setGlobalPrivateDns(ComponentName who, int mode, String privateDnsHost) {
+ public int setGlobalPrivateDns(ComponentName who, int mode, String privateDnsHost) {
+ return DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bca3b1f..041d5d8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -59,6 +59,8 @@
import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_UNKNOWN;
+import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
+import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_SUCCESS;
import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
@@ -13280,32 +13282,40 @@
}
@Override
- public void setGlobalPrivateDns(@NonNull ComponentName who, int mode, String privateDnsHost) {
+ public int setGlobalPrivateDns(@NonNull ComponentName who, int mode, String privateDnsHost) {
if (!mHasFeature) {
- return;
+ return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
}
Preconditions.checkNotNull(who, "ComponentName is null");
enforceDeviceOwner(who);
+ final int returnCode;
+
switch (mode) {
case PRIVATE_DNS_MODE_OPPORTUNISTIC:
if (!TextUtils.isEmpty(privateDnsHost)) {
- throw new IllegalArgumentException("A DNS host should not be provided when " +
- "setting opportunistic mode.");
+ throw new IllegalArgumentException(
+ "Host provided for opportunistic mode, but is not needed.");
}
putPrivateDnsSettings(ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC, null);
- break;
+ return PRIVATE_DNS_SET_SUCCESS;
case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
- if (!NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+ if (TextUtils.isEmpty(privateDnsHost)
+ || !NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
throw new IllegalArgumentException(
- String.format("Provided hostname is not valid: %s", privateDnsHost));
+ String.format("Provided hostname %s is not valid", privateDnsHost));
}
- putPrivateDnsSettings(ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
+
+ // Connectivity check will have been performed in the DevicePolicyManager before
+ // the call here.
+ putPrivateDnsSettings(
+ ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
privateDnsHost);
- break;
+ return PRIVATE_DNS_SET_SUCCESS;
default:
- throw new IllegalArgumentException(String.format("Unsupported mode: %d", mode));
+ throw new IllegalArgumentException(
+ String.format("Provided mode, %d, is not a valid mode.", mode));
}
}