diff options
54 files changed, 564 insertions, 151 deletions
diff --git a/Android.bp b/Android.bp index 0d9cbd8daf5c..554ceae3adad 100644 --- a/Android.bp +++ b/Android.bp @@ -487,7 +487,8 @@ java_library { // TODO(b/140299412): should be framework-wifi-stubs "framework-wifi", "ike-stubs", - // TODO(jiyong): add more stubs for APEXes here + // TODO(b/147200698): should be the stub of framework-tethering + "framework-tethering", ], sdk_version: "core_platform", apex_available: ["//apex_available:platform"], diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp index 3dc5a2c10b6b..1f30dda21ef7 100644 --- a/apex/appsearch/framework/Android.bp +++ b/apex/appsearch/framework/Android.bp @@ -26,9 +26,16 @@ java_library { installable: true, sdk_version: "core_platform", // TODO(b/146218515) should be core_current srcs: [":framework-appsearch-sources"], + hostdex: true, // for hiddenapi check libs: [ "framework-minus-apex", // TODO(b/146218515) should be framework-system-stubs ], + visibility: [ + "//frameworks/base/apex/appsearch:__subpackages__", + // TODO(b/146218515) remove this when framework is built with the stub of appsearch + "//frameworks/base", + ], + apex_available: ["com.android.appsearch"], } metalava_appsearch_docs_args = diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index 6bd0086681a7..18382a488428 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -55,6 +55,13 @@ java_library { jarjar_rules: "jarjar_rules.txt", plugins: ["java_api_finder"], + + hostdex: true, // for hiddenapi check + visibility: ["//frameworks/av/apex:__subpackages__"], + apex_available: [ + "com.android.media", + "test_com.android.media", + ], } filegroup { diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp index 5504f4e5dd8e..dd174734df6d 100644 --- a/apex/sdkextensions/framework/Android.bp +++ b/apex/sdkextensions/framework/Android.bp @@ -36,6 +36,11 @@ java_library { "//frameworks/base/apex/sdkextensions", "//frameworks/base/apex/sdkextensions/testing", ], + hostdex: true, // for hiddenapi check + apex_available: [ + "com.android.sdkext", + "test_com.android.sdkext", + ], } droidstubs { diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp index a2b0577fe001..0b46645ad06f 100644 --- a/apex/statsd/framework/Android.bp +++ b/apex/statsd/framework/Android.bp @@ -37,7 +37,16 @@ java_library { // TODO(b/146230220): Use framework-system-stubs instead. "android_system_stubs_current", ], - // TODO:(b/146210774): Add apex_available field. + hostdex: true, // for hiddenapi check + visibility: [ + "//frameworks/base/apex/statsd:__subpackages__", + //TODO(b/146167933) remove this when framework is built with framework-statsd-stubs + "//frameworks/base", + ], + apex_available: [ + "com.android.os.statsd", + "test_com.android.os.statsd", + ], } droidstubs { diff --git a/api/current.txt b/api/current.txt index 0c93555fc483..edb31dfdf444 100644 --- a/api/current.txt +++ b/api/current.txt @@ -35831,6 +35831,7 @@ package android.os { field public static final int THREAD_PRIORITY_URGENT_AUDIO = -19; // 0xffffffed field public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8; // 0xfffffff8 field public static final int THREAD_PRIORITY_VIDEO = -10; // 0xfffffff6 + field public static final int WIFI_UID = 1010; // 0x3f2 } public abstract class ProxyFileDescriptorCallback { diff --git a/api/system-current.txt b/api/system-current.txt index cb4f3333ecdc..367956c27721 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -152,6 +152,7 @@ package android { field public static final String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"; field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT"; field public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES"; + field public static final String RADIO_SCAN_WITHOUT_LOCATION = "android.permission.RADIO_SCAN_WITHOUT_LOCATION"; field public static final String READ_ACTIVE_EMERGENCY_SESSION = "android.permission.READ_ACTIVE_EMERGENCY_SESSION"; field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS"; diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 5fe647c8b6bf..5d80ab6453cc 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -68,10 +68,9 @@ public class Process { public static final int LOG_UID = 1007; /** - * Defines the UID/GID for the WIFI supplicant process. - * @hide + * Defines the UID/GID for the WIFI native processes like wificond, supplicant, hostapd, + * vendor HAL, etc. */ - @UnsupportedAppUsage public static final int WIFI_UID = 1010; /** diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index a0cf53437a50..20af76b0d5ca 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -5921,8 +5921,6 @@ public class Editor { // The offsets of that last touch down event. Remembered to start selection there. private int mMinTouchOffset, mMaxTouchOffset; - private boolean mGestureStayedInTapRegion; - // Where the user first starts the drag motion. private int mStartOffset = -1; @@ -6029,8 +6027,7 @@ public class Editor { eventX, eventY); // Double tap detection - if (mGestureStayedInTapRegion - && mTouchState.isMultiTapInSameArea() + if (mTouchState.isMultiTapInSameArea() && (isMouse || isPositionOnText(eventX, eventY))) { if (TextView.DEBUG_CURSOR) { logCursor("SelectionModifierCursorController: onTouchEvent", @@ -6043,7 +6040,6 @@ public class Editor { } mDiscardNextActionUp = true; } - mGestureStayedInTapRegion = true; mHaventMovedEnoughToStartDrag = true; } break; @@ -6059,25 +6055,8 @@ public class Editor { break; case MotionEvent.ACTION_MOVE: - final ViewConfiguration viewConfig = ViewConfiguration.get( - mTextView.getContext()); - - if (mGestureStayedInTapRegion || mHaventMovedEnoughToStartDrag) { - final float deltaX = eventX - mTouchState.getLastDownX(); - final float deltaY = eventY - mTouchState.getLastDownY(); - final float distanceSquared = deltaX * deltaX + deltaY * deltaY; - - if (mGestureStayedInTapRegion) { - int doubleTapTouchSlop = viewConfig.getScaledDoubleTapTouchSlop(); - mGestureStayedInTapRegion = - distanceSquared <= doubleTapTouchSlop * doubleTapTouchSlop; - } - if (mHaventMovedEnoughToStartDrag) { - // We don't start dragging until the user has moved enough. - int touchSlop = viewConfig.getScaledTouchSlop(); - mHaventMovedEnoughToStartDrag = - distanceSquared <= touchSlop * touchSlop; - } + if (mHaventMovedEnoughToStartDrag) { + mHaventMovedEnoughToStartDrag = !mTouchState.isMovedEnoughForDrag(); } if (isMouse && !isDragAcceleratorActive()) { diff --git a/core/java/android/widget/EditorTouchState.java b/core/java/android/widget/EditorTouchState.java index d53099d44f6f..6277afe2f613 100644 --- a/core/java/android/widget/EditorTouchState.java +++ b/core/java/android/widget/EditorTouchState.java @@ -31,13 +31,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Helper class used by {@link Editor} to track state for touch events. + * Helper class used by {@link Editor} to track state for touch events. Ideally the logic here + * should be replaced with {@link android.view.GestureDetector}. * * @hide */ @VisibleForTesting(visibility = PACKAGE) public class EditorTouchState { private float mLastDownX, mLastDownY; + private long mLastDownMillis; private float mLastUpX, mLastUpY; private long mLastUpMillis; @@ -106,9 +108,18 @@ public class EditorTouchState { final int action = event.getActionMasked(); if (action == MotionEvent.ACTION_DOWN) { final boolean isMouse = event.isFromSource(InputDevice.SOURCE_MOUSE); + + // We check both the time between the last up and current down event, as well as the + // time between the first down and up events. The latter check is necessary to handle + // the case when the user taps, drags/holds for some time, and then lifts up and + // quickly taps in the same area. This scenario should not be treated as a double-tap. + // This follows the behavior in GestureDetector. final long millisSinceLastUp = event.getEventTime() - mLastUpMillis; + final long millisBetweenLastDownAndLastUp = mLastUpMillis - mLastDownMillis; + // Detect double tap and triple click. if (millisSinceLastUp <= ViewConfiguration.getDoubleTapTimeout() + && millisBetweenLastDownAndLastUp <= ViewConfiguration.getDoubleTapTimeout() && (mMultiTapStatus == MultiTapStatus.FIRST_TAP || (mMultiTapStatus == MultiTapStatus.DOUBLE_TAP && isMouse))) { if (mMultiTapStatus == MultiTapStatus.FIRST_TAP) { @@ -133,6 +144,7 @@ public class EditorTouchState { } mLastDownX = event.getX(); mLastDownY = event.getY(); + mLastDownMillis = event.getEventTime(); mMovedEnoughForDrag = false; mIsDragCloseToVertical = false; } else if (action == MotionEvent.ACTION_UP) { diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp index 90cc98699827..0f56779135b8 100644 --- a/core/jni/android/graphics/apex/android_bitmap.cpp +++ b/core/jni/android/graphics/apex/android_bitmap.cpp @@ -122,6 +122,99 @@ AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) { return getInfo(bitmap->info(), bitmap->rowBytes()); } +static bool nearlyEqual(float a, float b) { + // By trial and error, this is close enough to match for the ADataSpaces we + // compare for. + return ::fabs(a-b) < .002f; +} + +static bool nearlyEqual(const skcms_TransferFunction& x, const skcms_TransferFunction& y) { + return nearlyEqual(x.g, y.g) + && nearlyEqual(x.a, y.a) + && nearlyEqual(x.b, y.b) + && nearlyEqual(x.c, y.c) + && nearlyEqual(x.d, y.d) + && nearlyEqual(x.e, y.e) + && nearlyEqual(x.f, y.f); +} + +static bool nearlyEqual(const skcms_Matrix3x3& x, const skcms_Matrix3x3& y) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (!nearlyEqual(x.vals[i][j], y.vals[i][j])) return false; + } + } + return true; +} + +static constexpr skcms_TransferFunction k2Dot6 = + { 2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + +// Skia's SkNamedGamut::kDCIP3 is based on a white point of D65. This gamut +// matches the white point used by ColorSpace.Named.DCIP3. +static constexpr skcms_Matrix3x3 kDCIP3 = {{ + { 0.486143, 0.323835, 0.154234 }, + { 0.226676, 0.710327, 0.0629966 }, + { 0.000800549, 0.0432385, 0.78275 }, +}}; + +ADataSpace ABitmap_getDataSpace(ABitmap* bitmapHandle) { + Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); + const SkImageInfo& info = bitmap->info(); + SkColorSpace* colorSpace = info.colorSpace(); + if (!colorSpace) { + return ADATASPACE_UNKNOWN; + } + + if (colorSpace->isSRGB()) { + if (info.colorType() == kRGBA_F16_SkColorType) { + return ADATASPACE_SCRGB; + } + return ADATASPACE_SRGB; + } + + skcms_TransferFunction fn; + LOG_ALWAYS_FATAL_IF(!colorSpace->isNumericalTransferFn(&fn)); + + skcms_Matrix3x3 gamut; + LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&gamut)); + + if (nearlyEqual(gamut, SkNamedGamut::kSRGB)) { + if (nearlyEqual(fn, SkNamedTransferFn::kLinear)) { + // Skia doesn't differentiate amongst the RANGES. In Java, we associate + // LINEAR_EXTENDED_SRGB with F16, and LINEAR_SRGB with other Configs. + // Make the same association here. + if (info.colorType() == kRGBA_F16_SkColorType) { + return ADATASPACE_SCRGB_LINEAR; + } + return ADATASPACE_SRGB_LINEAR; + } + + if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) { + return ADATASPACE_BT709; + } + } + + if (nearlyEqual(fn, SkNamedTransferFn::kSRGB) && nearlyEqual(gamut, SkNamedGamut::kDCIP3)) { + return ADATASPACE_DISPLAY_P3; + } + + if (nearlyEqual(fn, SkNamedTransferFn::k2Dot2) && nearlyEqual(gamut, SkNamedGamut::kAdobeRGB)) { + return ADATASPACE_ADOBE_RGB; + } + + if (nearlyEqual(fn, SkNamedTransferFn::kRec2020) + && nearlyEqual(gamut, SkNamedGamut::kRec2020)) { + return ADATASPACE_BT2020; + } + + if (nearlyEqual(fn, k2Dot6) && nearlyEqual(gamut, kDCIP3)) { + return ADATASPACE_DCI_P3; + } + + return ADATASPACE_UNKNOWN; +} + AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) { uint32_t rowBytes = 0; SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes); diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h index f231eeddb7e2..32b8a450e147 100644 --- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h +++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h @@ -17,6 +17,7 @@ #define ANDROID_GRAPHICS_BITMAP_H #include <android/bitmap.h> +#include <android/data_space.h> #include <jni.h> #include <sys/cdefs.h> @@ -49,6 +50,7 @@ void ABitmap_acquireRef(ABitmap* bitmap); void ABitmap_releaseRef(ABitmap* bitmap); AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap); +ADataSpace ABitmap_getDataSpace(ABitmap* bitmap); void* ABitmap_getPixels(ABitmap* bitmap); void ABitmap_notifyPixelsChanged(ABitmap* bitmap); @@ -106,6 +108,7 @@ namespace graphics { ABitmap* get() const { return mBitmap; } AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); } + ADataSpace getDataSpace() const { return ABitmap_getDataSpace(mBitmap); } void* getPixels() const { return ABitmap_getPixels(mBitmap); } void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); } @@ -119,4 +122,4 @@ namespace graphics { }; // namespace android #endif // __cplusplus -#endif // ANDROID_GRAPHICS_BITMAP_H
\ No newline at end of file +#endif // ANDROID_GRAPHICS_BITMAP_H diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5aa0a2dda17e..03d34b595e4a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1654,6 +1654,7 @@ <!-- Allows holder to request bluetooth/wifi scan bypassing global "use location" setting and location permissions. <p>Not for use by third-party or privileged applications. + @SystemApi @hide --> <permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION" diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java index 68b9b0079761..f4709ff0bc00 100644 --- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java +++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java @@ -33,14 +33,15 @@ import android.os.ParcelFileDescriptor.AutoCloseInputStream; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.support.test.uiautomator.UiDevice; import android.test.InstrumentationTestCase; import android.util.Log; -import libcore.io.Streams; - import com.google.mockwebserver.MockResponse; import com.google.mockwebserver.MockWebServer; +import libcore.io.Streams; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; @@ -63,6 +64,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { private static final String TAG = "DownloadManagerBaseTest"; protected DownloadManager mDownloadManager = null; private MockWebServer mServer = null; + private UiDevice mUiDevice = null; protected String mFileType = "text/plain"; protected Context mContext = null; protected MultipleDownloadsCompletedReceiver mReceiver = null; @@ -234,6 +236,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { @Override public void setUp() throws Exception { mContext = getInstrumentation().getContext(); + mUiDevice = UiDevice.getInstance(getInstrumentation()); mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE); mServer = new MockWebServer(); mServer.play(); @@ -512,7 +515,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { Log.i(LOG_TAG, "Setting WiFi State to: " + enable); WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); - manager.setWifiEnabled(enable); + mUiDevice.executeShellCommand("svc wifi " + (enable ? "enable" : "disable")); String timeoutMessage = "Timed out waiting for Wifi to be " + (enable ? "enabled!" : "disabled!"); diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java index f497db2256dd..89c237498e5c 100644 --- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java +++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java @@ -226,6 +226,61 @@ public class EditorCursorDragTest { } @Test + public void testEditor_onTouchEvent_quickTapAfterDrag() throws Throwable { + String text = "Hi world!"; + onView(withId(R.id.textview)).perform(replaceText(text)); + onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0)); + + TextView tv = mActivity.findViewById(R.id.textview); + Editor editor = tv.getEditorForTesting(); + + // Simulate a tap-and-drag gesture. + long event1Time = 1001; + MotionEvent event1 = downEvent(event1Time, event1Time, 5f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1)); + assertFalse(editor.getInsertionController().isCursorBeingModified()); + assertFalse(editor.getSelectionController().isCursorBeingModified()); + + long event2Time = 1002; + MotionEvent event2 = moveEvent(event1Time, event2Time, 50f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2)); + assertTrue(editor.getInsertionController().isCursorBeingModified()); + assertFalse(editor.getSelectionController().isCursorBeingModified()); + + long event3Time = 1003; + MotionEvent event3 = moveEvent(event1Time, event3Time, 100f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3)); + assertTrue(editor.getInsertionController().isCursorBeingModified()); + assertFalse(editor.getSelectionController().isCursorBeingModified()); + + long event4Time = 2004; + MotionEvent event4 = upEvent(event1Time, event4Time, 100f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event4)); + assertFalse(editor.getInsertionController().isCursorBeingModified()); + assertFalse(editor.getSelectionController().isCursorBeingModified()); + + // Simulate a quick tap after the drag, near the location where the drag ended. + long event5Time = 2005; + MotionEvent event5 = downEvent(event5Time, event5Time, 90f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event5)); + assertFalse(editor.getInsertionController().isCursorBeingModified()); + assertFalse(editor.getSelectionController().isCursorBeingModified()); + + long event6Time = 2006; + MotionEvent event6 = upEvent(event5Time, event6Time, 90f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event6)); + assertFalse(editor.getInsertionController().isCursorBeingModified()); + assertFalse(editor.getSelectionController().isCursorBeingModified()); + + // Simulate another quick tap in the same location; now selection should be triggered. + long event7Time = 2007; + MotionEvent event7 = downEvent(event7Time, event7Time, 90f, 10f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event7)); + assertFalse(editor.getInsertionController().isCursorBeingModified()); + assertTrue(editor.getSelectionController().isCursorBeingModified()); + } + + @Test public void testEditor_onTouchEvent_cursorDrag() throws Throwable { String text = "testEditor_onTouchEvent_cursorDrag"; onView(withId(R.id.textview)).perform(replaceText(text)); @@ -237,29 +292,25 @@ public class EditorCursorDragTest { // Simulate a tap-and-drag gesture. This should trigger a cursor drag. long event1Time = 1001; MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event1)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); long event2Time = 1002; MotionEvent event2 = moveEvent(event1Time, event2Time, 21f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event2)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); long event3Time = 1003; - MotionEvent event3 = moveEvent(event3Time, event3Time, 120f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event3)); - mInstrumentation.waitForIdleSync(); + MotionEvent event3 = moveEvent(event1Time, event3Time, 120f, 30f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3)); assertTrue(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); long event4Time = 1004; - MotionEvent event4 = upEvent(event3Time, event4Time, 120f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event4)); - mInstrumentation.waitForIdleSync(); + MotionEvent event4 = upEvent(event1Time, event4Time, 120f, 30f); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event4)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); } @@ -276,36 +327,31 @@ public class EditorCursorDragTest { // Simulate a double-tap followed by a drag. This should trigger a selection drag. long event1Time = 1001; MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event1)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); long event2Time = 1002; MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event2)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); long event3Time = 1003; MotionEvent event3 = downEvent(event3Time, event3Time, 20f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event3)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertTrue(editor.getSelectionController().isCursorBeingModified()); long event4Time = 1004; MotionEvent event4 = moveEvent(event3Time, event4Time, 120f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event4)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event4)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertTrue(editor.getSelectionController().isCursorBeingModified()); long event5Time = 1005; MotionEvent event5 = upEvent(event3Time, event5Time, 120f, 30f); - mActivity.runOnUiThread(() -> editor.onTouchEvent(event5)); - mInstrumentation.waitForIdleSync(); + mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event5)); assertFalse(editor.getInsertionController().isCursorBeingModified()); assertFalse(editor.getSelectionController().isCursorBeingModified()); } diff --git a/core/tests/coretests/src/android/widget/EditorTouchStateTest.java b/core/tests/coretests/src/android/widget/EditorTouchStateTest.java index 6adb1b8fa0d6..215d0b800074 100644 --- a/core/tests/coretests/src/android/widget/EditorTouchStateTest.java +++ b/core/tests/coretests/src/android/widget/EditorTouchStateTest.java @@ -120,6 +120,60 @@ public class EditorTouchStateTest { } @Test + public void testUpdate_doubleTap_delayAfterFirstDownEvent() throws Exception { + // Simulate an ACTION_DOWN event. + long event1Time = 1000; + MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f); + mTouchState.update(event1, mConfig); + assertSingleTap(mTouchState, 20f, 30f, 0, 0, false); + + // Simulate an ACTION_UP event with a delay that's longer than the double-tap timeout. + long event2Time = 1000 + ViewConfiguration.getDoubleTapTimeout() + 1; + MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f); + mTouchState.update(event2, mConfig); + assertSingleTap(mTouchState, 20f, 30f, 20f, 30f, false); + + // Generate an ACTION_DOWN event whose time is within the double-tap timeout when + // calculated from the last ACTION_UP event time. Even though the time between the last up + // and this down event is within the double-tap timeout, this should not be considered a + // double-tap (since the first down event had a longer delay). + long event3Time = event2Time + 1; + MotionEvent event3 = downEvent(event3Time, event3Time, 22f, 33f); + mTouchState.update(event3, mConfig); + assertSingleTap(mTouchState, 22f, 33f, 20f, 30f, false); + } + + @Test + public void testUpdate_quickTapAfterDrag() throws Exception { + // Simulate an ACTION_DOWN event. + long event1Time = 1000; + MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f); + mTouchState.update(event1, mConfig); + assertSingleTap(mTouchState, 20f, 30f, 0, 0, false); + + // Simulate an ACTION_MOVE event. + long event2Time = 1001; + MotionEvent event2 = moveEvent(event1Time, event2Time, 200f, 31f); + mTouchState.update(event2, mConfig); + assertSingleTap(mTouchState, 20f, 30f, 0, 0, true); + + // Simulate an ACTION_UP event with a delay that's longer than the double-tap timeout. + long event3Time = 5000; + MotionEvent event3 = upEvent(event1Time, event3Time, 200f, 31f); + mTouchState.update(event3, mConfig); + assertSingleTap(mTouchState, 20f, 30f, 200f, 31f, false); + + // Generate an ACTION_DOWN event whose time is within the double-tap timeout when + // calculated from the last ACTION_UP event time. Even though the time between the last up + // and this down event is within the double-tap timeout, this should not be considered a + // double-tap (since the first down event had a longer delay). + long event4Time = event3Time + 1; + MotionEvent event4 = downEvent(event4Time, event4Time, 200f, 31f); + mTouchState.update(event4, mConfig); + assertSingleTap(mTouchState, 200f, 31f, 200f, 31f, false); + } + + @Test public void testUpdate_tripleClick_mouse() throws Exception { // Simulate an ACTION_DOWN event. long event1Time = 1000; diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 11dc013af6bc..35a885f46919 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -457,7 +457,10 @@ void SkiaPipeline::renderFrameImpl(const SkRect& clip, const Rect& contentDrawBounds, SkCanvas* canvas, const SkMatrix& preTransform) { SkAutoCanvasRestore saver(canvas, true); - canvas->androidFramework_setDeviceClipRestriction(preTransform.mapRect(clip).roundOut()); + auto clipRestriction = preTransform.mapRect(clip).roundOut(); + canvas->androidFramework_setDeviceClipRestriction(clipRestriction); + canvas->drawAnnotation(SkRect::Make(clipRestriction), "AndroidDeviceClipRestriction", + nullptr); canvas->concat(preTransform); // STOPSHIP: Revert, temporary workaround to clear always F16 frame buffer for b/74976293 diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp index 1aebeaf1e7e8..26c7f8d709e7 100644 --- a/native/graphics/jni/bitmap.cpp +++ b/native/graphics/jni/bitmap.cpp @@ -16,6 +16,7 @@ #include <android/bitmap.h> #include <android/graphics/bitmap.h> +#include <android/data_space.h> int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, AndroidBitmapInfo* info) { @@ -29,6 +30,15 @@ int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, return ANDROID_BITMAP_RESULT_SUCCESS; } +int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) { + if (NULL == env || NULL == jbitmap) { + return ADATASPACE_UNKNOWN; // Or return a real error? + } + + android::graphics::Bitmap bitmap(env, jbitmap); + return bitmap.getDataSpace(); +} + int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) { if (NULL == env || NULL == jbitmap) { return ANDROID_BITMAP_RESULT_BAD_PARAMETER; diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt index a601d8af2830..6adb95520d6c 100644 --- a/native/graphics/jni/libjnigraphics.map.txt +++ b/native/graphics/jni/libjnigraphics.map.txt @@ -1,6 +1,7 @@ LIBJNIGRAPHICS { global: AndroidBitmap_getInfo; + AndroidBitmap_getDataSpace; AndroidBitmap_lockPixels; AndroidBitmap_unlockPixels; local: diff --git a/packages/SystemUI/docs/broadcasts.md b/packages/SystemUI/docs/broadcasts.md index 56a637fe588c..28657f28e53b 100644 --- a/packages/SystemUI/docs/broadcasts.md +++ b/packages/SystemUI/docs/broadcasts.md @@ -42,24 +42,29 @@ Acquire the dispatcher by using `@Inject` to obtain a `BroadcastDispatcher`. The ```kotlin /** - * Register a receiver for broadcast with the dispatcher - * - * @param receiver A receiver to dispatch the [Intent] - * @param filter A filter to determine what broadcasts should be dispatched to this receiver. - * It will only take into account actions and categories for filtering. It must - * have at least one action. - * @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the - * main handler. Pass `null` to use the default. - * @param user A user handle to determine which broadcast should be dispatched to this receiver. - * By default, it is the current user. - * @throws IllegalArgumentException if the filter has other constraints that are not actions or - * categories or the filter has no actions. - */ + * Register a receiver for broadcast with the dispatcher + * + * @param receiver A receiver to dispatch the [Intent] + * @param filter A filter to determine what broadcasts should be dispatched to this receiver. + * It will only take into account actions and categories for filtering. It must + * have at least one action. + * @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an + * executor in the main thread (default). + * @param user A user handle to determine which broadcast should be dispatched to this receiver. + * By default, it is the current user. + * @throws IllegalArgumentException if the filter has other constraints that are not actions or + * categories or the filter has no actions. + */ @JvmOverloads -fun registerReceiver(BroadcastReceiver, IntentFilter, Handler? = mainHandler, UserHandle = context.user) +fun registerReceiver( + BroadcastReceiver, + IntentFilter, + Executor? = context.mainExecutor, + UserHandle = context.user +) { ``` -All subscriptions are done with the same overloaded method. As specified in the doc, in order to pass a `UserHandle` with the default `Handler`, pass `null` for the `Handler`. +All subscriptions are done with the same overloaded method. As specified in the doc, in order to pass a `UserHandle` with the default `Executor`, pass `null` for the `Executor`. In the same way as with `Context`, subscribing the same `BroadcastReceiver` for the same user using different filters will result on two subscriptions, not in replacing the filter. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 431862f1cc11..a58e3d78bb08 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1638,7 +1638,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); - broadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, mHandler); + broadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, mHandler); final IntentFilter allUserFilter = new IntentFilter(); allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED); @@ -1649,8 +1649,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab allUserFilter.addAction(ACTION_USER_UNLOCKED); allUserFilter.addAction(ACTION_USER_STOPPED); allUserFilter.addAction(ACTION_USER_REMOVED); - broadcastDispatcher.registerReceiver(mBroadcastAllReceiver, allUserFilter, mHandler, - UserHandle.ALL); + broadcastDispatcher.registerReceiverWithHandler(mBroadcastAllReceiver, allUserFilter, + mHandler, UserHandle.ALL); mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); try { diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 0e736dcd11a8..c533755c76da 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -266,7 +266,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_SWITCHED); - mBroadcastDispatcher.registerReceiver(mIntentReceiver, filter, mHandler); + mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler); mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt index 8cb0cc5db1d3..cedf7c354ccc 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.IntentFilter import android.os.Handler +import android.os.HandlerExecutor import android.os.Looper import android.os.Message import android.os.UserHandle @@ -32,13 +33,14 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import java.io.FileDescriptor import java.io.PrintWriter +import java.util.concurrent.Executor import javax.inject.Inject import javax.inject.Singleton data class ReceiverData( val receiver: BroadcastReceiver, val filter: IntentFilter, - val handler: Handler, + val executor: Executor, val user: UserHandle ) @@ -76,24 +78,49 @@ open class BroadcastDispatcher @Inject constructor ( * @param filter A filter to determine what broadcasts should be dispatched to this receiver. * It will only take into account actions and categories for filtering. It must * have at least one action. - * @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the - * main handler. Pass `null` to use the default. + * @param handler A handler to dispatch [BroadcastReceiver.onReceive]. * @param user A user handle to determine which broadcast should be dispatched to this receiver. * By default, it is the current user. * @throws IllegalArgumentException if the filter has other constraints that are not actions or * categories or the filter has no actions. */ + @Deprecated(message = "Replacing Handler for Executor in SystemUI", + replaceWith = ReplaceWith("registerReceiver(receiver, filter, executor, user)")) @JvmOverloads - fun registerReceiver( + fun registerReceiverWithHandler( receiver: BroadcastReceiver, filter: IntentFilter, - handler: Handler? = mainHandler, + handler: Handler, user: UserHandle = context.user ) { + registerReceiver(receiver, filter, HandlerExecutor(handler), user) + } + + /** + * Register a receiver for broadcast with the dispatcher + * + * @param receiver A receiver to dispatch the [Intent] + * @param filter A filter to determine what broadcasts should be dispatched to this receiver. + * It will only take into account actions and categories for filtering. It must + * have at least one action. + * @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an + * executor in the main thread (default). + * @param user A user handle to determine which broadcast should be dispatched to this receiver. + * By default, it is the current user. + * @throws IllegalArgumentException if the filter has other constraints that are not actions or + * categories or the filter has no actions. + */ + @JvmOverloads + fun registerReceiver( + receiver: BroadcastReceiver, + filter: IntentFilter, + executor: Executor? = context.mainExecutor, + user: UserHandle = context.user + ) { checkFilter(filter) this.handler .obtainMessage(MSG_ADD_RECEIVER, - ReceiverData(receiver, filter, handler ?: mainHandler, user)) + ReceiverData(receiver, filter, executor ?: context.mainExecutor, user)) .sendToTarget() } diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt index b2942bb14c6b..0c631aacab82 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt @@ -193,7 +193,7 @@ class UserBroadcastDispatcher( it.filter.hasAction(intent.action) && it.filter.matchCategories(intent.categories) == null } ?.forEach { - it.handler.post { + it.executor.execute { if (DEBUG) Log.w(TAG, "[$index] Dispatching ${intent.action} to ${it.receiver}") it.receiver.pendingResult = pendingResult diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index c9faf69cfd6f..4e887262659e 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -91,7 +91,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi if (mDebuggable) { IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_AOD_BRIGHTNESS); - mBroadcastDispatcher.registerReceiver(this, filter, handler, UserHandle.ALL); + mBroadcastDispatcher.registerReceiverWithHandler(this, filter, handler, UserHandle.ALL); } } diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 59ac329e1983..48750fa5e769 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -233,7 +233,7 @@ public class PowerUI extends SystemUI implements CommandQueue.Callbacks { filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_SWITCHED); - mBroadcastDispatcher.registerReceiver(this, filter, mHandler); + mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java index bbff117c6f81..ad79cadcc12d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java @@ -322,7 +322,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); try { mUserReceiverRegistered.set(true); - mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser); + mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler, mUser); } catch (Exception ex) { mUserReceiverRegistered.set(false); Log.e(TAG, "Could not register unlock receiver", ex); diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java index 077d2602e43f..9599d77bf65a 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java +++ b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java @@ -98,7 +98,8 @@ public abstract class CurrentUserTracker { if (!mReceiverRegistered) { mCurrentUserId = ActivityManager.getCurrentUser(); IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); - mBroadcastDispatcher.registerReceiver(this, filter, null, UserHandle.ALL); + mBroadcastDispatcher.registerReceiver(this, filter, null, + UserHandle.ALL); mReceiverRegistered = true; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index a3b1b5f8360b..a6842badc153 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -366,8 +366,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_SWITCHED); - mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, Handler.getMain(), - UserHandle.ALL); + mBroadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, + Handler.getMain(), UserHandle.ALL); notifyNavigationBarScreenOn(); mOverviewProxyService.addCallback(mOverviewProxyListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 5b34aa7781c1..00e38f814dff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -179,7 +179,7 @@ public class PhoneStatusBarPolicy filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); - broadcastDispatcher.registerReceiver(mIntentReceiver, filter, mHandler); + broadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler); // listen for user / profile change. try { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index ddacc3aedce0..4f0af9e166c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -188,7 +188,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C // NOTE: This receiver could run before this method returns, as it's not dispatching // on the main thread and BroadcastDispatcher may not need to register with Context. // The receiver will return immediately if the view does not have a Handler yet. - mBroadcastDispatcher.registerReceiver(mIntentReceiver, filter, + mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, Dependency.get(Dependency.TIME_TICK_HANDLER), UserHandle.ALL); Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS, StatusBarIconController.ICON_BLACKLIST); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java index 2e26711a3578..b4c154aa28cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java @@ -96,7 +96,7 @@ public class DateView extends TextView { filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); filter.addAction(Intent.ACTION_LOCALE_CHANGED); - mBroadcastDispatcher.registerReceiver(mIntentReceiver, filter, + mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, Dependency.get(Dependency.TIME_TICK_HANDLER)); updateClock(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java index 570f153a62c0..cb40d7752f53 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java @@ -79,7 +79,8 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio IntentFilter filter = new IntentFilter(); filter.addAction(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION); filter.addAction(LocationManager.MODE_CHANGED_ACTION); - mBroadcastDispatcher.registerReceiver(this, filter, new Handler(bgLooper), UserHandle.ALL); + mBroadcastDispatcher.registerReceiverWithHandler(this, filter, + new Handler(bgLooper), UserHandle.ALL); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mStatusBarManager diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index f640d039ad31..679fa7e2b016 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -326,7 +326,7 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); - mBroadcastDispatcher.registerReceiver(this, filter, mReceiverHandler); + mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; updateMobileControllers(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index 019ef3bca709..312c4ac75bfa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -126,7 +126,8 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi IntentFilter filter = new IntentFilter(); filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED); filter.addAction(Intent.ACTION_USER_UNLOCKED); - broadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, bgHandler, UserHandle.ALL); + broadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, bgHandler, + UserHandle.ALL); // TODO: re-register network callback on user change. mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index 7758aba52918..31b9952afe94 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -88,7 +88,7 @@ public class ThemeOverlayController extends SystemUI { final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); - mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() { + mBroadcastDispatcher.registerReceiverWithHandler(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added."); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index a4ed31d95b2b..112ae6f3758a 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -1008,7 +1008,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - mBroadcastDispatcher.registerReceiver(this, filter, mWorker); + mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mWorker); } public void destroy() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 0c22aaeaafb9..2e0fb3bc850d 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -150,10 +150,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testReceiversRegistered() { - verify(mBroadcastDispatcher, atLeastOnce()).registerReceiver( + verify(mBroadcastDispatcher, atLeastOnce()).registerReceiverWithHandler( eq(mKeyguardUpdateMonitor.mBroadcastReceiver), any(IntentFilter.class), any(Handler.class)); - verify(mBroadcastDispatcher, atLeastOnce()).registerReceiver( + verify(mBroadcastDispatcher, atLeastOnce()).registerReceiverWithHandler( eq(mKeyguardUpdateMonitor.mBroadcastAllReceiver), any(IntentFilter.class), any(Handler.class), eq(UserHandle.ALL)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt index 42fbf59fef44..22b18373e81d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt @@ -27,6 +27,8 @@ import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert.assertSame import org.junit.Before import org.junit.Test @@ -39,6 +41,7 @@ import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import java.util.concurrent.Executor @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper @@ -73,6 +76,8 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Mock private lateinit var mockHandler: Handler + private lateinit var executor: Executor + @Captor private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData> @@ -83,6 +88,7 @@ class BroadcastDispatcherTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) + executor = FakeExecutor(FakeSystemClock()) broadcastDispatcher = TestBroadcastDispatcher( mockContext, @@ -98,8 +104,9 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testAddingReceiverToCorrectUBR() { - broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user0) - broadcastDispatcher.registerReceiver( + broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, + mockHandler, user0) + broadcastDispatcher.registerReceiverWithHandler( broadcastReceiverOther, intentFilterOther, mockHandler, user1) testableLooper.processAllMessages() @@ -115,9 +122,29 @@ class BroadcastDispatcherTest : SysuiTestCase() { } @Test + fun testAddingReceiverToCorrectUBR_executor() { + broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, executor, user0) + broadcastDispatcher.registerReceiver( + broadcastReceiverOther, intentFilterOther, executor, user1) + + testableLooper.processAllMessages() + + verify(mockUBRUser0).registerReceiver(capture(argumentCaptor)) + + assertSame(broadcastReceiver, argumentCaptor.value.receiver) + assertSame(intentFilter, argumentCaptor.value.filter) + + verify(mockUBRUser1).registerReceiver(capture(argumentCaptor)) + assertSame(broadcastReceiverOther, argumentCaptor.value.receiver) + assertSame(intentFilterOther, argumentCaptor.value.filter) + } + + @Test fun testRemovingReceiversRemovesFromAllUBR() { - broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user0) - broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user1) + broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, + mockHandler, user0) + broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, + mockHandler, user1) broadcastDispatcher.unregisterReceiver(broadcastReceiver) @@ -129,8 +156,10 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testRemoveReceiverFromUser() { - broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user0) - broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user1) + broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, + mockHandler, user0) + broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, + mockHandler, user1) broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user0) @@ -143,8 +172,8 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testRegisterCurrentAsActualUser() { setUserMock(mockContext, user1) - broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, - UserHandle.CURRENT) + broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, + mockHandler, UserHandle.CURRENT) testableLooper.processAllMessages() diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt index 21ed15517752..7821ae29592e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt @@ -26,6 +26,8 @@ import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue @@ -69,8 +71,6 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { @Mock private lateinit var mockContext: Context @Mock - private lateinit var mockHandler: Handler - @Mock private lateinit var mPendingResult: BroadcastReceiver.PendingResult @Captor @@ -81,12 +81,14 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { private lateinit var intentFilter: IntentFilter private lateinit var intentFilterOther: IntentFilter private lateinit var handler: Handler + private lateinit var fakeExecutor: FakeExecutor @Before fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) handler = Handler(testableLooper.looper) + fakeExecutor = FakeExecutor(FakeSystemClock()) userBroadcastDispatcher = UserBroadcastDispatcher( mockContext, USER_ID, handler, testableLooper.looper) @@ -108,7 +110,7 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) testableLooper.processAllMessages() assertTrue(userBroadcastDispatcher.isRegistered()) @@ -128,7 +130,7 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) testableLooper.processAllMessages() reset(mockContext) @@ -151,9 +153,9 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { } userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiverOther, intentFilterOther, mockHandler, USER_HANDLE)) + ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE)) testableLooper.processAllMessages() assertTrue(userBroadcastDispatcher.isRegistered()) @@ -179,14 +181,15 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { intentFilterOther = IntentFilter(ACTION_2) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE)) + ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE)) val intent = Intent(ACTION_2) userBroadcastDispatcher.onReceive(mockContext, intent) testableLooper.processAllMessages() + fakeExecutor.runAllReady() verify(broadcastReceiver, never()).onReceive(any(), any()) verify(broadcastReceiverOther).onReceive(mockContext, intent) @@ -198,14 +201,15 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { intentFilterOther = IntentFilter(ACTION_2) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilterOther, handler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilterOther, fakeExecutor, USER_HANDLE)) val intent = Intent(ACTION_2) userBroadcastDispatcher.onReceive(mockContext, intent) testableLooper.processAllMessages() + fakeExecutor.runAllReady() verify(broadcastReceiver).onReceive(mockContext, intent) } @@ -218,14 +222,15 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { intentFilterOther.addCategory(CATEGORY_2) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE)) + ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE)) val intent = Intent(ACTION_1) userBroadcastDispatcher.onReceive(mockContext, intent) testableLooper.processAllMessages() + fakeExecutor.runAllReady() verify(broadcastReceiver).onReceive(mockContext, intent) verify(broadcastReceiverOther).onReceive(mockContext, intent) @@ -235,12 +240,13 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { fun testPendingResult() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) val intent = Intent(ACTION_1) userBroadcastDispatcher.onReceive(mockContext, intent) testableLooper.processAllMessages() + fakeExecutor.runAllReady() verify(broadcastReceiver).onReceive(mockContext, intent) verify(broadcastReceiver).pendingResult = mPendingResult @@ -250,15 +256,16 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { fun testRemoveReceiverReferences() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE)) + ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)) intentFilterOther = IntentFilter(ACTION_1) intentFilterOther.addAction(ACTION_2) userBroadcastDispatcher.registerReceiver( - ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE)) + ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE)) userBroadcastDispatcher.unregisterReceiver(broadcastReceiver) testableLooper.processAllMessages() + fakeExecutor.runAllReady() assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index 167f361b341a..548da8e1f2aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -110,7 +110,7 @@ public class PowerUITest extends SysuiTestCase { @Test public void testReceiverIsRegisteredToDispatcherOnStart() { mPowerUI.start(); - verify(mBroadcastDispatcher).registerReceiver( + verify(mBroadcastDispatcher).registerReceiverWithHandler( any(BroadcastReceiver.class), any(IntentFilter.class), any(Handler.class)); //PowerUI does not call with User diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java index 39afbe0a1a23..8f645b6bd3c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java @@ -190,7 +190,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { mFragments.dispatchResume(); processAllMessages(); - verify(mBroadcastDispatcher).registerReceiver( + verify(mBroadcastDispatcher).registerReceiverWithHandler( any(BroadcastReceiver.class), any(IntentFilter.class), any(Handler.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java index 2854665aedb1..80aa6f6c49bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java @@ -69,7 +69,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { @Test public void testRegisteredWithDispatcher() { - verify(mBroadcastDispatcher).registerReceiver(any(BroadcastReceiver.class), + verify(mBroadcastDispatcher).registerReceiverWithHandler(any(BroadcastReceiver.class), any(IntentFilter.class), any(Handler.class)); // VolumeDialogControllerImpl does not call with user } diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 797b713d8614..d297f3f84189 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -123,4 +123,5 @@ android_app { use_embedded_native_libs: true, // The permission configuration *must* be included to ensure security of the device required: ["NetworkPermissionConfig"], + apex_available: ["com.android.tethering"], } diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index 5785707cb9c5..264ce440f59f 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -47,6 +47,16 @@ java_library { libs: [ "android_system_stubs_current", ], + + hostdex: true, // for hiddenapi check + visibility: [ + "//frameworks/base/packages/Tethering:__subpackages__", + //TODO(b/147200698) remove below lines when the platform is built with stubs + "//frameworks/base", + "//frameworks/base/services", + "//frameworks/base/services/core", + ], + apex_available: ["com.android.tethering"], } filegroup { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 3bce322a7655..d45a54e0ff28 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -1452,6 +1452,11 @@ public class BackupManagerService extends IBackupManager.Stub { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) { return; } + dumpWithoutCheckingPermission(fd, pw, args); + } + + @VisibleForTesting + void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) { int userId = binderGetCallingUserId(); if (!isUserReadyForBackup(userId)) { pw.println("Inactive"); @@ -1460,7 +1465,16 @@ public class BackupManagerService extends IBackupManager.Stub { if (args != null) { for (String arg : args) { - if ("users".equals(arg.toLowerCase())) { + if ("-h".equals(arg)) { + pw.println("'dumpsys backup' optional arguments:"); + pw.println(" -h : this help text"); + pw.println(" a[gents] : dump information about defined backup agents"); + pw.println(" transportclients : dump information about transport clients"); + pw.println(" transportstats : dump transport statts"); + pw.println(" users : dump the list of users for which backup service " + + "is running"); + return; + } else if ("users".equals(arg.toLowerCase())) { pw.print(DUMP_RUNNING_USERS_MESSAGE); for (int i = 0; i < mUserServices.size(); i++) { pw.print(" " + mUserServices.keyAt(i)); @@ -1471,11 +1485,12 @@ public class BackupManagerService extends IBackupManager.Stub { } } - UserBackupManagerService userBackupManagerService = - getServiceForUserIfCallerHasPermission(UserHandle.USER_SYSTEM, "dump()"); - - if (userBackupManagerService != null) { - userBackupManagerService.dump(fd, pw, args); + for (int i = 0; i < mUserServices.size(); i++) { + UserBackupManagerService userBackupManagerService = + getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()"); + if (userBackupManagerService != null) { + userBackupManagerService.dump(fd, pw, args); + } } } diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 064cd060528d..7b95ab526b41 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -3545,14 +3545,7 @@ public class UserBackupManagerService { try { if (args != null) { for (String arg : args) { - if ("-h".equals(arg)) { - pw.println("'dumpsys backup' optional arguments:"); - pw.println(" -h : this help text"); - pw.println(" a[gents] : dump information about defined backup agents"); - pw.println(" users : dump the list of users for which backup service " - + "is running"); - return; - } else if ("agents".startsWith(arg)) { + if ("agents".startsWith(arg)) { dumpAgents(pw); return; } else if ("transportclients".equals(arg.toLowerCase())) { @@ -3583,8 +3576,10 @@ public class UserBackupManagerService { } private void dumpInternal(PrintWriter pw) { + // Add prefix for only non-system users so that system user dumpsys is the same as before + String userPrefix = mUserId == UserHandle.USER_SYSTEM ? "" : "User " + mUserId + ":"; synchronized (mQueueLock) { - pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled") + pw.println(userPrefix + "Backup Manager is " + (mEnabled ? "enabled" : "disabled") + " / " + (!mSetupComplete ? "not " : "") + "setup complete / " + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init"); pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled")); @@ -3594,13 +3589,13 @@ public class UserBackupManagerService { + " (now = " + System.currentTimeMillis() + ')'); pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled(mUserId)); - pw.println("Transport whitelist:"); + pw.println(userPrefix + "Transport whitelist:"); for (ComponentName transport : mTransportManager.getTransportWhitelist()) { pw.print(" "); pw.println(transport.flattenToShortString()); } - pw.println("Available transports:"); + pw.println(userPrefix + "Available transports:"); final String[] transports = listAllTransports(); if (transports != null) { for (String t : transports) { @@ -3626,18 +3621,18 @@ public class UserBackupManagerService { mTransportManager.dumpTransportClients(pw); - pw.println("Pending init: " + mPendingInits.size()); + pw.println(userPrefix + "Pending init: " + mPendingInits.size()); for (String s : mPendingInits) { pw.println(" " + s); } - pw.print("Ancestral: "); + pw.print(userPrefix + "Ancestral: "); pw.println(Long.toHexString(mAncestralToken)); - pw.print("Current: "); + pw.print(userPrefix + "Current: "); pw.println(Long.toHexString(mCurrentToken)); int numPackages = mBackupParticipants.size(); - pw.println("Participants:"); + pw.println(userPrefix + "Participants:"); for (int i = 0; i < numPackages; i++) { int uid = mBackupParticipants.keyAt(i); pw.print(" uid: "); @@ -3648,7 +3643,7 @@ public class UserBackupManagerService { } } - pw.println("Ancestral packages: " + pw.println(userPrefix + "Ancestral packages: " + (mAncestralPackages == null ? "none" : mAncestralPackages.size())); if (mAncestralPackages != null) { for (String pkg : mAncestralPackages) { @@ -3657,17 +3652,17 @@ public class UserBackupManagerService { } Set<String> processedPackages = mProcessedPackagesJournal.getPackagesCopy(); - pw.println("Ever backed up: " + processedPackages.size()); + pw.println(userPrefix + "Ever backed up: " + processedPackages.size()); for (String pkg : processedPackages) { pw.println(" " + pkg); } - pw.println("Pending key/value backup: " + mPendingBackups.size()); + pw.println(userPrefix + "Pending key/value backup: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.println(" " + req); } - pw.println("Full backup queue:" + mFullBackupQueue.size()); + pw.println(userPrefix + "Full backup queue:" + mFullBackupQueue.size()); for (FullBackupEntry entry : mFullBackupQueue) { pw.print(" "); pw.print(entry.lastBackup); diff --git a/services/core/java/com/android/server/notification/OWNERS b/services/core/java/com/android/server/notification/OWNERS new file mode 100644 index 000000000000..5a19656b36a6 --- /dev/null +++ b/services/core/java/com/android/server/notification/OWNERS @@ -0,0 +1,4 @@ +dsandler@android.com +juliacr@google.com +beverlyt@google.com +pixel@google.com diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a9571d97200c..b26e6c7021c1 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -19380,7 +19380,7 @@ public class PackageManagerService extends IPackageManager.Stub // PermissionController manages default home directly. return false; } - mPermissionManager.setDefaultHome(currentPackageName, userId, (successful) -> { + mPermissionManager.setDefaultHome(packageName, userId, (successful) -> { if (successful) { postPreferredActivityChangedBroadcast(userId); } diff --git a/services/net/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java index 61cd88aac921..c93e5c5e4759 100644 --- a/services/net/java/android/net/ip/IpClientCallbacks.java +++ b/services/net/java/android/net/ip/IpClientCallbacks.java @@ -17,6 +17,7 @@ package android.net.ip; import android.net.DhcpResults; +import android.net.DhcpResultsParcelable; import android.net.Layer2PacketParcelable; import android.net.LinkProperties; @@ -69,6 +70,18 @@ public class IpClientCallbacks { public void onNewDhcpResults(DhcpResults dhcpResults) {} /** + * Callback called when new DHCP results are available. + * + * <p>This is purely advisory and not an indication of provisioning success or failure. This is + * only here for callers that want to expose DHCPv4 results to other APIs + * (e.g., WifiInfo#setInetAddress). + * + * <p>DHCPv4 or static IPv4 configuration failure or success can be determined by whether or not + * the passed-in DhcpResults object is null. + */ + public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {} + + /** * Indicates that provisioning was successful. */ public void onProvisioningSuccess(LinkProperties newLp) {} diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java index 4d60e6239376..7f723b1c232b 100644 --- a/services/net/java/android/net/ip/IpClientUtil.java +++ b/services/net/java/android/net/ip/IpClientUtil.java @@ -119,6 +119,7 @@ public class IpClientUtil { @Override public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { mCb.onNewDhcpResults(fromStableParcelable(dhcpResults)); + mCb.onNewDhcpResults(dhcpResults); } @Override diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java index 8632ca4c2898..8b2f15c2babb 100644 --- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java +++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java @@ -81,7 +81,10 @@ import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowPackageManager; import java.io.File; +import java.io.FileDescriptor; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.List; /** @@ -1238,13 +1241,49 @@ public class UserBackupManagerServiceTest { assertThat(service.getAncestralSerialNumber()).isEqualTo(testSerialNumber2); } + /** + * Test that {@link UserBackupManagerService#dump()} for system user does not prefix dump with + * "User 0:". + */ + @Test + public void testDump_forSystemUser_DoesNotHaveUserPrefix() throws Exception { + mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); + UserBackupManagerService service = + BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks( + UserHandle.USER_SYSTEM, + mContext, + mBackupThread, + mBaseStateDir, + mDataDir, + mTransportManager); + + StringWriter dump = new StringWriter(); + service.dump(new FileDescriptor(), new PrintWriter(dump), new String[0]); + + assertThat(dump.toString()).startsWith("Backup Manager is "); + } + + /** + * Test that {@link UserBackupManagerService#dump()} for non-system user prefixes dump with + * "User <userid>:". + */ + @Test + public void testDump_forNonSystemUser_HasUserPrefix() throws Exception { + mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); + UserBackupManagerService service = createUserBackupManagerServiceAndRunTasks(); + + StringWriter dump = new StringWriter(); + service.dump(new FileDescriptor(), new PrintWriter(dump), new String[0]); + + assertThat(dump.toString()).startsWith("User " + USER_ID + ":" + "Backup Manager is "); + } + private File createTestFile() throws IOException { File testFile = new File(mContext.getFilesDir(), "test"); testFile.createNewFile(); return testFile; } - /** * We can't mock the void method {@link #schedule(Context, long, BackupManagerConstants)} so we * extend {@link ShadowKeyValueBackupJob} and throw an exception at the end of the method. diff --git a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java index 2326dfda7e12..d44476ed971d 100644 --- a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java @@ -27,6 +27,7 @@ import static junit.framework.Assert.fail; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -59,6 +60,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -83,6 +85,8 @@ public class BackupManagerServiceTest { @Mock private UserBackupManagerService mUserBackupManagerService; @Mock + private UserBackupManagerService mNonSystemUserBackupManagerService; + @Mock private Context mContextMock; @Mock private PrintWriter mPrintWriterMock; @@ -105,7 +109,7 @@ public class BackupManagerServiceTest { mUserServices = new SparseArray<>(); mUserServices.append(UserHandle.USER_SYSTEM, mUserBackupManagerService); - mUserServices.append(NON_USER_SYSTEM, mUserBackupManagerService); + mUserServices.append(NON_USER_SYSTEM, mNonSystemUserBackupManagerService); when(mUserManagerMock.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(mUserInfoMock); when(mUserManagerMock.getUserInfo(NON_USER_SYSTEM)).thenReturn(mUserInfoMock); @@ -512,6 +516,26 @@ public class BackupManagerServiceTest { mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]); verifyNoMoreInteractions(mUserBackupManagerService); + verifyNoMoreInteractions(mNonSystemUserBackupManagerService); + } + + /** + * Test that {@link BackupManagerService#dump()} dumps system user information before non-system + * user information. + */ + + @Test + public void testDump_systemUserFirst() { + String[] args = new String[0]; + mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args); + + InOrder inOrder = + inOrder(mUserBackupManagerService, mNonSystemUserBackupManagerService); + inOrder.verify(mUserBackupManagerService) + .dump(mFileDescriptorStub, mPrintWriterMock, args); + inOrder.verify(mNonSystemUserBackupManagerService) + .dump(mFileDescriptorStub, mPrintWriterMock, args); + inOrder.verifyNoMoreInteractions(); } @Test diff --git a/wifi/Android.bp b/wifi/Android.bp index 09d5386dcfc5..180368cbd9f7 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -67,10 +67,15 @@ java_library { optimize: { enabled: false }, + hostdex: true, // for hiddenapi check visibility: [ "//frameworks/base", // TODO(b/140299412) remove once all dependencies are fixed "//frameworks/opt/net/wifi/service:__subpackages__", ] + test_access_hidden_api_whitelist, + apex_available: [ + "com.android.wifi", + "test_com.android.wifi", + ], plugins: ["java_api_finder"], } |