summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/Layout.java9
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java5
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java4
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp2
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/tests/coretests/src/android/text/LayoutTest.java3
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java118
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java111
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java132
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java411
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java17
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerDebugConfig.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java148
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java2
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java8
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java116
-rw-r--r--services/core/java/com/android/server/policy/TEST_MAPPING3
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java12
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackController.java15
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java2
-rw-r--r--telecomm/java/android/telecom/ConferenceParticipant.java103
-rw-r--r--telecomm/java/android/telecom/Connection.java22
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java3
-rw-r--r--telecomm/java/android/telecom/ParcelableConnection.java17
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java42
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java7
35 files changed, 905 insertions, 512 deletions
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index bf0ef9465fcd..2c2c2953ed51 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1122,6 +1122,9 @@ public abstract class Layout {
if (limit > lineEnd) {
limit = lineEnd;
}
+ if (limit == start) {
+ continue;
+ }
level[limit - lineStart - 1] =
(byte) ((runs[i + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK);
}
@@ -1220,8 +1223,8 @@ public abstract class Layout {
}
/**
- * Computes in linear time the results of calling
- * #getHorizontal for all offsets on a line.
+ * Computes in linear time the results of calling #getHorizontal for all offsets on a line.
+ *
* @param line The line giving the offsets we compute information for
* @param clamped Whether to clamp the results to the width of the layout
* @param primary Whether the results should be the primary or the secondary horizontal
@@ -1257,7 +1260,7 @@ public abstract class Layout {
TextLine.recycle(tl);
if (clamped) {
- for (int offset = 0; offset <= wid.length; ++offset) {
+ for (int offset = 0; offset < wid.length; ++offset) {
if (wid[offset] > mWidth) {
wid[offset] = mWidth;
}
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 8b70bd61785a..4daddfbfb204 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -177,6 +177,11 @@ public final class SystemUiDeviceConfigFlags {
"assist_handles_suppress_on_apps";
/**
+ * (bool) Whether to show handles when taught.
+ */
+ public static final String ASSIST_HANDLES_SHOW_WHEN_TAUGHT = "assist_handles_show_when_taught";
+
+ /**
* (bool) Whether to use the new BrightLineFalsingManager.
*/
public static final String BRIGHTLINE_FALSING_MANAGER_ENABLED =
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index 82593b5e2f0a..1fdb1f30125f 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -458,7 +458,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
}
private String getFuncTypeAsString() {
- if (isRecycled()) throw new IllegalStateException();
+ if (isRecycled()) return "<recycled>";
if (isConstSupplier()) return "supplier";
String name = LambdaType.toString(getFlags(MASK_EXPOSED_AS));
if (name.endsWith("Consumer")) return "consumer";
@@ -466,7 +466,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
if (name.endsWith("Predicate")) return "predicate";
if (name.endsWith("Supplier")) return "supplier";
if (name.endsWith("Runnable")) return "runnable";
- throw new IllegalStateException("Don't know the string representation of " + name);
+ return name;
}
/**
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4783a257755f..82c27f02ba87 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1160,6 +1160,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi
/*
* Grant the following capabilities to the Bluetooth user:
* - CAP_WAKE_ALARM
+ * - CAP_NET_ADMIN
* - CAP_NET_RAW
* - CAP_NET_BIND_SERVICE (for DHCP client functionality)
* - CAP_SYS_NICE (for setting RT priority for audio-related threads)
@@ -1167,6 +1168,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi
if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
capabilities |= (1LL << CAP_WAKE_ALARM);
+ capabilities |= (1LL << CAP_NET_ADMIN);
capabilities |= (1LL << CAP_NET_RAW);
capabilities |= (1LL << CAP_NET_BIND_SERVICE);
capabilities |= (1LL << CAP_SYS_NICE);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6aff8b8f1d5c..fef4dcd3b9f1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2544,7 +2544,7 @@
<!-- @SystemApi @TestApi @hide Allows an application to modify config settings.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_DEVICE_CONFIG"
- android:protectionLevel="signature|configurator"/>
+ android:protectionLevel="signature|verifier|configurator"/>
<!-- @SystemApi @hide Allows an application to read config settings.
<p>Not for use by third-party applications. -->
diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java
index 990161a88c22..93a6b15f744c 100644
--- a/core/tests/coretests/src/android/text/LayoutTest.java
+++ b/core/tests/coretests/src/android/text/LayoutTest.java
@@ -743,6 +743,9 @@ public class LayoutTest {
assertPrimaryIsTrailingPrevious(
RTL + LRI + RTL + LTR + PDI + RTL,
new boolean[]{false, false, true, false, false, false, false});
+ assertPrimaryIsTrailingPrevious(
+ "",
+ new boolean[]{false});
}
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4b4912cb1e8a..17274f418a1e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -644,7 +644,8 @@
<provider
android:name="com.android.keyguard.clock.ClockOptionsProvider"
android:authorities="com.android.keyguard.clock"
- android:exported="true"
+ android:enabled="false"
+ android:exported="false"
android:grantUriPermissions="true">
</provider>
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 0af333e96edf..f9ddeaef3e86 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -67,6 +67,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false;
private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false;
private static final boolean DEFAULT_SUPPRESS_ON_APPS = true;
+ private static final boolean DEFAULT_SHOW_WHEN_TAUGHT = false;
private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
@@ -309,7 +310,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
return;
}
- if (mIsDozing || mIsNavBarHidden || mOnLockscreen) {
+ if (mIsDozing || mIsNavBarHidden || mOnLockscreen || !getShowWhenTaught()) {
mAssistHandleCallbacks.hide();
} else if (justUnlocked) {
long currentEpochDay = LocalDate.now().toEpochDay();
@@ -429,6 +430,12 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
DEFAULT_SUPPRESS_ON_APPS);
}
+ private boolean getShowWhenTaught() {
+ return mPhenotypeHelper.getBoolean(
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT,
+ DEFAULT_SHOW_WHEN_TAUGHT);
+ }
+
@Override
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "Current AssistHandleReminderExpBehavior State:");
@@ -480,5 +487,9 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS
+ "="
+ getSuppressOnApps());
+ pw.println(prefix + " "
+ + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT
+ + "="
+ + getShowWhenTaught());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 15218896f089..3cc8ec9afbb2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -96,7 +96,7 @@ public class FalsingManagerProxy implements FalsingManager {
mInternalFalsingManager = new FalsingManagerImpl(context);
} else {
mInternalFalsingManager = new BrightLineFalsingManager(
- new FalsingDataProvider(context),
+ new FalsingDataProvider(context.getResources().getDisplayMetrics()),
Dependency.get(AsyncSensorManager.class)
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java
index 4975e63f7a0a..8b11ceb34ea0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java
@@ -16,7 +16,6 @@
package com.android.systemui.classifier.brightline;
-import android.content.Context;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
@@ -51,8 +50,7 @@ public class FalsingDataProvider {
private MotionEvent mFirstRecentMotionEvent;
private MotionEvent mLastMotionEvent;
- public FalsingDataProvider(Context context) {
- DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
+ public FalsingDataProvider(DisplayMetrics displayMetrics) {
mXdpi = displayMetrics.xdpi;
mYdpi = displayMetrics.ydpi;
mWidthPixels = displayMetrics.widthPixels;
@@ -145,12 +143,20 @@ public class FalsingDataProvider {
boolean isHorizontal() {
recalculateData();
+ if (mRecentMotionEvents.isEmpty()) {
+ return false;
+ }
+
return Math.abs(mFirstRecentMotionEvent.getX() - mLastMotionEvent.getX()) > Math
.abs(mFirstRecentMotionEvent.getY() - mLastMotionEvent.getY());
}
boolean isRight() {
recalculateData();
+ if (mRecentMotionEvents.isEmpty()) {
+ return false;
+ }
+
return mLastMotionEvent.getX() > mFirstRecentMotionEvent.getX();
}
@@ -160,6 +166,10 @@ public class FalsingDataProvider {
boolean isUp() {
recalculateData();
+ if (mRecentMotionEvents.isEmpty()) {
+ return false;
+ }
+
return mLastMotionEvent.getY() < mFirstRecentMotionEvent.getY();
}
@@ -168,8 +178,13 @@ public class FalsingDataProvider {
return;
}
- mFirstRecentMotionEvent = mRecentMotionEvents.get(0);
- mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
+ if (mRecentMotionEvents.isEmpty()) {
+ mFirstRecentMotionEvent = null;
+ mLastMotionEvent = null;
+ } else {
+ mFirstRecentMotionEvent = mRecentMotionEvents.get(0);
+ mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
+ }
calculateAngleInternal();
@@ -245,5 +260,7 @@ public class FalsingDataProvider {
}
mRecentMotionEvents.clear();
+
+ mDirty = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
new file mode 100644
index 000000000000..d011e486d2e0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 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.classifier.brightline;
+
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.After;
+import org.junit.Before;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ClassifierTest extends SysuiTestCase {
+
+ private FalsingDataProvider mDataProvider;
+ private List<MotionEvent> mMotionEvents = new ArrayList<>();
+ private float mOffsetX = 0;
+ private float mOffsetY = 0;
+
+ @Before
+ public void setup() {
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ displayMetrics.xdpi = 100;
+ displayMetrics.ydpi = 100;
+ displayMetrics.widthPixels = 1000;
+ displayMetrics.heightPixels = 1000;
+ mDataProvider = new FalsingDataProvider(displayMetrics);
+ }
+
+ @After
+ public void tearDown() {
+ resetDataProvider();
+ }
+
+ FalsingDataProvider getDataProvider() {
+ return mDataProvider;
+ }
+
+ void setOffsetX(float offsetX) {
+ mOffsetX = offsetX;
+ }
+
+ void setOffsetY(float offsetY) {
+ mOffsetY = offsetY;
+ }
+
+ void resetDataProvider() {
+ for (MotionEvent motionEvent : mMotionEvents) {
+ motionEvent.recycle();
+ }
+
+ mMotionEvents.clear();
+
+ mDataProvider.onSessionEnd();
+ }
+
+ MotionEvent appendDownEvent(float x, float y) {
+ return appendMotionEvent(MotionEvent.ACTION_DOWN, x, y);
+ }
+
+ MotionEvent appendDownEvent(float x, float y, long eventTime) {
+ return appendMotionEvent(MotionEvent.ACTION_DOWN, x, y, eventTime);
+ }
+
+ MotionEvent appendMoveEvent(float x, float y) {
+ return appendMotionEvent(MotionEvent.ACTION_MOVE, x, y);
+ }
+
+ MotionEvent appendMoveEvent(float x, float y, long eventTime) {
+ return appendMotionEvent(MotionEvent.ACTION_MOVE, x, y, eventTime);
+ }
+
+
+ MotionEvent appendUpEvent(float x, float y) {
+ return appendMotionEvent(MotionEvent.ACTION_UP, x, y);
+ }
+
+ MotionEvent appendUpEvent(float x, float y, long eventTime) {
+ return appendMotionEvent(MotionEvent.ACTION_UP, x, y, eventTime);
+ }
+
+ private MotionEvent appendMotionEvent(int actionType, float x, float y) {
+
+ long eventTime = mMotionEvents.isEmpty() ? 1 : mMotionEvents.get(
+ mMotionEvents.size() - 1).getEventTime() + 1;
+ return appendMotionEvent(actionType, x, y, eventTime);
+ }
+
+ private MotionEvent appendMotionEvent(int actionType, float x, float y, long eventTime) {
+ x += mOffsetX;
+ y += mOffsetY;
+
+ MotionEvent motionEvent = MotionEvent.obtain(1, eventTime, actionType, x, y,
+ 0);
+ mMotionEvents.add(motionEvent);
+
+ mDataProvider.onMotionEvent(motionEvent);
+
+ return motionEvent;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
index ade5f36d659e..b45d3f2855ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
@@ -28,8 +28,7 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,7 +38,7 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class DiagonalClassifierTest extends SysuiTestCase {
+public class DiagonalClassifierTest extends ClassifierTest {
// Next variable is not actually five, but is very close. 5 degrees is currently the value
// used in the diagonal classifier, so we want slightly less than that to deal with
@@ -57,10 +56,16 @@ public class DiagonalClassifierTest extends SysuiTestCase {
@Before
public void setup() {
+ super.setup();
MockitoAnnotations.initMocks(this);
mClassifier = new DiagonalClassifier(mDataProvider);
}
+ @After
+ public void tearDown() {
+ super.tearDown();
+ }
+
@Test
public void testPass_UnknownAngle() {
when(mDataProvider.getAngle()).thenReturn(Float.MAX_VALUE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
index 3d0471bee728..805bb91591e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
@@ -18,48 +18,37 @@ package com.android.systemui.classifier.brightline;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class DistanceClassifierTest extends SysuiTestCase {
+public class DistanceClassifierTest extends ClassifierTest {
- @Mock
private FalsingDataProvider mDataProvider;
private FalsingClassifier mClassifier;
- private List<MotionEvent> mMotionEvents = new ArrayList<>();
-
- private static final float DPI = 100;
- private static final int SCREEN_SIZE = (int) (DPI * 10);
@Before
public void setup() {
- MockitoAnnotations.initMocks(this);
- when(mDataProvider.getHeightPixels()).thenReturn(SCREEN_SIZE);
- when(mDataProvider.getWidthPixels()).thenReturn(SCREEN_SIZE);
- when(mDataProvider.getXdpi()).thenReturn(DPI);
- when(mDataProvider.getYdpi()).thenReturn(DPI);
+ super.setup();
+ mDataProvider = getDataProvider();
mClassifier = new DistanceClassifier(mDataProvider);
}
+ @After
+ public void tearDown() {
+ super.tearDown();
+ }
+
@Test
public void testPass_noPointer() {
assertThat(mClassifier.isFalseTouch(), is(true));
@@ -67,104 +56,54 @@ public class DistanceClassifierTest extends SysuiTestCase {
@Test
public void testPass_fling() {
- MotionEvent motionEventA = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 1, 1, 0);
- MotionEvent motionEventB = MotionEvent.obtain(1, 2, MotionEvent.ACTION_MOVE, 1, 2, 0);
- MotionEvent motionEventC = MotionEvent.obtain(1, 3, MotionEvent.ACTION_UP, 1, 40, 0);
- appendMotionEvent(motionEventA);
+ mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
- appendMotionEvent(motionEventB);
+ mClassifier.onTouchEvent(appendMoveEvent(1, 2));
assertThat(mClassifier.isFalseTouch(), is(true));
- appendMotionEvent(motionEventC);
+ mClassifier.onTouchEvent(appendUpEvent(1, 40));
assertThat(mClassifier.isFalseTouch(), is(false));
-
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
}
@Test
public void testFail_flingShort() {
- MotionEvent motionEventA = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 1, 1, 0);
- MotionEvent motionEventB = MotionEvent.obtain(1, 2, MotionEvent.ACTION_MOVE, 1, 2, 0);
- MotionEvent motionEventC = MotionEvent.obtain(1, 3, MotionEvent.ACTION_UP, 1, 10, 0);
-
- appendMotionEvent(motionEventA);
+ mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
- appendMotionEvent(motionEventB);
+ mClassifier.onTouchEvent(appendMoveEvent(1, 2));
assertThat(mClassifier.isFalseTouch(), is(true));
- appendMotionEvent(motionEventC);
+ mClassifier.onTouchEvent(appendUpEvent(1, 10));
assertThat(mClassifier.isFalseTouch(), is(true));
-
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
}
@Test
public void testFail_flingSlowly() {
// These events, in testing, result in a fling that falls just short of the threshold.
- MotionEvent motionEventA = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 1, 1, 0);
- MotionEvent motionEventB = MotionEvent.obtain(1, 2, MotionEvent.ACTION_MOVE, 1, 15, 0);
- MotionEvent motionEventC = MotionEvent.obtain(1, 3, MotionEvent.ACTION_MOVE, 1, 16, 0);
- MotionEvent motionEventD = MotionEvent.obtain(1, 300, MotionEvent.ACTION_MOVE, 1, 17, 0);
- MotionEvent motionEventE = MotionEvent.obtain(1, 301, MotionEvent.ACTION_MOVE, 1, 18, 0);
- MotionEvent motionEventF = MotionEvent.obtain(1, 500, MotionEvent.ACTION_UP, 1, 19, 0);
-
- appendMotionEvent(motionEventA);
- assertThat(mClassifier.isFalseTouch(), is(true));
- appendMotionEvent(motionEventB);
+ mClassifier.onTouchEvent(appendDownEvent(1, 1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
- appendMotionEvent(motionEventC);
- appendMotionEvent(motionEventD);
- appendMotionEvent(motionEventE);
- appendMotionEvent(motionEventF);
+ mClassifier.onTouchEvent(appendMoveEvent(1, 15, 2));
assertThat(mClassifier.isFalseTouch(), is(true));
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
- motionEventD.recycle();
- motionEventE.recycle();
- motionEventF.recycle();
+ mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3));
+ mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300));
+ mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301));
+ mClassifier.onTouchEvent(appendUpEvent(1, 19, 501));
+ assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void testPass_swipe() {
- MotionEvent motionEventA = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 1, 1, 0);
- MotionEvent motionEventB = MotionEvent.obtain(1, 3, MotionEvent.ACTION_MOVE, 1, DPI * 3, 0);
- MotionEvent motionEventC = MotionEvent.obtain(1, 1000, MotionEvent.ACTION_UP, 1, DPI * 3,
- 0);
- appendMotionEvent(motionEventA);
+ mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
-
- appendMotionEvent(motionEventB);
- appendMotionEvent(motionEventC);
+ mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3));
+ mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300));
assertThat(mClassifier.isFalseTouch(), is(false));
-
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
- }
-
- private void appendMotionEvent(MotionEvent motionEvent) {
- if (mMotionEvents.isEmpty()) {
- when(mDataProvider.getFirstRecentMotionEvent()).thenReturn(motionEvent);
- }
-
- mMotionEvents.add(motionEvent);
- when(mDataProvider.getRecentMotionEvents()).thenReturn(mMotionEvents);
-
- when(mDataProvider.getLastMotionEvent()).thenReturn(motionEvent);
-
- mClassifier.onTouchEvent(motionEvent);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
index 1da42061c234..748c1377f7a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
@@ -22,12 +22,12 @@ import static org.junit.Assert.assertThat;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.DisplayMetrics;
import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,24 +37,32 @@ import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class FalsingDataProviderTest extends SysuiTestCase {
+public class FalsingDataProviderTest extends ClassifierTest {
private FalsingDataProvider mDataProvider;
@Before
public void setup() {
- mDataProvider = new FalsingDataProvider(getContext());
+ super.setup();
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ displayMetrics.xdpi = 100;
+ displayMetrics.ydpi = 100;
+ displayMetrics.widthPixels = 1000;
+ displayMetrics.heightPixels = 1000;
+ mDataProvider = new FalsingDataProvider(displayMetrics);
+ }
+
+ @After
+ public void tearDown() {
+ super.tearDown();
+ mDataProvider.onSessionEnd();
}
@Test
public void test_trackMotionEvents() {
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 2, 9);
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 4, 7);
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_UP, 3, 6, 5);
-
- mDataProvider.onMotionEvent(motionEventA);
- mDataProvider.onMotionEvent(motionEventB);
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendDownEvent(2, 9));
+ mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
+ mDataProvider.onMotionEvent(appendUpEvent(6, 5));
List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
assertThat(motionEventList.size(), is(3));
@@ -70,20 +78,12 @@ public class FalsingDataProviderTest extends SysuiTestCase {
assertThat(motionEventList.get(0).getY(), is(9f));
assertThat(motionEventList.get(1).getY(), is(7f));
assertThat(motionEventList.get(2).getY(), is(5f));
-
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
}
@Test
public void test_trackRecentMotionEvents() {
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 2, 9);
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 800, 4, 7);
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_UP, 1200, 6, 5);
-
- mDataProvider.onMotionEvent(motionEventA);
- mDataProvider.onMotionEvent(motionEventB);
+ mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1));
+ mDataProvider.onMotionEvent(appendMoveEvent(4, 7, 800));
List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
assertThat(motionEventList.size(), is(2));
@@ -96,7 +96,7 @@ public class FalsingDataProviderTest extends SysuiTestCase {
assertThat(motionEventList.get(0).getY(), is(9f));
assertThat(motionEventList.get(1).getY(), is(7f));
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendUpEvent(6, 5, 1200));
// Still two events, but event a is gone.
assertThat(motionEventList.size(), is(2));
@@ -115,18 +115,14 @@ public class FalsingDataProviderTest extends SysuiTestCase {
assertThat(firstRealMotionEvent.getEventTime(), is(1L));
assertThat(firstRealMotionEvent.getX(), is(2f));
assertThat(firstRealMotionEvent.getY(), is(9f));
-
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
}
@Test
public void test_unpackMotionEvents() {
// Batching only works for motion events of the same type.
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_MOVE, 1, 2, 9);
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 4, 7);
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_MOVE, 3, 6, 5);
+ MotionEvent motionEventA = appendMoveEvent(2, 9);
+ MotionEvent motionEventB = appendMoveEvent(4, 7);
+ MotionEvent motionEventC = appendMoveEvent(6, 5);
motionEventA.addBatch(motionEventB);
motionEventA.addBatch(motionEventC);
// Note that calling addBatch changes properties on the original event, not just it's
@@ -148,114 +144,86 @@ public class FalsingDataProviderTest extends SysuiTestCase {
assertThat(motionEventList.get(0).getY(), is(9f));
assertThat(motionEventList.get(1).getY(), is(7f));
assertThat(motionEventList.get(2).getY(), is(5f));
-
- motionEventA.recycle();
- motionEventB.recycle();
- motionEventC.recycle();
}
@Test
public void test_getAngle() {
- MotionEvent motionEventOrigin = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 0, 0);
+ MotionEvent motionEventOrigin = appendDownEvent(0, 0);
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 1, 1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventA);
+ mDataProvider.onMotionEvent(appendMoveEvent(1, 1));
assertThat((double) mDataProvider.getAngle(), closeTo(Math.PI / 4, .001));
- motionEventA.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, -1, -1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventB);
+ mDataProvider.onMotionEvent(appendMoveEvent(-1, -1));
assertThat((double) mDataProvider.getAngle(), closeTo(5 * Math.PI / 4, .001));
- motionEventB.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 2, 0);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendMoveEvent(2, 0));
assertThat((double) mDataProvider.getAngle(), closeTo(0, .001));
- motionEventC.recycle();
mDataProvider.onSessionEnd();
}
@Test
public void test_isHorizontal() {
- MotionEvent motionEventOrigin = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 0, 0);
+ MotionEvent motionEventOrigin = appendDownEvent(0, 0);
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 1, 1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventA);
+ mDataProvider.onMotionEvent(appendMoveEvent(1, 1));
assertThat(mDataProvider.isHorizontal(), is(false));
- motionEventA.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 2, 1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventB);
+ mDataProvider.onMotionEvent(appendMoveEvent(2, 1));
assertThat(mDataProvider.isHorizontal(), is(true));
- motionEventB.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, -3, -1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendMoveEvent(-3, -1));
assertThat(mDataProvider.isHorizontal(), is(true));
- motionEventC.recycle();
mDataProvider.onSessionEnd();
}
@Test
public void test_isVertical() {
- MotionEvent motionEventOrigin = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 0, 0);
+ MotionEvent motionEventOrigin = appendDownEvent(0, 0);
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 1, 0);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventA);
+ mDataProvider.onMotionEvent(appendMoveEvent(1, 0));
assertThat(mDataProvider.isVertical(), is(false));
- motionEventA.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 0, 1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventB);
+ mDataProvider.onMotionEvent(appendMoveEvent(0, 1));
assertThat(mDataProvider.isVertical(), is(true));
- motionEventB.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, -3, -10);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendMoveEvent(-3, -10));
assertThat(mDataProvider.isVertical(), is(true));
- motionEventC.recycle();
mDataProvider.onSessionEnd();
}
@Test
public void test_isRight() {
- MotionEvent motionEventOrigin = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 0, 0);
+ MotionEvent motionEventOrigin = appendDownEvent(0, 0);
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 1, 1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventA);
+ mDataProvider.onMotionEvent(appendMoveEvent(1, 1));
assertThat(mDataProvider.isRight(), is(true));
- motionEventA.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 0, 1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventB);
+ mDataProvider.onMotionEvent(appendMoveEvent(0, 1));
assertThat(mDataProvider.isRight(), is(false));
- motionEventB.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, -3, -10);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendMoveEvent(-3, -10));
assertThat(mDataProvider.isRight(), is(false));
- motionEventC.recycle();
mDataProvider.onSessionEnd();
}
@@ -263,31 +231,21 @@ public class FalsingDataProviderTest extends SysuiTestCase {
public void test_isUp() {
// Remember that our y axis is flipped.
- MotionEvent motionEventOrigin = obtainMotionEvent(MotionEvent.ACTION_DOWN, 1, 0, 0);
+ MotionEvent motionEventOrigin = appendDownEvent(0, 0);
- MotionEvent motionEventA = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 1, -1);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventA);
+ mDataProvider.onMotionEvent(appendMoveEvent(1, -1));
assertThat(mDataProvider.isUp(), is(true));
- motionEventA.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventB = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, 0, 0);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventB);
+ mDataProvider.onMotionEvent(appendMoveEvent(0, 0));
assertThat(mDataProvider.isUp(), is(false));
- motionEventB.recycle();
mDataProvider.onSessionEnd();
- MotionEvent motionEventC = obtainMotionEvent(MotionEvent.ACTION_MOVE, 2, -3, 10);
mDataProvider.onMotionEvent(motionEventOrigin);
- mDataProvider.onMotionEvent(motionEventC);
+ mDataProvider.onMotionEvent(appendMoveEvent(-3, 10));
assertThat(mDataProvider.isUp(), is(false));
- motionEventC.recycle();
mDataProvider.onSessionEnd();
}
-
- private MotionEvent obtainMotionEvent(int action, long eventTimeMs, float x, float y) {
- return MotionEvent.obtain(1, eventTimeMs, action, x, y, 0);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
index cba9ee38b306..341b74b33784 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
@@ -25,25 +25,27 @@ import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class PointerCountClassifierTest extends SysuiTestCase {
+public class PointerCountClassifierTest extends ClassifierTest {
- @Mock
- private FalsingDataProvider mDataProvider;
private FalsingClassifier mClassifier;
@Before
public void setup() {
- mClassifier = new PointerCountClassifier(mDataProvider);
+ super.setup();
+ mClassifier = new PointerCountClassifier(getDataProvider());
+ }
+
+ @After
+ public void tearDown() {
+ super.tearDown();
}
@Test
@@ -53,9 +55,7 @@ public class PointerCountClassifierTest extends SysuiTestCase {
@Test
public void testPass_singlePointer() {
- MotionEvent motionEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 1, 1, 0);
- mClassifier.onTouchEvent(motionEvent);
- motionEvent.recycle();
+ mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(false));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
index 2ed792542efd..a6cabbf49458 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
@@ -31,8 +31,7 @@ import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,7 +44,7 @@ import java.lang.reflect.Field;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class ProximityClassifierTest extends SysuiTestCase {
+public class ProximityClassifierTest extends ClassifierTest {
private static final long NS_PER_MS = 1000000;
@@ -57,12 +56,18 @@ public class ProximityClassifierTest extends SysuiTestCase {
@Before
public void setup() {
+ super.setup();
MockitoAnnotations.initMocks(this);
when(mDataProvider.getInteractionType()).thenReturn(GENERIC);
when(mDistanceClassifier.isLongSwipe()).thenReturn(false);
mClassifier = new ProximityClassifier(mDistanceClassifier, mDataProvider);
}
+ @After
+ public void tearDown() {
+ super.tearDown();
+ }
+
@Test
public void testPass_uncovered() {
touchDown();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java
index 4bb3c15818c1..0355dc362593 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java
@@ -34,8 +34,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,15 +43,15 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class TypeClassifierTest extends SysuiTestCase {
+public class TypeClassifierTest extends ClassifierTest {
@Mock
private FalsingDataProvider mDataProvider;
-
private FalsingClassifier mClassifier;
@Before
public void setup() {
+ super.setup();
MockitoAnnotations.initMocks(this);
mClassifier = new TypeClassifier(mDataProvider);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
index 9d09a7e6f01f..25a1a75b0cbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
@@ -18,128 +18,93 @@ package com.android.systemui.classifier.brightline;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Random;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class ZigZagClassifierTest extends SysuiTestCase {
-
- private static final long NS_PER_MS = 1000000;
+public class ZigZagClassifierTest extends ClassifierTest {
- @Mock
- private FalsingDataProvider mDataProvider;
private FalsingClassifier mClassifier;
- private List<MotionEvent> mMotionEvents = new ArrayList<>();
- private float mOffsetX = 0;
- private float mOffsetY = 0;
- private float mDx;
- private float mDy;
@Before
public void setup() {
- MockitoAnnotations.initMocks(this);
- when(mDataProvider.getXdpi()).thenReturn(100f);
- when(mDataProvider.getYdpi()).thenReturn(100f);
- when(mDataProvider.getRecentMotionEvents()).thenReturn(mMotionEvents);
- mClassifier = new ZigZagClassifier(mDataProvider);
-
-
- // Calculate the response to these calls on the fly, otherwise Mockito gets bogged down
- // everytime we call appendMotionEvent.
- when(mDataProvider.getFirstRecentMotionEvent()).thenAnswer(
- (Answer<MotionEvent>) invocation -> mMotionEvents.get(0));
- when(mDataProvider.getLastMotionEvent()).thenAnswer(
- (Answer<MotionEvent>) invocation -> mMotionEvents.get(mMotionEvents.size() - 1));
- when(mDataProvider.isHorizontal()).thenAnswer(
- (Answer<Boolean>) invocation -> Math.abs(mDy) < Math.abs(mDx));
- when(mDataProvider.isVertical()).thenAnswer(
- (Answer<Boolean>) invocation -> Math.abs(mDy) > Math.abs(mDx));
- when(mDataProvider.isRight()).thenAnswer((Answer<Boolean>) invocation -> mDx > 0);
- when(mDataProvider.isUp()).thenAnswer((Answer<Boolean>) invocation -> mDy < 0);
+ super.setup();
+ mClassifier = new ZigZagClassifier(getDataProvider());
}
@After
public void tearDown() {
- clearMotionEvents();
+ super.tearDown();
}
@Test
public void testPass_fewTouchesVertical() {
assertThat(mClassifier.isFalseTouch(), is(false));
- appendMotionEvent(0, 0);
+ appendMoveEvent(0, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
- appendMotionEvent(0, 100);
+ appendMoveEvent(0, 100);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@Test
public void testPass_vertical() {
- appendMotionEvent(0, 0);
- appendMotionEvent(0, 100);
- appendMotionEvent(0, 200);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(0, 100);
+ appendMoveEvent(0, 200);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@Test
public void testPass_fewTouchesHorizontal() {
assertThat(mClassifier.isFalseTouch(), is(false));
- appendMotionEvent(0, 0);
+ appendMoveEvent(0, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
- appendMotionEvent(100, 0);
+ appendMoveEvent(100, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@Test
public void testPass_horizontal() {
- appendMotionEvent(0, 0);
- appendMotionEvent(100, 0);
- appendMotionEvent(200, 0);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, 0);
+ appendMoveEvent(200, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@Test
public void testFail_minimumTouchesVertical() {
- appendMotionEvent(0, 0);
- appendMotionEvent(0, 100);
- appendMotionEvent(0, 1);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(0, 100);
+ appendMoveEvent(0, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void testFail_minimumTouchesHorizontal() {
- appendMotionEvent(0, 0);
- appendMotionEvent(100, 0);
- appendMotionEvent(1, 0);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, 0);
+ appendMoveEvent(1, 0);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void testPass_fortyFiveDegreesStraight() {
- appendMotionEvent(0, 0);
- appendMotionEvent(10, 10);
- appendMotionEvent(20, 20);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(10, 10);
+ appendMoveEvent(20, 20);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@@ -147,9 +112,9 @@ public class ZigZagClassifierTest extends SysuiTestCase {
public void testPass_horizontalZigZagVerticalStraight() {
// This test looks just like testFail_horizontalZigZagVerticalStraight but with
// a longer y range, making it look straighter.
- appendMotionEvent(0, 0);
- appendMotionEvent(5, 100);
- appendMotionEvent(-5, 200);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(5, 100);
+ appendMoveEvent(-5, 200);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@@ -157,9 +122,9 @@ public class ZigZagClassifierTest extends SysuiTestCase {
public void testPass_horizontalStraightVerticalZigZag() {
// This test looks just like testFail_horizontalStraightVerticalZigZag but with
// a longer x range, making it look straighter.
- appendMotionEvent(0, 0);
- appendMotionEvent(100, 5);
- appendMotionEvent(200, -5);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, 5);
+ appendMoveEvent(200, -5);
assertThat(mClassifier.isFalseTouch(), is(false));
}
@@ -167,9 +132,9 @@ public class ZigZagClassifierTest extends SysuiTestCase {
public void testFail_horizontalZigZagVerticalStraight() {
// This test looks just like testPass_horizontalZigZagVerticalStraight but with
// a shorter y range, making it look more crooked.
- appendMotionEvent(0, 0);
- appendMotionEvent(5, 10);
- appendMotionEvent(-5, 20);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(5, 10);
+ appendMoveEvent(-5, 20);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@@ -177,217 +142,217 @@ public class ZigZagClassifierTest extends SysuiTestCase {
public void testFail_horizontalStraightVerticalZigZag() {
// This test looks just like testPass_horizontalStraightVerticalZigZag but with
// a shorter x range, making it look more crooked.
- appendMotionEvent(0, 0);
- appendMotionEvent(10, 5);
- appendMotionEvent(20, -5);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(10, 5);
+ appendMoveEvent(20, -5);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between0And45() {
- appendMotionEvent(0, 0);
- appendMotionEvent(100, 5);
- appendMotionEvent(200, 10);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, 5);
+ appendMoveEvent(200, 10);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(100, 0);
- appendMotionEvent(200, 10);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, 0);
+ appendMoveEvent(200, 10);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(100, -10);
- appendMotionEvent(200, 10);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, -10);
+ appendMoveEvent(200, 10);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(100, -10);
- appendMotionEvent(200, 50);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, -10);
+ appendMoveEvent(200, 50);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between45And90() {
- appendMotionEvent(0, 0);
- appendMotionEvent(10, 50);
- appendMotionEvent(8, 100);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(10, 50);
+ appendMoveEvent(8, 100);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(1, 800);
- appendMotionEvent(2, 900);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(1, 800);
+ appendMoveEvent(2, 900);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-10, 600);
- appendMotionEvent(30, 700);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-10, 600);
+ appendMoveEvent(30, 700);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(40, 100);
- appendMotionEvent(0, 101);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(40, 100);
+ appendMoveEvent(0, 101);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between90And135() {
- appendMotionEvent(0, 0);
- appendMotionEvent(-10, 50);
- appendMotionEvent(-24, 100);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-10, 50);
+ appendMoveEvent(-24, 100);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-20, 800);
- appendMotionEvent(-20, 900);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-20, 800);
+ appendMoveEvent(-20, 900);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(30, 600);
- appendMotionEvent(-10, 700);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(30, 600);
+ appendMoveEvent(-10, 700);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-80, 100);
- appendMotionEvent(-10, 101);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-80, 100);
+ appendMoveEvent(-10, 101);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between135And180() {
- appendMotionEvent(0, 0);
- appendMotionEvent(-120, 10);
- appendMotionEvent(-200, 20);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-120, 10);
+ appendMoveEvent(-200, 20);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-20, 8);
- appendMotionEvent(-40, 2);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-20, 8);
+ appendMoveEvent(-40, 2);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-500, -2);
- appendMotionEvent(-600, 70);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-500, -2);
+ appendMoveEvent(-600, 70);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-80, 100);
- appendMotionEvent(-100, 1);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-80, 100);
+ appendMoveEvent(-100, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between180And225() {
- appendMotionEvent(0, 0);
- appendMotionEvent(-120, -10);
- appendMotionEvent(-200, -20);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-120, -10);
+ appendMoveEvent(-200, -20);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-20, -8);
- appendMotionEvent(-40, -2);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-20, -8);
+ appendMoveEvent(-40, -2);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-500, 2);
- appendMotionEvent(-600, -70);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-500, 2);
+ appendMoveEvent(-600, -70);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-80, -100);
- appendMotionEvent(-100, -1);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-80, -100);
+ appendMoveEvent(-100, -1);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between225And270() {
- appendMotionEvent(0, 0);
- appendMotionEvent(-12, -20);
- appendMotionEvent(-20, -40);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-12, -20);
+ appendMoveEvent(-20, -40);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-20, -130);
- appendMotionEvent(-40, -260);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-20, -130);
+ appendMoveEvent(-40, -260);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(1, -100);
- appendMotionEvent(-6, -200);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(1, -100);
+ appendMoveEvent(-6, -200);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-80, -100);
- appendMotionEvent(-10, -110);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-80, -100);
+ appendMoveEvent(-10, -110);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between270And315() {
- appendMotionEvent(0, 0);
- appendMotionEvent(12, -20);
- appendMotionEvent(20, -40);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(12, -20);
+ appendMoveEvent(20, -40);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(20, -130);
- appendMotionEvent(40, -260);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(20, -130);
+ appendMoveEvent(40, -260);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(-1, -100);
- appendMotionEvent(6, -200);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(-1, -100);
+ appendMoveEvent(6, -200);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(80, -100);
- appendMotionEvent(10, -110);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(80, -100);
+ appendMoveEvent(10, -110);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@Test
public void test_between315And360() {
- appendMotionEvent(0, 0);
- appendMotionEvent(120, -20);
- appendMotionEvent(200, -40);
+ appendMoveEvent(0, 0);
+ appendMoveEvent(120, -20);
+ appendMoveEvent(200, -40);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(200, -13);
- appendMotionEvent(400, -30);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(200, -13);
+ appendMoveEvent(400, -30);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(100, 10);
- appendMotionEvent(600, -20);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(100, 10);
+ appendMoveEvent(600, -20);
assertThat(mClassifier.isFalseTouch(), is(false));
- mMotionEvents.clear();
- appendMotionEvent(0, 0);
- appendMotionEvent(80, -100);
- appendMotionEvent(100, -1);
+ resetDataProvider();
+ appendMoveEvent(0, 0);
+ appendMoveEvent(80, -100);
+ appendMoveEvent(100, -1);
assertThat(mClassifier.isFalseTouch(), is(true));
}
@@ -397,74 +362,50 @@ public class ZigZagClassifierTest extends SysuiTestCase {
// We use a pre-determined seed to make this test repeatable.
Random rand = new Random(23);
for (int i = 0; i < 100; i++) {
- mOffsetX = rand.nextInt(2000) - 1000;
- mOffsetY = rand.nextInt(2000) - 1000;
+ setOffsetX(rand.nextInt(2000) - 1000);
+ setOffsetY(rand.nextInt(2000) - 1000);
try {
- clearMotionEvents();
+ resetDataProvider();
testPass_fewTouchesVertical();
- clearMotionEvents();
+ resetDataProvider();
testPass_vertical();
- clearMotionEvents();
+ resetDataProvider();
testFail_horizontalStraightVerticalZigZag();
- clearMotionEvents();
+ resetDataProvider();
testFail_horizontalZigZagVerticalStraight();
- clearMotionEvents();
+ resetDataProvider();
testFail_minimumTouchesHorizontal();
- clearMotionEvents();
+ resetDataProvider();
testFail_minimumTouchesVertical();
- clearMotionEvents();
+ resetDataProvider();
testPass_fewTouchesHorizontal();
- clearMotionEvents();
+ resetDataProvider();
testPass_fortyFiveDegreesStraight();
- clearMotionEvents();
+ resetDataProvider();
testPass_horizontal();
- clearMotionEvents();
+ resetDataProvider();
testPass_horizontalStraightVerticalZigZag();
- clearMotionEvents();
+ resetDataProvider();
testPass_horizontalZigZagVerticalStraight();
- clearMotionEvents();
+ resetDataProvider();
test_between0And45();
- clearMotionEvents();
+ resetDataProvider();
test_between45And90();
- clearMotionEvents();
+ resetDataProvider();
test_between90And135();
- clearMotionEvents();
+ resetDataProvider();
test_between135And180();
- clearMotionEvents();
+ resetDataProvider();
test_between180And225();
- clearMotionEvents();
+ resetDataProvider();
test_between225And270();
- clearMotionEvents();
+ resetDataProvider();
test_between270And315();
- clearMotionEvents();
+ resetDataProvider();
test_between315And360();
} catch (AssertionError e) {
throw new AssertionError("Random origin failure in iteration " + i, e);
}
}
}
-
- private void clearMotionEvents() {
- for (MotionEvent motionEvent : mMotionEvents) {
- motionEvent.recycle();
- }
- mMotionEvents.clear();
- }
-
- private void appendMotionEvent(float x, float y) {
- x += mOffsetX;
- y += mOffsetY;
-
- long eventTime = mMotionEvents.size() + 1;
- MotionEvent motionEvent = MotionEvent.obtain(1, eventTime, MotionEvent.ACTION_DOWN, x, y,
- 0);
- mMotionEvents.add(motionEvent);
-
- mDx = mDataProvider.getFirstRecentMotionEvent().getX()
- - mDataProvider.getLastMotionEvent().getX();
- mDy = mDataProvider.getFirstRecentMotionEvent().getY()
- - mDataProvider.getLastMotionEvent().getY();
-
- mClassifier.onTouchEvent(motionEvent);
- }
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e81d1721b271..fc67c38560fa 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2616,9 +2616,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0);
final boolean wasValidated = nai.lastValidated;
final boolean wasDefault = isDefaultNetwork(nai);
- if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified
- && valid) {
- nai.captivePortalLoginNotified = true;
+ // Only show a connected notification if the network is pending validation
+ // after the captive portal app was open, and it has now validated.
+ if (nai.captivePortalValidationPending && valid) {
+ // User is now logged in, network validated.
+ nai.captivePortalValidationPending = false;
showNetworkNotification(nai, NotificationType.LOGGED_IN);
}
@@ -2689,9 +2691,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int oldScore = nai.getCurrentScore();
nai.lastCaptivePortalDetected = visible;
nai.everCaptivePortalDetected |= visible;
- if (visible) {
- nai.captivePortalLoginNotified = false;
- }
if (nai.lastCaptivePortalDetected &&
Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
if (DBG) log("Avoiding captive portal network: " + nai.name());
@@ -3500,6 +3499,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+ // This runs on a random binder thread, but getNetworkAgentInfoForNetwork is thread-safe,
+ // and captivePortalValidationPending is volatile.
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai != null) {
+ nai.captivePortalValidationPending = true;
+ }
Binder.withCleanCallingIdentity(() ->
mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 7ab70fad70d4..ed64475084b8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -42,7 +42,7 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_ALL = false;
// Available log categories in the activity manager package.
- static final boolean DEBUG_ANR = true; // STOPSHIP disable it (b/113252928)
+ static final boolean DEBUG_ANR = false;
static final boolean DEBUG_BACKGROUND_CHECK = DEBUG_ALL || false;
static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b342d37dd37a..91ae156afdf5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -272,6 +272,7 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.provider.DeviceConfig.Properties;
import android.server.ServerProtoEnums;
import android.sysprop.VoldProperties;
import android.text.TextUtils;
@@ -356,6 +357,7 @@ import com.android.server.uri.GrantUri;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.PriorityDump;
import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityMetricsLaunchObserver;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerService;
@@ -392,6 +394,7 @@ import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
@@ -861,6 +864,51 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
+ /**
+ * Depth of overlapping activity-start PSS deferral notes
+ */
+ private final AtomicInteger mActivityStartingNesting = new AtomicInteger(0);
+
+ private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
+ new ActivityMetricsLaunchObserver() {
+ @Override
+ public void onActivityLaunched(byte[] activity, int temperature) {
+ // This is safe to force to the head of the queue because it relies only
+ // on refcounting to track begin/end of deferrals, not on actual
+ // message ordering. We don't care *what* activity is being
+ // launched; only that we're doing so.
+ if (mPssDeferralTime > 0) {
+ final Message msg = mBgHandler.obtainMessage(DEFER_PSS_MSG);
+ mBgHandler.sendMessageAtFrontOfQueue(msg);
+ }
+ }
+
+ // The other observer methods are unused
+ @Override
+ public void onIntentStarted(Intent intent) {
+ }
+
+ @Override
+ public void onIntentFailed() {
+ }
+
+ @Override
+ public void onActivityLaunchCancelled(byte[] abortingActivity) {
+ }
+
+ @Override
+ public void onActivityLaunchFinished(byte[] finalActivity) {
+ }
+ };
+
+ /**
+ * How long we defer PSS gathering while activities are starting, in milliseconds.
+ * This is adjustable via DeviceConfig. If it is zero or negative, no PSS deferral
+ * is done.
+ */
+ private volatile long mPssDeferralTime = 0;
+ private static final String ACTIVITY_START_PSS_DEFER_CONFIG = "activity_start_pss_defer";
+
private boolean mBinderTransactionTrackingEnabled = false;
/**
@@ -874,6 +922,20 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
boolean mFullPssPending = false;
+ /**
+ * Observe DeviceConfig changes to the PSS calculation interval
+ */
+ private final DeviceConfig.OnPropertiesChangedListener mPssDelayConfigListener =
+ new DeviceConfig.OnPropertiesChangedListener() {
+ @Override
+ public void onPropertiesChanged(Properties properties) {
+ mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Activity-start PSS delay now "
+ + mPssDeferralTime + " ms");
+ }
+ }
+ };
/**
* This is for verifying the UID report flow.
@@ -1838,6 +1900,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
static final int COLLECT_PSS_BG_MSG = 1;
+ static final int DEFER_PSS_MSG = 2;
+ static final int STOP_DEFERRING_PSS_MSG = 3;
final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
@Override
@@ -1945,6 +2009,30 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} while (true);
}
+
+ case DEFER_PSS_MSG: {
+ deferPssForActivityStart();
+ } break;
+
+ case STOP_DEFERRING_PSS_MSG: {
+ final int nesting = mActivityStartingNesting.decrementAndGet();
+ if (nesting <= 0) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "PSS activity start deferral interval ended; now "
+ + nesting);
+ }
+ if (nesting < 0) {
+ Slog.wtf(TAG, "Activity start nesting undercount!");
+ mActivityStartingNesting.incrementAndGet();
+ }
+ } else {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Still deferring PSS, nesting=" + nesting);
+ }
+ }
+ }
+ break;
+
}
}
};
@@ -3694,9 +3782,7 @@ public class ActivityManagerService extends IActivityManager.Stub
ArrayList<Integer> nativePids) {
ArrayList<Integer> extraPids = null;
- if (DEBUG_ANR) {
- Slog.d(TAG, "dumpStackTraces pids=" + lastPids + " nativepids=" + nativePids);
- }
+ Slog.i(TAG, "dumpStackTraces pids=" + lastPids + " nativepids=" + nativePids);
// Measure CPU usage as soon as we're called in order to get a realistic sampling
// of the top users at the time of the request.
@@ -3718,8 +3804,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid " + stats.pid);
extraPids.add(stats.pid);
- } else if (DEBUG_ANR) {
- Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
+ } else {
+ Slog.i(TAG, "Skipping next CPU consuming process, not a java proc: "
+ stats.pid);
}
}
@@ -3737,9 +3823,6 @@ public class ActivityManagerService extends IActivityManager.Stub
if (tracesFile == null) {
return null;
}
- if (DEBUG_ANR) {
- Slog.d(TAG, "Dumping to " + tracesFile.getAbsolutePath());
- }
dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, nativePids, extraPids);
return tracesFile;
@@ -3832,6 +3915,8 @@ public class ActivityManagerService extends IActivityManager.Stub
public static void dumpStackTraces(String tracesFile, ArrayList<Integer> firstPids,
ArrayList<Integer> nativePids, ArrayList<Integer> extraPids) {
+ Slog.i(TAG, "Dumping to " + tracesFile);
+
// We don't need any sort of inotify based monitoring when we're dumping traces via
// tombstoned. Data is piped to an "intercept" FD installed in tombstoned so we're in full
// control of all writes to the file in question.
@@ -3843,7 +3928,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (firstPids != null) {
int num = firstPids.size();
for (int i = 0; i < num; i++) {
- if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid " + firstPids.get(i));
+ Slog.i(TAG, "Collecting stacks for pid " + firstPids.get(i));
final long timeTaken = dumpJavaTracesTombstoned(firstPids.get(i), tracesFile,
remainingTime);
@@ -3863,7 +3948,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Next collect the stacks of the native pids
if (nativePids != null) {
for (int pid : nativePids) {
- if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
+ Slog.i(TAG, "Collecting stacks for native pid " + pid);
final long nativeDumpTimeoutMs = Math.min(NATIVE_DUMP_TIMEOUT_MS, remainingTime);
final long start = SystemClock.elapsedRealtime();
@@ -3887,7 +3972,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Lastly, dump stacks for all extra PIDs from the CPU tracker.
if (extraPids != null) {
for (int pid : extraPids) {
- if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid " + pid);
+ Slog.i(TAG, "Collecting stacks for extra pid " + pid);
final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime);
@@ -3903,6 +3988,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
}
+ Slog.i(TAG, "Done dumping");
}
@Override
@@ -8845,6 +8931,12 @@ public class ActivityManagerService extends IActivityManager.Stub
NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
mHiddenApiBlacklist.registerObserver();
+ final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ActivityThread.currentApplication().getMainExecutor(),
+ mPssDelayConfigListener);
+
synchronized (this) {
mDebugApp = mOrigDebugApp = debugApp;
mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
@@ -8861,6 +8953,7 @@ public class ActivityManagerService extends IActivityManager.Stub
com.android.internal.R.bool.config_multiuserDelayUserDataLocking);
mWaitForNetworkTimeoutMs = waitForNetworkTimeoutMs;
+ mPssDeferralTime = pssDeferralMs;
}
}
@@ -8923,6 +9016,7 @@ public class ActivityManagerService extends IActivityManager.Stub
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY, SystemClock.uptimeMillis());
mAtmInternal.updateTopComponentForFactoryTest();
+ mAtmInternal.getLaunchObserverRegistry().registerLaunchObserver(mActivityLaunchObserver);
watchDeviceProvisioning(mContext);
@@ -16146,7 +16240,13 @@ public class ActivityManagerService extends IActivityManager.Stub
return false;
}
if (mPendingPssProcesses.size() == 0) {
- mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
+ final long deferral = (mPssDeferralTime > 0 && mActivityStartingNesting.get() > 0)
+ ? mPssDeferralTime : 0;
+ if (DEBUG_PSS && deferral > 0) {
+ Slog.d(TAG_PSS, "requestPssLocked() deferring PSS request by "
+ + deferral + " ms");
+ }
+ mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, deferral);
}
if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
proc.pssProcState = procState;
@@ -16156,6 +16256,30 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/**
+ * Re-defer a posted PSS collection pass, if one exists. Assumes deferral is
+ * currently active policy when called.
+ */
+ private void deferPssIfNeededLocked() {
+ if (mPendingPssProcesses.size() > 0) {
+ mBgHandler.removeMessages(COLLECT_PSS_BG_MSG);
+ mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, mPssDeferralTime);
+ }
+ }
+
+ private void deferPssForActivityStart() {
+ synchronized (ActivityManagerService.this) {
+ if (mPssDeferralTime > 0) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Deferring PSS collection for activity start");
+ }
+ deferPssIfNeededLocked();
+ mActivityStartingNesting.getAndIncrement();
+ mBgHandler.sendEmptyMessageDelayed(STOP_DEFERRING_PSS_MSG, mPssDeferralTime);
+ }
+ }
+ }
+
+ /**
* Schedule PSS collection of all processes.
*/
void requestPssAllProcsLocked(long now, boolean always, boolean memLowered) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 5ade50a5f248..bcfe71b82a6a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -431,7 +431,7 @@ public final class OomAdjuster {
for (int i = 0; i < N; i++) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
- if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now,
+ if (computeOomAdjLocked(app, app.getCurRawAdj(), TOP_APP, true, now,
true)) {
retryCycles = true;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 864a793b8f40..5b043799f848 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -155,9 +155,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// Whether a captive portal was found during the last network validation attempt.
public boolean lastCaptivePortalDetected;
- // Indicates the user was notified of a successful captive portal login since a portal was
- // last detected.
- public boolean captivePortalLoginNotified;
+ // Indicates the captive portal app was opened to show a login UI to the user, but the network
+ // has not validated yet.
+ public volatile boolean captivePortalValidationPending;
// Set to true when partial connectivity was detected.
public boolean partialConnectivity;
@@ -629,7 +629,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
+ "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} "
+ "everCaptivePortalDetected{" + everCaptivePortalDetected + "} "
+ "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} "
- + "captivePortalLoginNotified{" + captivePortalLoginNotified + "} "
+ + "captivePortalValidationPending{" + captivePortalValidationPending + "} "
+ "partialConnectivity{" + partialConnectivity + "} "
+ "acceptPartialConnectivity{" + networkMisc.acceptPartialConnectivity + "} "
+ "clat{" + clatd + "} "
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 3a78aa2fbbf5..037293f9536c 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -50,6 +50,7 @@ import android.permission.PermissionControllerManager;
import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.util.ArraySet;
+import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -58,6 +59,7 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.IntPair;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -147,11 +149,9 @@ public final class PermissionPolicyService extends SystemService {
PermissionInfo perm = dangerousPerms.get(i);
if (perm.isHardRestricted() || perm.backgroundPermission != null) {
- appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
- null, appOpsListener);
+ appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
} else if (perm.isSoftRestricted()) {
- appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
- null, appOpsListener);
+ appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
SoftRestrictedPermissionPolicy policy =
SoftRestrictedPermissionPolicy.forPermission(null, null, null,
@@ -167,6 +167,25 @@ public final class PermissionPolicyService extends SystemService {
}
}
+ /**
+ * Get op that controls the access related to the permission.
+ *
+ * <p>Usually the permission-op relationship is 1:1 but some permissions (e.g. fine location)
+ * {@link AppOpsManager#sOpToSwitch share an op} to control the access.
+ *
+ * @param permission The permission
+ *
+ * @return The op that controls the access of the permission
+ */
+ private static int getSwitchOp(@NonNull String permission) {
+ int op = AppOpsManager.permissionToOpCode(permission);
+ if (op == OP_NONE) {
+ return OP_NONE;
+ }
+
+ return AppOpsManager.opToSwitch(op);
+ }
+
private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
@UserIdInt int changedUserId) {
if (isStarted(changedUserId)) {
@@ -430,40 +449,89 @@ public final class PermissionPolicyService extends SystemService {
* <p>This processes ops previously added by {@link #addOpIfRestricted}
*/
private void syncPackages() {
+ // Remember which ops were already set. This makes sure that we always set the most
+ // permissive mode if two OpChanges are scheduled. This can e.g. happen if two
+ // permissions change the same op. See {@link #getSwitchOp}.
+ LongSparseLongArray alreadySetAppOps = new LongSparseLongArray();
+
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
final OpToChange op = mOpsToAllow.get(i);
+
setUidModeAllowed(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
for (int i = 0; i < allowIfDefaultCount; i++) {
final OpToChange op = mOpsToAllowIfDefault.get(i);
- setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
- final int foregroundCount = mOpsToForegroundIfAllow.size();
- for (int i = 0; i < foregroundCount; i++) {
+
+ final int foregroundIfAllowedCount = mOpsToForegroundIfAllow.size();
+ for (int i = 0; i < foregroundIfAllowedCount; i++) {
final OpToChange op = mOpsToForegroundIfAllow.get(i);
- setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
- final int foregroundIfAllowCount = mOpsToForeground.size();
- for (int i = 0; i < foregroundIfAllowCount; i++) {
+
+ final int foregroundCount = mOpsToForeground.size();
+ for (int i = 0; i < foregroundCount; i++) {
final OpToChange op = mOpsToForeground.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeForeground(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) {
final OpToChange op = mOpsToIgnore.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeIgnored(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
for (int i = 0; i < ignoreIfDefaultCount; i++) {
final OpToChange op = mOpsToIgnoreIfDefault.get(i);
- setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
+
final int defaultCount = mOpsToDefault.size();
for (int i = 0; i < defaultCount; i++) {
final OpToChange op = mOpsToDefault.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeDefault(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
}
@@ -479,7 +547,7 @@ public final class PermissionPolicyService extends SystemService {
private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo,
@NonNull PackageInfo pkg) {
final String permission = permissionInfo.name;
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
final int uid = pkg.applicationInfo.uid;
if (!permissionInfo.isRestricted()) {
@@ -581,7 +649,7 @@ public final class PermissionPolicyService extends SystemService {
}
final String permission = permissionInfo.name;
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
final String pkgName = pkg.packageName;
final int uid = pkg.applicationInfo.uid;
@@ -641,7 +709,7 @@ public final class PermissionPolicyService extends SystemService {
}
for (String permission : pkg.requestedPermissions) {
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
if (opCode == OP_NONE) {
continue;
}
@@ -658,24 +726,27 @@ public final class PermissionPolicyService extends SystemService {
}
}
- private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
+ private boolean setUidModeAllowedIfDefault(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
}
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
}
- private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
+ private boolean setUidModeForegroundIfAllow(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
}
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
}
- private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
+ private boolean setUidModeIgnoredIfDefault(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
}
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
@@ -692,14 +763,17 @@ public final class PermissionPolicyService extends SystemService {
}
}
- private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
+ private boolean setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
@NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
if (currentMode == requiredModeBefore) {
mAppOpsManager.setUidMode(opCode, uid, newMode);
+ return true;
}
+
+ return false;
}
private void setUidModeDefault(int opCode, int uid, String packageName) {
diff --git a/services/core/java/com/android/server/policy/TEST_MAPPING b/services/core/java/com/android/server/policy/TEST_MAPPING
index c7f8c07432a8..c7e241b35e9a 100644
--- a/services/core/java/com/android/server/policy/TEST_MAPPING
+++ b/services/core/java/com/android/server/policy/TEST_MAPPING
@@ -41,6 +41,9 @@
"options": [
{
"include-filter": "android.permission.cts.SplitPermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.BackgroundPermissionsTest"
}
]
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index bbfb3c555657..cf87203893cf 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -478,8 +478,10 @@ public class DisplayPolicy {
@Override
public void onSwipeFromRight() {
- final Region excludedRegion =
- mDisplayContent.calculateSystemGestureExclusion();
+ final Region excludedRegion;
+ synchronized (mLock) {
+ excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
+ }
final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
|| mNavigationBarPosition == NAV_BAR_RIGHT;
if (mNavigationBar != null && sideAllowed
@@ -490,8 +492,10 @@ public class DisplayPolicy {
@Override
public void onSwipeFromLeft() {
- final Region excludedRegion =
- mDisplayContent.calculateSystemGestureExclusion();
+ final Region excludedRegion;
+ synchronized (mLock) {
+ excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
+ }
final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
|| mNavigationBarPosition == NAV_BAR_LEFT;
if (mNavigationBar != null && sideAllowed
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index ba2325877075..af729317392b 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -25,6 +25,7 @@ import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.NonNull;
import android.app.RemoteAction;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
@@ -45,6 +46,7 @@ import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.internal.util.Preconditions;
import com.android.server.UiThread;
import java.io.PrintWriter;
@@ -326,8 +328,8 @@ class PinnedStackController {
boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
synchronized (mService.mGlobalLock) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
- if (mDisplayInfo.equals(displayInfo)) {
- // We are already in the right orientation, ignore
+ if (isSameDimensionAndRotation(mDisplayInfo, displayInfo)) {
+ // No dimension/rotation change, ignore
outBounds.setEmpty();
return false;
} else if (targetBounds.isEmpty()) {
@@ -427,6 +429,15 @@ class PinnedStackController {
notifyActionsChanged(mActions);
}
+ private boolean isSameDimensionAndRotation(@NonNull DisplayInfo display1,
+ @NonNull DisplayInfo display2) {
+ Preconditions.checkNotNull(display1);
+ Preconditions.checkNotNull(display2);
+ return ((display1.rotation == display2.rotation)
+ && (display1.logicalWidth == display2.logicalWidth)
+ && (display1.logicalHeight == display2.logicalHeight));
+ }
+
/**
* Notifies listeners that the PIP needs to be adjusted for the IME.
*/
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 481c3ba24fca..114a56feaf73 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1936,8 +1936,12 @@ public class TaskStack extends WindowContainer<Task> implements
public boolean setPinnedStackAlpha(float alpha) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
synchronized (mWmService.mGlobalLock) {
- getPendingTransaction().setAlpha(getSurfaceControl(),
- mCancelCurrentBoundsAnimation ? 1 : alpha);
+ final SurfaceControl sc = getSurfaceControl();
+ if (sc == null || !sc.isValid()) {
+ // If the stack is already removed, don't bother updating any stack animation
+ return false;
+ }
+ getPendingTransaction().setAlpha(sc, mCancelCurrentBoundsAnimation ? 1 : alpha);
scheduleAnimation();
return !mCancelCurrentBoundsAnimation;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 57fa2ed63121..28bb3d8999c3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7690,7 +7690,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void onPointerDownOutsideFocusLocked(IBinder touchedToken) {
final WindowState touchedWindow = windowForClientLocked(null, touchedToken, false);
- if (touchedWindow == null) {
+ if (touchedWindow == null || !touchedWindow.canReceiveKeys()) {
return;
}
diff --git a/telecomm/java/android/telecom/ConferenceParticipant.java b/telecomm/java/android/telecom/ConferenceParticipant.java
index 2f1505cd9e4e..5e4818a67b31 100644
--- a/telecomm/java/android/telecom/ConferenceParticipant.java
+++ b/telecomm/java/android/telecom/ConferenceParticipant.java
@@ -19,6 +19,7 @@ package android.telecom;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
@@ -69,18 +70,28 @@ public class ConferenceParticipant implements Parcelable {
private long mConnectElapsedTime;
/**
+ * The direction of the call;
+ * {@link Call.Details#DIRECTION_INCOMING} for incoming calls, or
+ * {@link Call.Details#DIRECTION_OUTGOING} for outgoing calls.
+ */
+ private int mCallDirection;
+
+ /**
* Creates an instance of {@code ConferenceParticipant}.
*
* @param handle The conference participant's handle (e.g., phone number).
* @param displayName The display name for the participant.
* @param endpoint The enpoint Uri which uniquely identifies this conference participant.
* @param state The state of the participant in the conference.
+ * @param callDirection The direction of the call (incoming/outgoing).
*/
- public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state) {
+ public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state,
+ int callDirection) {
mHandle = handle;
mDisplayName = displayName;
mEndpoint = endpoint;
mState = state;
+ mCallDirection = callDirection;
}
/**
@@ -96,7 +107,16 @@ public class ConferenceParticipant implements Parcelable {
String displayName = source.readString();
Uri endpoint = source.readParcelable(classLoader);
int state = source.readInt();
- return new ConferenceParticipant(handle, displayName, endpoint, state);
+ long connectTime = source.readLong();
+ long elapsedRealTime = source.readLong();
+ int callDirection = source.readInt();
+ ConferenceParticipant participant =
+ new ConferenceParticipant(handle, displayName, endpoint, state,
+ callDirection);
+ participant.setConnectTime(connectTime);
+ participant.setConnectElapsedTime(elapsedRealTime);
+ participant.setCallDirection(callDirection);
+ return participant;
}
@Override
@@ -170,6 +190,9 @@ public class ConferenceParticipant implements Parcelable {
dest.writeString(mDisplayName);
dest.writeParcelable(mEndpoint, 0);
dest.writeInt(mState);
+ dest.writeLong(mConnectTime);
+ dest.writeLong(mConnectElapsedTime);
+ dest.writeInt(mCallDirection);
}
/**
@@ -192,6 +215,8 @@ public class ConferenceParticipant implements Parcelable {
sb.append(getConnectTime());
sb.append(" ConnectElapsedTime: ");
sb.append(getConnectElapsedTime());
+ sb.append(" Direction: ");
+ sb.append(getCallDirection() == Call.Details.DIRECTION_INCOMING ? "Incoming" : "Outgoing");
sb.append("]");
return sb.toString();
}
@@ -239,7 +264,7 @@ public class ConferenceParticipant implements Parcelable {
}
/**
- * The connect elpased time of the participant to the conference.
+ * The connect elapsed time of the participant to the conference.
*/
public long getConnectElapsedTime() {
return mConnectElapsedTime;
@@ -248,4 +273,76 @@ public class ConferenceParticipant implements Parcelable {
public void setConnectElapsedTime(long connectElapsedTime) {
mConnectElapsedTime = connectElapsedTime;
}
+
+ /**
+ * @return The direction of the call (incoming/outgoing).
+ */
+ public @Call.Details.CallDirection int getCallDirection() {
+ return mCallDirection;
+ }
+
+ /**
+ * Sets the direction of the call.
+ * @param callDirection Whether the call is incoming or outgoing.
+ */
+ public void setCallDirection(@Call.Details.CallDirection int callDirection) {
+ mCallDirection = callDirection;
+ }
+
+ /**
+ * Attempts to build a tel: style URI from a conference participant.
+ * Conference event package data contains SIP URIs, so we try to extract the phone number and
+ * format into a typical tel: style URI.
+ *
+ * @param address The conference participant's address.
+ * @param countryIso The country ISO of the current subscription; used when formatting the
+ * participant phone number to E.164 format.
+ * @return The participant's address URI.
+ * @hide
+ */
+ @VisibleForTesting
+ public static Uri getParticipantAddress(Uri address, String countryIso) {
+ if (address == null) {
+ return address;
+ }
+ // Even if address is already in tel: format, still parse it and rebuild.
+ // This is to recognize tel URIs such as:
+ // tel:6505551212;phone-context=ims.mnc012.mcc034.3gppnetwork.org
+
+ // Conference event package participants are identified using SIP URIs (see RFC3261).
+ // A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
+ // Per RFC3261, the "user" can be a telephone number.
+ // For example: sip:1650555121;phone-context=blah.com@host.com
+ // In this case, the phone number is in the user field of the URI, and the parameters can be
+ // ignored.
+ //
+ // A SIP URI can also specify a phone number in a format similar to:
+ // sip:+1-212-555-1212@something.com;user=phone
+ // In this case, the phone number is again in user field and the parameters can be ignored.
+ // We can get the user field in these instances by splitting the string on the @, ;, or :
+ // and looking at the first found item.
+ String number = address.getSchemeSpecificPart();
+ if (TextUtils.isEmpty(number)) {
+ return address;
+ }
+
+ String numberParts[] = number.split("[@;:]");
+ if (numberParts.length == 0) {
+ return address;
+ }
+ number = numberParts[0];
+
+ // Attempt to format the number in E.164 format and use that as part of the TEL URI.
+ // RFC2806 recommends to format telephone numbers using E.164 since it is independent of
+ // how the dialing of said numbers takes place.
+ // If conversion to E.164 fails, the returned value is null. In that case, fallback to the
+ // number which was in the CEP data.
+ String formattedNumber = null;
+ if (!TextUtils.isEmpty(countryIso)) {
+ formattedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
+ }
+
+ return Uri.fromParts(PhoneAccount.SCHEME_TEL,
+ formattedNumber != null ? formattedNumber : number, null);
+ }
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 47587c5787f4..0983eea8e819 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1793,6 +1793,11 @@ public abstract class Connection extends Conferenceable {
private ConnectionService mConnectionService;
private Bundle mExtras;
private final Object mExtrasLock = new Object();
+ /**
+ * The direction of the connection; used where an existing connection is created and we need to
+ * communicate to Telecom whether its incoming or outgoing.
+ */
+ private @Call.Details.CallDirection int mCallDirection = Call.Details.DIRECTION_UNKNOWN;
/**
* Tracks the key set for the extras bundle provided on the last invocation of
@@ -3357,4 +3362,21 @@ public abstract class Connection extends Conferenceable {
l.onConnectionEvent(this, event, extras);
}
}
+
+ /**
+ * @return The direction of the call.
+ * @hide
+ */
+ public final @Call.Details.CallDirection int getCallDirection() {
+ return mCallDirection;
+ }
+
+ /**
+ * Sets the direction of this connection.
+ * @param callDirection The direction of this connection.
+ * @hide
+ */
+ public void setCallDirection(@Call.Details.CallDirection int callDirection) {
+ mCallDirection = callDirection;
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 626fcc4ddc1e..35488100fb58 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2144,7 +2144,8 @@ public abstract class ConnectionService extends Service {
connection.getDisconnectCause(),
emptyList,
connection.getExtras(),
- conferenceId);
+ conferenceId,
+ connection.getCallDirection());
mAdapter.addExistingConnection(id, parcelableConnection);
}
}
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index dab1c6e7ae77..4734af6371d4 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -53,6 +53,7 @@ public final class ParcelableConnection implements Parcelable {
private final List<String> mConferenceableConnectionIds;
private final Bundle mExtras;
private String mParentCallId;
+ private @Call.Details.CallDirection int mCallDirection;
/** @hide */
public ParcelableConnection(
@@ -75,13 +76,15 @@ public final class ParcelableConnection implements Parcelable {
DisconnectCause disconnectCause,
List<String> conferenceableConnectionIds,
Bundle extras,
- String parentCallId) {
+ String parentCallId,
+ @Call.Details.CallDirection int callDirection) {
this(phoneAccount, state, capabilities, properties, supportedAudioRoutes, address,
addressPresentation, callerDisplayName, callerDisplayNamePresentation,
videoProvider, videoState, ringbackRequested, isVoipAudioMode, connectTimeMillis,
connectElapsedTimeMillis, statusHints, disconnectCause, conferenceableConnectionIds,
extras);
mParentCallId = parentCallId;
+ mCallDirection = callDirection;
}
/** @hide */
@@ -125,6 +128,7 @@ public final class ParcelableConnection implements Parcelable {
mConferenceableConnectionIds = conferenceableConnectionIds;
mExtras = extras;
mParentCallId = null;
+ mCallDirection = Call.Details.DIRECTION_UNKNOWN;
}
public PhoneAccountHandle getPhoneAccount() {
@@ -219,6 +223,10 @@ public final class ParcelableConnection implements Parcelable {
return mParentCallId;
}
+ public @Call.Details.CallDirection int getCallDirection() {
+ return mCallDirection;
+ }
+
@Override
public String toString() {
return new StringBuilder()
@@ -234,6 +242,8 @@ public final class ParcelableConnection implements Parcelable {
.append(mExtras)
.append(", parent:")
.append(mParentCallId)
+ .append(", callDirection:")
+ .append(mCallDirection)
.toString();
}
@@ -265,6 +275,7 @@ public final class ParcelableConnection implements Parcelable {
int supportedAudioRoutes = source.readInt();
String parentCallId = source.readString();
long connectElapsedTimeMillis = source.readLong();
+ int callDirection = source.readInt();
return new ParcelableConnection(
phoneAccount,
@@ -286,7 +297,8 @@ public final class ParcelableConnection implements Parcelable {
disconnectCause,
conferenceableConnectionIds,
extras,
- parentCallId);
+ parentCallId,
+ callDirection);
}
@Override
@@ -325,5 +337,6 @@ public final class ParcelableConnection implements Parcelable {
destination.writeInt(mSupportedAudioRoutes);
destination.writeString(mParentCallId);
destination.writeLong(mConnectElapsedTimeMillis);
+ destination.writeInt(mCallDirection);
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 8c024a5a53c7..73ee7f544b5f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,6 +18,7 @@ package com.android.server;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
@@ -80,13 +81,13 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -141,6 +142,7 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
+import android.net.NetworkStack;
import android.net.NetworkStackClient;
import android.net.NetworkState;
import android.net.NetworkUtils;
@@ -154,6 +156,7 @@ import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
import android.os.Binder;
+import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -191,6 +194,7 @@ import com.android.server.connectivity.DefaultNetworkMetrics;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
+import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
@@ -282,6 +286,7 @@ public class ConnectivityServiceTest {
@Mock NetworkStackClient mNetworkStack;
@Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
+ @Mock NotificationManager mNotificationManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -351,7 +356,7 @@ public class ConnectivityServiceTest {
@Override
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
- if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
+ if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
if (Context.USER_SERVICE.equals(name)) return mUserManager;
return super.getSystemService(name);
@@ -371,7 +376,17 @@ public class ConnectivityServiceTest {
public PackageManager getPackageManager() {
return mPackageManager;
}
- }
+
+ @Override
+ public void enforceCallingOrSelfPermission(String permission, String message) {
+ // The mainline permission can only be held if signed with the network stack certificate
+ // Skip testing for this permission.
+ if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
+ // All other permissions should be held by the test or unnecessary: check as normal to
+ // make sure the code does not rely on unexpected permissions.
+ super.enforceCallingOrSelfPermission(permission, message);
+ }
+ }
public void waitForIdle(int timeoutMsAsInt) {
long timeoutMs = timeoutMsAsInt;
@@ -2856,6 +2871,9 @@ public class ConnectivityServiceTest {
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+ // Expect no notification to be shown when captive portal disappears by itself
+ verify(mNotificationManager, never()).notifyAsUser(
+ anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
// Break network connectivity.
// Expect NET_CAPABILITY_VALIDATED onLost callback.
@@ -2885,6 +2903,8 @@ public class ConnectivityServiceTest {
// Check that calling startCaptivePortalApp does nothing.
final int fastTimeoutMs = 100;
mCm.startCaptivePortalApp(wifiNetwork);
+ waitForIdle();
+ verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
// Turn into a captive portal.
@@ -2895,14 +2915,26 @@ public class ConnectivityServiceTest {
// Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
mCm.startCaptivePortalApp(wifiNetwork);
- verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
- .launchCaptivePortalApp();
+ waitForIdle();
+ verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
+
+ // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
+ final Bundle testBundle = new Bundle();
+ final String testKey = "testkey";
+ final String testValue = "testvalue";
+ testBundle.putString(testKey, testValue);
+ mCm.startCaptivePortalApp(wifiNetwork, testBundle);
+ final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
+ assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
+ assertEquals(testValue, signInIntent.getStringExtra(testKey));
// Report that the captive portal is dismissed, and check that callbacks are fired
mWiFiNetworkAgent.setNetworkValid();
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
+ eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
mCm.unregisterNetworkCallback(validatedCallback);
mCm.unregisterNetworkCallback(captivePortalCallback);
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index daea601e9f96..0511f2411647 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -31,11 +31,8 @@ import java.util.Arrays;
import java.util.Objects;
/**
- * Network specifier object used to request a Wi-Fi Aware network. Apps do not create these objects
- * directly but obtain them using
- * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} or
- * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)} or their secure (Passphrase)
- * versions.
+ * Network specifier object used to request a Wi-Fi Aware network. Apps should use the
+ * {@link WifiAwareNetworkSpecifier.Builder} class to create an instance.
*/
public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
/**