From 3c4315bf311b7ee6c4cbf164995f41777fff48ed Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Mon, 15 Apr 2019 16:14:51 +0100 Subject: [PATCH 001/182] Ensure all fields of AutoBufferPointer are initialized In the process of revising libnativehelper interface, the initialization of the fArray field was dropped. This change fixes this and adds regression tests. In writing the tests, it became apparent that the AutoBufferPointer destructor would crash if the underlying buffer was heap array backed and the buffer position was non-zero. ReleasePrimitiveArrayCritical was called with the element corresponding to the current position rather than the first element. Bug: b/130390512 Test: atest FrameworksCoreTests:android.graphics.BitmapTest Change-Id: I319512aaede7ba8af5d013c9281417695abf9099 (cherry picked from commit e522c99430ec9ee0b4daa588dbcaea4824bc3f70) --- core/jni/android_nio_utils.cpp | 37 ++++++---- core/jni/android_nio_utils.h | 9 +-- .../src/android/graphics/BitmapTest.java | 72 +++++++++++++++++++ 3 files changed, 100 insertions(+), 18 deletions(-) diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp index 19a1c7212fae0..a62dd7c4048fd 100644 --- a/core/jni/android_nio_utils.cpp +++ b/core/jni/android_nio_utils.cpp @@ -18,42 +18,51 @@ #include "core_jni_helpers.h" -void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) { - assert(array); +namespace { +void* getPointer(JNIEnv *_env, jobject buffer, jarray *array, void** elements) { + assert(array); jint position; jint limit; jint elementSizeShift; jlong pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift); if (pointer != 0L) { + *array = nullptr; + *elements = nullptr; pointer += position << elementSizeShift; return reinterpret_cast(pointer); } - jint offset = jniGetNioBufferBaseArrayOffset(_env, buffer); *array = jniGetNioBufferBaseArray(_env, buffer); - void * data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0); - return reinterpret_cast(reinterpret_cast(data) + offset); + *elements = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0); + return reinterpret_cast(reinterpret_cast(*elements) + offset); } +void releasePointer(JNIEnv *_env, jarray array, void *elements, jboolean commit) { + _env->ReleasePrimitiveArrayCritical(array, elements, commit ? 0 : JNI_ABORT); +} -void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data, - jboolean commit) { - _env->ReleasePrimitiveArrayCritical(array, data, - commit ? 0 : JNI_ABORT); +} // namespace + +void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) { + void* elements; + return getPointer(_env, buffer, array, &elements); +} + +void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) { + releasePointer(_env, array, data, commit); } /////////////////////////////////////////////////////////////////////////////// -android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, - jboolean commit) { +android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit) { fEnv = env; fCommit = commit; - fPointer = android::nio_getPointer(env, nioBuffer, &fArray); + fPointer = getPointer(env, nioBuffer, &fArray, &fElements); } android::AutoBufferPointer::~AutoBufferPointer() { - if (NULL != fArray) { - android::nio_releasePointer(fEnv, fArray, fPointer, fCommit); + if (nullptr != fArray) { + releasePointer(fEnv, fArray, fElements, fCommit); } } diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h index c634cb9177196..7c9acd2638daa 100644 --- a/core/jni/android_nio_utils.h +++ b/core/jni/android_nio_utils.h @@ -20,7 +20,7 @@ #include namespace android { - + /** * Given an nio.Buffer, return a pointer to it, beginning at its current * position. The returned pointer is only valid for the current JNI stack-frame. @@ -63,9 +63,10 @@ public: private: JNIEnv* fEnv; - void* fPointer; - jarray fArray; - jboolean fCommit; + void* fPointer; // pointer to current buffer position. + void* fElements; // pointer to array element 0 (may be directly in fArray or a copy). + jarray fArray; // pointer to array on managed heap. + jboolean fCommit; // commit data to source if required (when fElements is a copy of fArray). }; } /* namespace android */ diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java index d2a1dd9a7b5cb..4bee24385cc59 100644 --- a/core/tests/coretests/src/android/graphics/BitmapTest.java +++ b/core/tests/coretests/src/android/graphics/BitmapTest.java @@ -22,6 +22,8 @@ import androidx.test.filters.SmallTest; import junit.framework.TestCase; +import java.nio.ByteBuffer; + public class BitmapTest extends TestCase { @SmallTest @@ -262,4 +264,74 @@ public class BitmapTest extends TestCase { assertFalse(hardwareBitmap.isMutable()); assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), hardwareBitmap.getColorSpace()); } + + @SmallTest + public void testCopyWithDirectBuffer() { + // Initialize Bitmap + final int width = 2; + final int height = 2; + Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2); + + // Copy bytes to direct buffer, buffer is padded by fixed amount (pad bytes) either side + // of bitmap. + final int pad = 1; + final byte padValue = 0x5a; + final int bufferSize = pad + width * height * 2 + pad; + ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize); + + // Write padding + directBuffer.put(0, padValue); + directBuffer.put(directBuffer.limit() - 1, padValue); + + // Copy bitmap + directBuffer.position(pad); + bm1.copyPixelsToBuffer(directBuffer); + assertEquals(directBuffer.position(), pad + width * height * 2); + + // Check padding + assertEquals(directBuffer.get(0), padValue); + assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue); + + // Create bitmap from direct buffer and check match. + directBuffer.position(pad); + Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + bm2.copyPixelsFromBuffer(directBuffer); + assertTrue(bm2.sameAs(bm1)); + } + + @SmallTest + public void testCopyWithHeapBuffer() { + // Initialize Bitmap + final int width = 2; + final int height = 2; + Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2); + + // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side + // of bitmap. + final int pad = 1; + final byte padValue = 0x5a; + final int bufferSize = pad + width * height * 2 + pad; + ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize); + + // Write padding + heapBuffer.put(0, padValue); + heapBuffer.put(heapBuffer.limit() - 1, padValue); + + // Copy bitmap + heapBuffer.position(pad); + bm1.copyPixelsToBuffer(heapBuffer); + assertEquals(heapBuffer.position(), pad + width * height * 2); + + // Check padding + assertEquals(heapBuffer.get(0), padValue); + assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue); + + // Create bitmap from heap buffer and check match. + heapBuffer.position(pad); + Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + bm2.copyPixelsFromBuffer(heapBuffer); + assertTrue(bm2.sameAs(bm1)); + } } From 7e28b54dc9f8e2cb6269ecfa172482adc375248b Mon Sep 17 00:00:00 2001 From: Winson Date: Fri, 12 Apr 2019 16:19:26 -0700 Subject: [PATCH 002/182] Skip idmap1 generation if target defines overlayable Since idmap1 can't enforce policy restrictions, we can't allow it to generate an idmap that might get used. Migrating to idmap2 is too difficult for now as it requires a lot of PackageManager infrastructure to validate policies, and none of that is available during manifest parsing, which is where idmap1 is currently used. Bug: b/130260055 Test: manual test BT issue from b/130260055 Test: manual test app with test overlay toggling Activity enabled Change-Id: I5e7e321d27aab9be360a5e8be77d804ad3f66336 (cherry picked from commit 6597302f570e37efbef5d86291d41073003ebe5b) --- libs/androidfw/ResourceTypes.cpp | 14 +++++++++++++- libs/androidfw/include/androidfw/ResourceTypes.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 11e4cb835d65b..c3bfcfe4d9f26 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -3460,6 +3460,7 @@ struct ResTable::Header const uint8_t* dataEnd; size_t index; int32_t cookie; + bool definesOverlayable = false; ResStringPool values; uint32_t* resourceIDMap; @@ -6559,7 +6560,7 @@ status_t ResTable::getEntry( } status_t ResTable::parsePackage(const ResTable_package* const pkg, - const Header* const header, bool appAsLib, bool isSystemAsset) + Header* const header, bool appAsLib, bool isSystemAsset) { const uint8_t* base = (const uint8_t*)pkg; status_t err = validate_chunk(&pkg->header, sizeof(*pkg) - sizeof(pkg->typeIdOffset), @@ -6861,6 +6862,10 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, ALOGW("Found multiple library tables, ignoring..."); } } else { + if (ctype == RES_TABLE_OVERLAYABLE_TYPE) { + header->definesOverlayable = true; + } + status_t err = validate_chunk(chunk, sizeof(ResChunk_header), endPos, "ResTable_package:unknown"); if (err != NO_ERROR) { @@ -7138,6 +7143,13 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, return UNKNOWN_ERROR; } + for (auto header : targetResTable.mHeaders) { + // Idmap is not aware of overlayable, exit since policy checks can't be done + if (header->definesOverlayable) { + return UNKNOWN_ERROR; + } + } + const ResTable_package* targetPackageStruct = targetResTable.mPackageGroups[0]->packages[0]->package; const size_t tmpNameSize = arraysize(targetPackageStruct->name); diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 875b90b7ac653..086b688179de1 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -2106,7 +2106,7 @@ private: size_t nameLen, uint32_t* outTypeSpecFlags) const; status_t parsePackage( - const ResTable_package* const pkg, const Header* const header, + const ResTable_package* const pkg, Header* const header, bool appAsLib, bool isSystemAsset); void print_value(const Package* pkg, const Res_value& value) const; From bf92e74a259b8c080a5b5829cea5a7c385357749 Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Mon, 15 Apr 2019 22:13:59 +0100 Subject: [PATCH 003/182] Retire unused android::nio_{get,release}Buffer functions Removes unused functions nio_getBuffer and nio_releaseBuffer. Motivated by the observation that nio_releaseBuffer() is not sound for java.nio.Buffer instances backed by heap arrays when the buffer position is non-zero. Adds doc comments to AutoBufferPointer that is used in the framework. Bug: b/130390512 Test: m -j100 Change-Id: I01fb72ed71d46a4ef8c7d3da82319ea57e391dbd (cherry picked from commit bd1e15613db24406c322f8890ab7fcff449d417c) --- core/jni/android_nio_utils.cpp | 18 +++------ core/jni/android_nio_utils.h | 67 ++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp index a62dd7c4048fd..ee6f26c4bf1e5 100644 --- a/core/jni/android_nio_utils.cpp +++ b/core/jni/android_nio_utils.cpp @@ -21,7 +21,6 @@ namespace { void* getPointer(JNIEnv *_env, jobject buffer, jarray *array, void** elements) { - assert(array); jint position; jint limit; jint elementSizeShift; @@ -44,25 +43,18 @@ void releasePointer(JNIEnv *_env, jarray array, void *elements, jboolean commit) } // namespace -void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) { - void* elements; - return getPointer(_env, buffer, array, &elements); -} +namespace android { -void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) { - releasePointer(_env, array, data, commit); -} - -/////////////////////////////////////////////////////////////////////////////// - -android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit) { +AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit) { fEnv = env; fCommit = commit; fPointer = getPointer(env, nioBuffer, &fArray, &fElements); } -android::AutoBufferPointer::~AutoBufferPointer() { +AutoBufferPointer::~AutoBufferPointer() { if (nullptr != fArray) { releasePointer(fEnv, fArray, fElements, fCommit); } } + +} // namespace android diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h index 7c9acd2638daa..586e6db58cde1 100644 --- a/core/jni/android_nio_utils.h +++ b/core/jni/android_nio_utils.h @@ -22,51 +22,54 @@ namespace android { /** - * Given an nio.Buffer, return a pointer to it, beginning at its current - * position. The returned pointer is only valid for the current JNI stack-frame. - * For performance, it does not create any global references, so the getPointer - * (and releasePointer if array is returned non-null) must be done in the - * same JNI stack-frame. + * Class providing scoped access to the memory backing a java.nio.Buffer instance. * - * @param env The current JNI env - * @param buffer The nio.Buffer object - * @param array REQUIRED. Output. If on return it is set to non-null, then - * nio_releasePointer must be called with the array - * and the returned pointer when the caller is through with it. - * If on return it is set to null, do not call - * nio_releasePointer. - * @return The pointer to the memory in the buffer object - */ -void* nio_getPointer(JNIEnv *env, jobject buffer, jarray *array); - -/** - * Call this if android_nio_getPointer returned non-null in its array parameter. - * Pass that array and the returned pointer when you are done accessing the - * pointer. If called (i.e. array is non-null), it must be called in the same - * JNI stack-frame as getPointer + * Instances of this class should only be allocated on the stack as heap allocation is not + * supported. * - * @param env The current JNI env - * @param buffer The array returned from android_nio_getPointer (!= null) - * @param pointer The pointer returned by android_nio_getPointer - * @param commit JNI_FALSE if the pointer was just read, and JNI_TRUE if - * the pointer was written to. + * Instances of this class do not create any global references for performance reasons. */ -void nio_releasePointer(JNIEnv *env, jarray array, void *pointer, - jboolean commit); - -class AutoBufferPointer { +class AutoBufferPointer final { public: + /** Constructor for an AutoBufferPointer instance. + * + * @param env The current JNI env + * @param nioBuffer Instance of a java.nio.Buffer whose memory will be accessed. + * @param commit JNI_TRUE if the underlying memory will be updated and should be + * copied back to the managed heap. JNI_FALSE if the data will + * not be modified or the modifications may be discarded. + * + * The commit parameter is only applicable if the buffer is backed by a managed heap + * array and the runtime had to provide a copy of the data rather than the original data. + */ AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit); + ~AutoBufferPointer(); + /** + * Returns a pointer to the current position of the buffer provided to the constructor. This + * pointer is only valid whilst the AutoBufferPointer instance remains in scope. + */ void* pointer() const { return fPointer; } private: JNIEnv* fEnv; - void* fPointer; // pointer to current buffer position. - void* fElements; // pointer to array element 0 (may be directly in fArray or a copy). + void* fPointer; // pointer to current buffer position when constructed. + void* fElements; // pointer to array element 0 (null if buffer is direct, may be within fArray + // or point to a copy of the array). jarray fArray; // pointer to array on managed heap. jboolean fCommit; // commit data to source if required (when fElements is a copy of fArray). + + // Unsupported constructors and operators. + AutoBufferPointer() = delete; + AutoBufferPointer(AutoBufferPointer&) = delete; + AutoBufferPointer& operator=(AutoBufferPointer&) = delete; + static void* operator new(std::size_t); + static void* operator new[](std::size_t); + static void* operator new(std::size_t, void*); + static void* operator new[](std::size_t, void*); + static void operator delete(void*, std::size_t); + static void operator delete[](void*, std::size_t); }; } /* namespace android */ From 2aedb72bde815a6ef9d65246232294c26ea3b567 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 20 May 2019 23:21:48 +0000 Subject: [PATCH 004/182] Revert "Use the SubId in the TM.getNetworkType if Valid" This reverts commit f36fee3cf764838aa8b1f59142e82049e4cbacb1. Reason for revert: 133129040 Bug: 133129040 Merged-In: I9a974018d4155426b1050a4b80b82f4bf4a9d996 Change-Id: Ib6f9a4e461a7e1cfa6c4648bd289a8f92475423e (cherry picked from commit af62adcb6c328ef682237ec027793fc8e27782d5) --- .../android/telephony/TelephonyManager.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a628babc11322..3536561f0d81a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2449,7 +2449,21 @@ public class TelephonyManager { * @return the NETWORK_TYPE_xxxx for current data connection. */ public @NetworkType int getNetworkType() { - return getDataNetworkType(); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getNetworkType(); + } else { + // This can happen when the ITelephony interface is not up yet. + return NETWORK_TYPE_UNKNOWN; + } + } catch(RemoteException ex) { + // This shouldn't happen in the normal case + return NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return NETWORK_TYPE_UNKNOWN; + } } /** @@ -2480,9 +2494,23 @@ public class TelephonyManager { * @hide */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + @UnsupportedAppUsage public int getNetworkType(int subId) { - return getDataNetworkType(subId); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName()); + } else { + // This can happen when the ITelephony interface is not up yet. + return NETWORK_TYPE_UNKNOWN; + } + } catch (RemoteException ex) { + // This shouldn't happen in the normal case + return NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return NETWORK_TYPE_UNKNOWN; + } } /** From e34e99db64a891aa1cda74966a49cc771926ec6b Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 19 Jun 2019 11:39:20 -0700 Subject: [PATCH 005/182] Revert SurfaceView back to Q's version Revert API behavior changes to SurfaceView, snapping back to Q's version. Bug: 133378280 Test: none Change-Id: I3a47f9bfdfab2d16707f952a9af672551736e681 (cherry picked from commit 5866a0c6aba39dda1a775abaf92ecacee715c89a) --- core/java/android/view/SurfaceView.java | 42 ------------------------- 1 file changed, 42 deletions(-) diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 4891b43c829e9..17e83ca364bd2 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -27,7 +27,6 @@ import android.content.res.Configuration; import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.HardwareRenderer; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff; @@ -203,29 +202,6 @@ public class SurfaceView extends View private SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction(); - /** - * A callback which reflects an alpha value of this view onto the underlying surfaces. - * - *

Note: This doesn't have to be defined as a member variable, - * but can be defined as an inline lambda when calling ViewRootImpl#registerRtFrameCallback(). - * However when we do so, the callback is triggered only for a few times and stops working for - * some reason. It's suspected that there is a problem around garbage collection, and until - * the cause is fixed, we will keep this callback in a member variable.

- */ - private HardwareRenderer.FrameDrawingCallback mSetSurfaceAlphaCallback = frame -> { - final ViewRootImpl viewRoot = getViewRootImpl(); - if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) { - // In this case, the alpha value is reflected on the screen in #updateSurface() later. - return; - } - - final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - t.setAlpha(mSurfaceControl, getAlpha()); - t.deferTransactionUntilSurface(mSurfaceControl, viewRoot.mSurface, frame); - t.setEarlyWakeup(); - t.apply(); - }; - public SurfaceView(Context context) { this(context, null); } @@ -324,17 +300,6 @@ public class SurfaceView extends View updateSurface(); } - @Override - public void setAlpha(float alpha) { - super.setAlpha(alpha); - final ViewRootImpl viewRoot = getViewRootImpl(); - if (viewRoot == null) { - return; - } - viewRoot.registerRtFrameCallback(mSetSurfaceAlphaCallback); - invalidate(); - } - private void performDrawFinished() { if (mPendingReportDraws > 0) { mDrawFinished = true; @@ -709,13 +674,6 @@ public class SurfaceView extends View } updateBackgroundVisibilityInTransaction(viewRoot.getSurfaceControl()); - // Alpha value change is handled in setAlpha() directly using a local - // transaction. However it can happen that setAlpha() is called while - // local transactions cannot be applied, so the value is stored in a View - // but not yet reflected on the Surface. - mSurfaceControl.setAlpha(getAlpha()); - mBackgroundControl.setAlpha(getAlpha()); - // While creating the surface, we will set it's initial // geometry. Outside of that though, we should generally // leave it to the RenderThread. From 4ef6b6d1f3b6d4a8770525adeee842519d283039 Mon Sep 17 00:00:00 2001 From: Beth Thibodeau Date: Tue, 30 Jul 2019 12:22:34 -0400 Subject: [PATCH 006/182] Adding null checks Fixes: 138638813 Test: manual, atest NotificationMediaTemplateViewWrapperTest Change-Id: Ib74cf6109e4ee7e8a353f5537b566e50130bc403 (cherry picked from commit ce92d3370cb853214c0eedec3784e67f905d576c) --- .../com/android/internal/widget/MediaNotificationView.java | 6 ++++-- .../row/wrapper/NotificationMediaTemplateViewWrapper.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java index 0d87afa42e3eb..9bb45012b61a3 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -175,8 +175,10 @@ public class MediaNotificationView extends FrameLayout { @Override public void onVisibilityAggregated(boolean isVisible) { super.onVisibilityAggregated(isVisible); - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onAggregatedVisibilityChanged(isVisible); + if (mListeners != null) { + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onAggregatedVisibilityChanged(isVisible); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 38f9bff2a63f9..e499814aa5b83 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -95,7 +95,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi @Override public void onAggregatedVisibilityChanged(boolean isVisible) { mIsViewVisible = isVisible; - if (isVisible) { + if (isVisible && mMediaController != null) { // Restart timer if we're currently playing and didn't already have one going PlaybackState state = mMediaController.getPlaybackState(); if (state != null && state.getState() == PlaybackState.STATE_PLAYING From 974aca31a9400032b38618f4453028322cb1adc3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Wed, 21 Aug 2019 10:38:24 -0700 Subject: [PATCH 007/182] WifiManager: Return dummy values when wifi service is not up Many system/vendor modules assume that wifi service is up by the time they run. This is no longer the case since wifi stack now starts a little later in the bootup sequence (to support pluggable wifi stack module for mainline). If any of these modules invoke a WifiManager call, a) Return an appropriate dummy value if the API returns a value b) Raise a RemoteException if the API returns nothing (void). Bug: 139492857 Bug: 137650946 Test: Verified that SUW & CNE receiver no longer crashes with the stack traces in the linked bugs. Also, verified that SUW still can connect to wifi networks & detect when wifi auto-connects after SUW comes up. Test: Verified wifi/softap toggle from Settings/Sysui. Change-Id: Ia100a4612fc903ae470a0c89523d4fda27eb3fbc (cherry picked from commit dfb747ef8dc8ddced934ffa1d5e4b2897ad6bc20) --- wifi/java/android/net/wifi/WifiManager.java | 416 +++++++++++++++----- 1 file changed, 327 insertions(+), 89 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index ca65736d8ec27..e9c24cd6e3e09 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -70,7 +70,6 @@ import java.lang.ref.WeakReference; import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -1170,15 +1169,16 @@ public class WifiManager { updateVerboseLoggingEnabledFromService(); } - private IWifiManager getIWifiManager() throws RemoteException { + private IWifiManager getIWifiManager() { if (mService == null) { synchronized (this) { mService = IWifiManager.Stub.asInterface( ServiceManager.getService(Context.WIFI_SERVICE)); - if (mService == null) { - throw new RemoteException("Wifi Service not running"); + if (mService != null) { + updateVerboseLoggingEnabledFromService(); + } else { + Log.e(TAG, "Wifi Service not running yet, ignoring WifiManager API call"); } - updateVerboseLoggingEnabledFromService(); } } return mService; @@ -1223,8 +1223,10 @@ public class WifiManager { @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) public List getConfiguredNetworks() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); ParceledListSlice parceledList = - getIWifiManager().getConfiguredNetworks(mContext.getOpPackageName()); + iWifiManager.getConfiguredNetworks(mContext.getOpPackageName()); if (parceledList == null) { return Collections.emptyList(); } @@ -1239,8 +1241,10 @@ public class WifiManager { @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL}) public List getPrivilegedConfiguredNetworks() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); ParceledListSlice parceledList = - getIWifiManager().getPrivilegedConfiguredNetworks(mContext.getOpPackageName()); + iWifiManager.getPrivilegedConfiguredNetworks(mContext.getOpPackageName()); if (parceledList == null) { return Collections.emptyList(); } @@ -1271,14 +1275,16 @@ public class WifiManager { @NonNull List scanResults) { List>>> configs = new ArrayList<>(); try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); Map>> results = - getIWifiManager().getAllMatchingFqdnsForScanResults( + iWifiManager.getAllMatchingFqdnsForScanResults( scanResults); if (results.isEmpty()) { return configs; } List wifiConfigurations = - getIWifiManager().getWifiConfigsForPasspointProfiles( + iWifiManager.getWifiConfigsForPasspointProfiles( new ArrayList<>(results.keySet())); for (WifiConfiguration configuration : wifiConfigurations) { Map> scanResultsPerNetworkType = results.get( @@ -1313,10 +1319,12 @@ public class WifiManager { public Map> getMatchingOsuProviders( @Nullable List scanResults) { if (scanResults == null) { - return new HashMap<>(); + return Collections.emptyMap(); } try { - return getIWifiManager().getMatchingOsuProviders(scanResults); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyMap(); + return iWifiManager.getMatchingOsuProviders(scanResults); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1343,7 +1351,9 @@ public class WifiManager { public Map getMatchingPasspointConfigsForOsuProviders( @NonNull Set osuProviders) { try { - return getIWifiManager().getMatchingPasspointConfigsForOsuProviders( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyMap(); + return iWifiManager.getMatchingPasspointConfigsForOsuProviders( new ArrayList<>(osuProviders)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1428,7 +1438,9 @@ public class WifiManager { */ private int addOrUpdateNetwork(WifiConfiguration config) { try { - return getIWifiManager().addOrUpdateNetwork(config, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return -1; + return iWifiManager.addOrUpdateNetwork(config, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1654,7 +1666,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); Binder binder = new Binder(); try { - getIWifiManager().registerNetworkRequestMatchCallback( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.registerNetworkRequestMatchCallback( binder, new NetworkRequestMatchCallbackProxy(looper, callback), callback.hashCode()); } catch (RemoteException e) { @@ -1680,7 +1696,11 @@ public class WifiManager { Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); try { - getIWifiManager().unregisterNetworkRequestMatchCallback(callback.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.unregisterNetworkRequestMatchCallback(callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1714,7 +1734,9 @@ public class WifiManager { public @NetworkSuggestionsStatusCode int addNetworkSuggestions( @NonNull List networkSuggestions) { try { - return getIWifiManager().addNetworkSuggestions( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; + return iWifiManager.addNetworkSuggestions( networkSuggestions, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1738,7 +1760,9 @@ public class WifiManager { public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( @NonNull List networkSuggestions) { try { - return getIWifiManager().removeNetworkSuggestions( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; + return iWifiManager.removeNetworkSuggestions( networkSuggestions, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1754,7 +1778,9 @@ public class WifiManager { @RequiresPermission(ACCESS_WIFI_STATE) public @NonNull List getNetworkSuggestions() { try { - return mService.getNetworkSuggestions(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); + return iWifiManager.getNetworkSuggestions(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -1784,7 +1810,11 @@ public class WifiManager { */ public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { try { - if (!getIWifiManager().addOrUpdatePasspointConfiguration( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + if (!iWifiManager.addOrUpdatePasspointConfiguration( config, mContext.getOpPackageName())) { throw new IllegalArgumentException(); } @@ -1808,7 +1838,11 @@ public class WifiManager { }) public void removePasspointConfiguration(String fqdn) { try { - if (!getIWifiManager().removePasspointConfiguration( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + if (!iWifiManager.removePasspointConfiguration( fqdn, mContext.getOpPackageName())) { throw new IllegalArgumentException(); } @@ -1832,7 +1866,9 @@ public class WifiManager { }) public List getPasspointConfigurations() { try { - return getIWifiManager().getPasspointConfigurations(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) Collections.emptyList(); + return iWifiManager.getPasspointConfigurations(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1852,7 +1888,11 @@ public class WifiManager { */ public void queryPasspointIcon(long bssid, String fileName) { try { - getIWifiManager().queryPasspointIcon(bssid, fileName); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.queryPasspointIcon(bssid, fileName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1866,7 +1906,9 @@ public class WifiManager { */ public int matchProviderWithCurrentNetwork(String fqdn) { try { - return getIWifiManager().matchProviderWithCurrentNetwork(fqdn); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return -1; + return iWifiManager.matchProviderWithCurrentNetwork(fqdn); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1880,7 +1922,11 @@ public class WifiManager { */ public void deauthenticateNetwork(long holdoff, boolean ess) { try { - getIWifiManager().deauthenticateNetwork(holdoff, ess); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.deauthenticateNetwork(holdoff, ess); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1910,7 +1956,9 @@ public class WifiManager { @Deprecated public boolean removeNetwork(int netId) { try { - return getIWifiManager().removeNetwork(netId, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.removeNetwork(netId, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1965,7 +2013,9 @@ public class WifiManager { boolean success; try { - success = getIWifiManager().enableNetwork( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + success = iWifiManager.enableNetwork( netId, attemptConnect, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2002,7 +2052,9 @@ public class WifiManager { @Deprecated public boolean disableNetwork(int netId) { try { - return getIWifiManager().disableNetwork(netId, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.disableNetwork(netId, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2025,7 +2077,9 @@ public class WifiManager { @Deprecated public boolean disconnect() { try { - return getIWifiManager().disconnect(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.disconnect(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2049,7 +2103,9 @@ public class WifiManager { @Deprecated public boolean reconnect() { try { - return getIWifiManager().reconnect(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.reconnect(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2073,7 +2129,9 @@ public class WifiManager { @Deprecated public boolean reassociate() { try { - return getIWifiManager().reassociate(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.reassociate(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2159,7 +2217,9 @@ public class WifiManager { private long getSupportedFeatures() { try { - return getIWifiManager().getSupportedFeatures(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return 0L; + return iWifiManager.getSupportedFeatures(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2289,8 +2349,10 @@ public class WifiManager { */ public WifiActivityEnergyInfo getControllerActivityEnergyInfo() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; synchronized(this) { - return getIWifiManager().reportActivityInfo(); + return iWifiManager.reportActivityInfo(); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2329,8 +2391,10 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(WorkSource workSource) { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; String packageName = mContext.getOpPackageName(); - return getIWifiManager().startScan(packageName); + return iWifiManager.startScan(packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2359,7 +2423,9 @@ public class WifiManager { */ public WifiInfo getConnectionInfo() { try { - return getIWifiManager().getConnectionInfo(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getConnectionInfo(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2373,7 +2439,9 @@ public class WifiManager { */ public List getScanResults() { try { - return getIWifiManager().getScanResults(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); + return iWifiManager.getScanResults(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2392,7 +2460,9 @@ public class WifiManager { @Deprecated public boolean isScanAlwaysAvailable() { try { - return getIWifiManager().isScanAlwaysAvailable(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.isScanAlwaysAvailable(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2423,7 +2493,11 @@ public class WifiManager { */ public void setCountryCode(@NonNull String country) { try { - getIWifiManager().setCountryCode(country); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.setCountryCode(country); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2438,7 +2512,9 @@ public class WifiManager { @UnsupportedAppUsage public String getCountryCode() { try { - String country = getIWifiManager().getCountryCode(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + String country = iWifiManager.getCountryCode(); return country; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2453,7 +2529,9 @@ public class WifiManager { @UnsupportedAppUsage public boolean isDualBandSupported() { try { - return getIWifiManager().isDualBandSupported(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.isDualBandSupported(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2466,7 +2544,9 @@ public class WifiManager { */ public boolean isDualModeSupported() { try { - return getIWifiManager().needs5GHzToAnyApBandConversion(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.needs5GHzToAnyApBandConversion(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2479,7 +2559,9 @@ public class WifiManager { */ public DhcpInfo getDhcpInfo() { try { - return getIWifiManager().getDhcpInfo(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getDhcpInfo(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2506,7 +2588,9 @@ public class WifiManager { @Deprecated public boolean setWifiEnabled(boolean enabled) { try { - return getIWifiManager().setWifiEnabled(mContext.getOpPackageName(), enabled); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.setWifiEnabled(mContext.getOpPackageName(), enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2521,7 +2605,9 @@ public class WifiManager { */ public int getWifiState() { try { - return getIWifiManager().getWifiEnabledState(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return WIFI_STATE_UNKNOWN; + return iWifiManager.getWifiEnabledState(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2595,7 +2681,11 @@ public class WifiManager { */ public void updateInterfaceIpState(String ifaceName, int mode) { try { - getIWifiManager().updateInterfaceIpState(ifaceName, mode); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.updateInterfaceIpState(ifaceName, mode); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2613,7 +2703,9 @@ public class WifiManager { */ public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { try { - return getIWifiManager().startSoftAp(wifiConfig); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.startSoftAp(wifiConfig); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2628,7 +2720,9 @@ public class WifiManager { */ public boolean stopSoftAp() { try { - return getIWifiManager().stopSoftAp(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.stopSoftAp(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2696,8 +2790,12 @@ public class WifiManager { LocalOnlyHotspotCallbackProxy proxy = new LocalOnlyHotspotCallbackProxy(this, looper, callback); try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } String packageName = mContext.getOpPackageName(); - int returnCode = getIWifiManager().startLocalOnlyHotspot( + int returnCode = iWifiManager.startLocalOnlyHotspot( proxy.getMessenger(), new Binder(), packageName); if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { // Send message to the proxy to make sure we call back on the correct thread @@ -2749,7 +2847,11 @@ public class WifiManager { } mLOHSCallbackProxy = null; try { - getIWifiManager().stopLocalOnlyHotspot(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.stopLocalOnlyHotspot(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2779,7 +2881,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); mLOHSObserverProxy = new LocalOnlyHotspotObserverProxy(this, looper, observer); try { - getIWifiManager().startWatchLocalOnlyHotspot( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startWatchLocalOnlyHotspot( mLOHSObserverProxy.getMessenger(), new Binder()); mLOHSObserverProxy.registered(); } catch (RemoteException e) { @@ -2803,7 +2909,11 @@ public class WifiManager { } mLOHSObserverProxy = null; try { - getIWifiManager().stopWatchLocalOnlyHotspot(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.stopWatchLocalOnlyHotspot(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2823,7 +2933,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState() { try { - return getIWifiManager().getWifiApEnabledState(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return WIFI_AP_STATE_FAILED; + return iWifiManager.getWifiApEnabledState(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2852,7 +2964,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public WifiConfiguration getWifiApConfiguration() { try { - return getIWifiManager().getWifiApConfiguration(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getWifiApConfiguration(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2869,7 +2983,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { try { - return getIWifiManager().setWifiApConfiguration( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.setWifiApConfiguration( wifiConfig, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2885,7 +3001,11 @@ public class WifiManager { public void notifyUserOfApBandConversion() { Log.d(TAG, "apBand was converted, notify the user"); try { - getIWifiManager().notifyUserOfApBandConversion(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.notifyUserOfApBandConversion(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2913,7 +3033,11 @@ public class WifiManager { */ public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { try { - getIWifiManager().enableTdls(remoteIPAddress.getHostAddress(), enable); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableTdls(remoteIPAddress.getHostAddress(), enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2927,7 +3051,11 @@ public class WifiManager { */ public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { try { - getIWifiManager().enableTdlsWithMacAddress(remoteMacAddress, enable); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableTdlsWithMacAddress(remoteMacAddress, enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3216,7 +3344,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); Binder binder = new Binder(); try { - getIWifiManager().registerSoftApCallback( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.registerSoftApCallback( binder, new SoftApCallbackProxy(looper, callback), callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -3237,7 +3369,11 @@ public class WifiManager { Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); try { - getIWifiManager().unregisterSoftApCallback(callback.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.unregisterSoftApCallback(callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3807,7 +3943,11 @@ public class WifiManager { public void disableEphemeralNetwork(String SSID) { if (SSID == null) throw new IllegalArgumentException("SSID cannot be null"); try { - getIWifiManager().disableEphemeralNetwork(SSID, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.disableEphemeralNetwork(SSID, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3851,7 +3991,9 @@ public class WifiManager { @UnsupportedAppUsage private Messenger getWifiServiceMessenger() { try { - return getIWifiManager().getWifiServiceMessenger(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getWifiServiceMessenger(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3911,10 +4053,14 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { try { - getIWifiManager().acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); synchronized (WifiManager.this) { if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { - getIWifiManager().releaseWifiLock(mBinder); + iWifiManager.releaseWifiLock(mBinder); throw new UnsupportedOperationException( "Exceeded maximum number of wifi locks"); } @@ -3944,7 +4090,11 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { - getIWifiManager().releaseWifiLock(mBinder); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.releaseWifiLock(mBinder); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -4007,7 +4157,11 @@ public class WifiManager { } if (changed && mHeld) { try { - getIWifiManager().updateWifiLockWorkSource(mBinder, mWorkSource); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.updateWifiLockWorkSource(mBinder, mWorkSource); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4035,7 +4189,11 @@ public class WifiManager { synchronized (mBinder) { if (mHeld) { try { - getIWifiManager().releaseWifiLock(mBinder); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.releaseWifiLock(mBinder); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -4148,10 +4306,14 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { try { - getIWifiManager().acquireMulticastLock(mBinder, mTag); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.acquireMulticastLock(mBinder, mTag); synchronized (WifiManager.this) { if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { - getIWifiManager().releaseMulticastLock(mTag); + iWifiManager.releaseMulticastLock(mTag); throw new UnsupportedOperationException( "Exceeded maximum number of wifi locks"); } @@ -4193,7 +4355,11 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { - getIWifiManager().releaseMulticastLock(mTag); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.releaseMulticastLock(mTag); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -4270,7 +4436,9 @@ public class WifiManager { */ public boolean isMulticastEnabled() { try { - return getIWifiManager().isMulticastEnabled(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.isMulticastEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4283,7 +4451,9 @@ public class WifiManager { @UnsupportedAppUsage public boolean initializeMulticastFiltering() { try { - getIWifiManager().initializeMulticastFiltering(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + iWifiManager.initializeMulticastFiltering(); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4308,7 +4478,11 @@ public class WifiManager { @UnsupportedAppUsage public void enableVerboseLogging (int verbose) { try { - getIWifiManager().enableVerboseLogging(verbose); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableVerboseLogging(verbose); } catch (Exception e) { //ignore any failure here Log.e(TAG, "enableVerboseLogging " + e.toString()); @@ -4323,7 +4497,9 @@ public class WifiManager { @UnsupportedAppUsage public int getVerboseLoggingLevel() { try { - return getIWifiManager().getVerboseLoggingLevel(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return -1; + return iWifiManager.getVerboseLoggingLevel(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4336,7 +4512,11 @@ public class WifiManager { */ public void factoryReset() { try { - getIWifiManager().factoryReset(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.factoryReset(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4350,7 +4530,9 @@ public class WifiManager { @UnsupportedAppUsage public Network getCurrentNetwork() { try { - return getIWifiManager().getCurrentNetwork(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getCurrentNetwork(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4382,7 +4564,11 @@ public class WifiManager { */ public void enableWifiConnectivityManager(boolean enabled) { try { - getIWifiManager().enableWifiConnectivityManager(enabled); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableWifiConnectivityManager(enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4394,7 +4580,9 @@ public class WifiManager { */ public byte[] retrieveBackupData() { try { - return getIWifiManager().retrieveBackupData(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.retrieveBackupData(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4406,7 +4594,11 @@ public class WifiManager { */ public void restoreBackupData(byte[] data) { try { - getIWifiManager().restoreBackupData(data); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.restoreBackupData(data); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4422,7 +4614,11 @@ public class WifiManager { @Deprecated public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { try { - getIWifiManager().restoreSupplicantBackupData(supplicantData, ipConfigData); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.restoreSupplicantBackupData(supplicantData, ipConfigData); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4451,7 +4647,11 @@ public class WifiManager { throw new IllegalArgumentException("callback must not be null"); } try { - getIWifiManager().startSubscriptionProvisioning(provider, + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startSubscriptionProvisioning(provider, new ProvisioningCallbackProxy(executor, callback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4565,7 +4765,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); Binder binder = new Binder(); try { - getIWifiManager().registerTrafficStateCallback( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.registerTrafficStateCallback( binder, new TrafficStateCallbackProxy(looper, callback), callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4585,7 +4789,11 @@ public class WifiManager { Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); try { - getIWifiManager().unregisterTrafficStateCallback(callback.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.unregisterTrafficStateCallback(callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4641,7 +4849,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getFactoryMacAddresses() { try { - return getIWifiManager().getFactoryMacAddresses(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getFactoryMacAddresses(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4710,7 +4920,11 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(@DeviceMobilityState int state) { try { - getIWifiManager().setDeviceMobilityState(state); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.setDeviceMobilityState(state); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4765,7 +4979,11 @@ public class WifiManager { @NonNull EasyConnectStatusCallback callback) { Binder binder = new Binder(); try { - getIWifiManager().startDppAsConfiguratorInitiator( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startDppAsConfiguratorInitiator( binder, enrolleeUri, selectedNetworkId, enrolleeNetworkRole, new EasyConnectCallbackProxy(executor, callback)); } catch (RemoteException e) { @@ -4792,7 +5010,11 @@ public class WifiManager { @NonNull EasyConnectStatusCallback callback) { Binder binder = new Binder(); try { - getIWifiManager().startDppAsEnrolleeInitiator(binder, configuratorUri, + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startDppAsEnrolleeInitiator(binder, configuratorUri, new EasyConnectCallbackProxy(executor, callback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4813,8 +5035,12 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } /* Request lower layers to stop/abort and clear resources */ - getIWifiManager().stopDppSession(); + iWifiManager.stopDppSession(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4913,7 +5139,11 @@ public class WifiManager { Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener); } try { - getIWifiManager().addOnWifiUsabilityStatsListener(new Binder(), + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.addOnWifiUsabilityStatsListener(new Binder(), new IOnWifiUsabilityStatsListener.Stub() { @Override public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, @@ -4950,7 +5180,11 @@ public class WifiManager { Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener); } try { - getIWifiManager().removeOnWifiUsabilityStatsListener(listener.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.removeOnWifiUsabilityStatsListener(listener.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4973,7 +5207,11 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { try { - getIWifiManager().updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } From ad5d0844a6d74358f0a7f0173610634ac655cc00 Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Wed, 28 Aug 2019 10:17:45 +0100 Subject: [PATCH 008/182] Clear calling identity as broadcast needs permission The intent BUGREPORT_REQUESTED is permission protected by the permission "android.permission.TRIGGER_SHELL_BUGREPORT" Test: manually trigger interactive bugreport from power button and Settings Bug: 140158937 Change-Id: Ic82d4a63359c8c2f252fe631d3eb91648c23768e (cherry picked from commit f598710a1af3b7cfea3d3163351d6ff2a94e510f) --- .../com/android/server/am/ActivityManagerService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 775a7dd44f68a..39d6aca385718 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8285,8 +8285,13 @@ public class ActivityManagerService extends IActivityManager.Stub if (shareDescription != null) { triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription); } - // Send broadcast to shell to trigger bugreport using Bugreport API - mContext.sendBroadcast(triggerShellBugreport); + final long identity = Binder.clearCallingIdentity(); + try { + // Send broadcast to shell to trigger bugreport using Bugreport API + mContext.sendBroadcast(triggerShellBugreport); + } finally { + Binder.restoreCallingIdentity(identity); + } } else { SystemProperties.set("dumpstate.options", type); SystemProperties.set("ctl.start", "bugreport"); From 3ff90cea37292fd06445cee251877fdba21cc5e6 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 009/182] Fix regression in updating gesture exclusion rects - Only update the rects when the view visibility changes if there were previously set rects Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 3baffd871c1e1a0b9ab412f4e6a2ba11758c6076) --- core/java/android/view/View.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6ce712061db0a..7c176673bf9b1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14403,7 +14403,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + + // Update the gesture exclusion rects only if they are set + final ListenerInfo info = getListenerInfo(); + if (info != null && info.mSystemGestureExclusionRects != null) { + updateSystemGestureExclusionRects(); + } } /** From 6bb7a719f8cc225bc3e8e6bec22993522d9aa02a Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 010/182] Fix regression in updating gesture exclusion rects - Only update the rects when the view visibility changes if there were previously set rects Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 3baffd871c1e1a0b9ab412f4e6a2ba11758c6076) --- core/java/android/view/View.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6ce712061db0a..7c176673bf9b1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14403,7 +14403,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + + // Update the gesture exclusion rects only if they are set + final ListenerInfo info = getListenerInfo(); + if (info != null && info.mSystemGestureExclusionRects != null) { + updateSystemGestureExclusionRects(); + } } /** From dea939944a1c5e65c301db8836ab1496132dc589 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 011/182] Fix regression in updating gesture exclusion rects - Only update the rects when the view visibility changes if there were previously set rects Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 3baffd871c1e1a0b9ab412f4e6a2ba11758c6076) --- core/java/android/view/View.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6ce712061db0a..7c176673bf9b1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14403,7 +14403,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + + // Update the gesture exclusion rects only if they are set + final ListenerInfo info = getListenerInfo(); + if (info != null && info.mSystemGestureExclusionRects != null) { + updateSystemGestureExclusionRects(); + } } /** From 78ccb4046a43d11551be3c1fa438905cfaf52db1 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 012/182] Fix regression in updating gesture exclusion rects - Use the precalculated aggregate visibility instead of traversing hierarchy again in isShown() Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 05a36465b4dec80a656f0659536d5fc6187f9b0b) --- .../java/android/view/GestureExclusionTracker.java | 4 ++-- core/java/android/view/View.java | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java index fcc14c1967301..fffb323e6d500 100644 --- a/core/java/android/view/GestureExclusionTracker.java +++ b/core/java/android/view/GestureExclusionTracker.java @@ -44,7 +44,7 @@ class GestureExclusionTracker { while (i.hasNext()) { final GestureExclusionViewInfo info = i.next(); final View v = info.getView(); - if (v == null || !v.isAttachedToWindow() || !v.isShown()) { + if (v == null || !v.isAttachedToWindow() || !v.isAggregatedVisible()) { mGestureExclusionViewsChanged = true; i.remove(); continue; @@ -123,7 +123,7 @@ class GestureExclusionTracker { public int update() { final View excludedView = getView(); if (excludedView == null || !excludedView.isAttachedToWindow() - || !excludedView.isShown()) return GONE; + || !excludedView.isAggregatedVisible()) return GONE; final List localRects = excludedView.getSystemGestureExclusionRects(); final List newRects = new ArrayList<>(localRects.size()); for (Rect src : localRects) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6ce712061db0a..8c8b9d34f8763 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14323,6 +14323,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + /** + * @return true if this view and all ancestors are visible as of the last + * {@link #onVisibilityAggregated(boolean)} call. + */ + boolean isAggregatedVisible() { + return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0; + } + /** * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()}, @@ -14351,7 +14359,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @CallSuper public void onVisibilityAggregated(boolean isVisible) { // Update our internal visibility tracking so we can detect changes - boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0; + boolean oldVisible = isAggregatedVisible(); mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE) : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE); if (isVisible && mAttachInfo != null) { @@ -14403,7 +14411,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + if (isVisible != oldVisible) { + updateSystemGestureExclusionRects(); + } } /** From f46f568fa4e717d5e1150fabcb2280d5b8ad6719 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 4 Sep 2019 11:18:46 -0400 Subject: [PATCH 013/182] Fixes regression caused by ag/9259064 Makes sure that onClickListeners are always up to date. Fixes: 139920678 Test: manual Test: atest UserDetailViewAdapterTest (fails on old code) Change-Id: I1060cb432b7e24a46a3472754efdf004798d6b6e (cherry picked from commit 8f571e59547dfb6293b9c24764bdc087c46fc713) --- .../systemui/qs/tiles/UserDetailView.java | 2 +- .../qs/tiles/UserDetailViewAdapterTest.kt | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java index d6dad687e5d47..187a3bdec13fc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -76,7 +76,7 @@ public class UserDetailView extends PseudoGridView { UserSwitcherController.UserRecord item) { UserDetailItemView v = UserDetailItemView.convertOrInflate( mContext, convertView, parent); - if ((v != convertView && !item.isCurrent) || item.isGuest) { + if (!item.isCurrent || item.isGuest) { v.setOnClickListener(this); } else { v.setOnClickListener(null); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt new file mode 100644 index 0000000000000..b51e716591fe4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt @@ -0,0 +1,128 @@ +/* + * 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.qs.tiles + +import android.content.Context +import android.content.pm.UserInfo +import android.graphics.Bitmap +import android.testing.AndroidTestingRunner +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.policy.UserSwitcherController +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class UserDetailViewAdapterTest : SysuiTestCase() { + + @Mock private lateinit var mUserSwitcherController: UserSwitcherController + @Mock private lateinit var mParent: ViewGroup + @Mock private lateinit var mUserDetailItemView: UserDetailItemView + @Mock private lateinit var mOtherView: View + @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView + @Mock private lateinit var mUserInfo: UserInfo + @Mock private lateinit var mPicture: Bitmap + @Mock private lateinit var mLayoutInflater: LayoutInflater + private lateinit var adapter: UserDetailView.Adapter + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater) + `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean())) + .thenReturn(mInflatedUserDetailItemView) + adapter = UserDetailView.Adapter(mContext, mUserSwitcherController) + } + + private fun clickableTest( + current: Boolean, + guest: Boolean, + convertView: View, + shouldBeClickable: Boolean + ) { + val user = createUserRecord(current, guest) + val v = adapter.createUserDetailItemView(convertView, mParent, user) + if (shouldBeClickable) { + verify(v).setOnClickListener(adapter) + } else { + verify(v).setOnClickListener(null) + } + } + + @Test + fun testGuestIsClickable_differentViews_notCurrent() { + clickableTest(false, true, mOtherView, true) + } + + @Test + fun testGuestIsClickable_differentViews_Current() { + clickableTest(true, true, mOtherView, true) + } + + @Test + fun testGuestIsClickable_sameView_notCurrent() { + clickableTest(false, true, mUserDetailItemView, true) + } + + @Test + fun testGuestIsClickable_sameView_Current() { + clickableTest(true, true, mUserDetailItemView, true) + } + + @Test + fun testNotGuestCurrentUserIsNotClickable_otherView() { + clickableTest(true, false, mOtherView, false) + } + + @Test + fun testNotGuestCurrentUserIsNotClickable_sameView() { + clickableTest(true, false, mUserDetailItemView, false) + } + + @Test + fun testNotGuestNotCurrentUserIsClickable_otherView() { + clickableTest(false, false, mOtherView, true) + } + + @Test + fun testNotGuestNotCurrentUserIsClickable_sameView() { + clickableTest(false, false, mUserDetailItemView, true) + } + + private fun createUserRecord(current: Boolean, guest: Boolean) = + UserSwitcherController.UserRecord( + mUserInfo, + mPicture, + guest, + current, + false /* isAddUser */, + false /* isRestricted */, + true /* isSwitchToEnabled */) +} \ No newline at end of file From 4eb63db904cf85c5eb027f0ef9484103ecbcfba5 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Tue, 10 Sep 2019 13:56:37 -0400 Subject: [PATCH 014/182] Remove KeyguardUpdateMonitor.getInstance(). This class is now provided via dependency injection. This fixes the fingerprint sensor. Bug: 140712902 Test: manual. Change-Id: I37f55e946d67e6c7ad443a2110ad4955fdb52894 (cherry picked from commit cd84b099443113805fe36040147e022c63b1b21c) --- .../com/android/keyguard/KeyguardUpdateMonitor.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index b964edf7fc440..720074b0ad731 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -217,8 +217,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private static KeyguardUpdateMonitor sInstance; - private final Context mContext; private final boolean mIsPrimaryUser; HashMap mSimDatas = new HashMap(); @@ -1389,15 +1387,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { Trace.endSection(); } - - /** Provides access to the static instance. */ - public static KeyguardUpdateMonitor getInstance(Context context) { - if (sInstance == null) { - sInstance = new KeyguardUpdateMonitor(context, Looper.getMainLooper()); - } - return sInstance; - } - protected void handleStartedGoingToSleep(int arg1) { checkIsHandlerThread(); mLockIconPressed = false; From b38a669ecb043d601743635f2fbcfa5cde4f5b1e Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Wed, 11 Sep 2019 14:14:45 -0400 Subject: [PATCH 015/182] Ensure that the Application is constructed before any Service. This fixes dependency injection issues and brings Service construction in line with the way that Activities are created. Specifically, this ensures that there is always a reference to a Context available at the time a Service is constructed, such that the Context can then be injected into the constructor of the Service. Bug: 140868981 Test: atest SystemUITests Change-Id: If85e4106fef8c2fd12f7ca9e8b7fd686af62e29b (cherry picked from commit 66d22c8a59836b2e3f22074e358696275ed10ab7) --- core/java/android/app/ActivityThread.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index a6784780d72f9..1cc849936fde4 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3982,25 +3982,15 @@ public final class ActivityThread extends ClientTransactionHandler { LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; - try { - java.lang.ClassLoader cl = packageInfo.getClassLoader(); - service = packageInfo.getAppFactory() - .instantiateService(cl, data.info.name, data.intent); - } catch (Exception e) { - if (!mInstrumentation.onException(service, e)) { - throw new RuntimeException( - "Unable to instantiate service " + data.info.name - + ": " + e.toString(), e); - } - } - try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); ContextImpl context = ContextImpl.createAppContext(this, packageInfo); - context.setOuterContext(service); - Application app = packageInfo.makeApplication(false, mInstrumentation); + java.lang.ClassLoader cl = packageInfo.getClassLoader(); + service = packageInfo.getAppFactory() + .instantiateService(cl, data.info.name, data.intent); + context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); From 780bdd9a0d4c528b2c0a63c7752d90782c4bcdc1 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Fri, 13 Sep 2019 14:35:15 -0400 Subject: [PATCH 016/182] Workaround multiple instance of AppComponentFactory. When a device is newly reformatted, we can end up with multiple instances of AppComponentFactory. We need to ensure they are all injected into properly so that we don't get NPEs. Bug: 140556803 Test: atest SystemUITests && manual Change-Id: Ia2076124b9435a6a8ff6305f4442df8cf7f1034c (cherry picked from commit 66c4c72ba4a79a3f28833744411d5e1387bb4bbc) --- .../systemui/SystemUIAppComponentFactory.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java index e8b5285c26413..3eb330e04381c 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java @@ -21,8 +21,6 @@ import android.app.Service; import android.content.ContentProvider; import android.content.Context; import android.content.Intent; -import android.os.Process; -import android.util.Log; import androidx.annotation.NonNull; import androidx.core.app.AppComponentFactory; @@ -60,9 +58,6 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { SystemUIFactory.createFromConfig(context); SystemUIFactory.getInstance().getRootComponent().inject( SystemUIAppComponentFactory.this); - Log.d(TAG, "Initialized during Application creation in Process " - + Process.myPid() + ", Thread " + Process.myTid()); - Log.d(TAG, "mComponentHelper: " + mComponentHelper); } ); } @@ -83,8 +78,6 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { SystemUIFactory.createFromConfig(context); SystemUIFactory.getInstance().getRootComponent().inject( contentProvider); - Log.d(TAG, "Initialized during ContentProvider creation in Process " - + Process.myPid() + ", Thread " + Process.myTid()); } ); } @@ -98,10 +91,10 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { @NonNull ClassLoader cl, @NonNull String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { if (mComponentHelper == null) { - // Everything is about to crash if this is true, but that is inevitable. We either crash - // here or crash lower in the stack. Better to crash early! - Log.wtf(TAG, "Uninitialized mComponentHelper in Process" + Process.myPid() + ", Thread " - + Process.myTid()); + // This shouldn't happen, but does when a device is freshly formatted. + // Bug filed against framework to take a look: http://b/141008541 + SystemUIFactory.getInstance().getRootComponent().inject( + SystemUIAppComponentFactory.this); } Service service = mComponentHelper.resolveService(className); if (service != null) { From e3c639620090e7404279342d16ca9da9d393f346 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Fri, 20 Sep 2019 07:54:47 -0700 Subject: [PATCH 017/182] Clears calling identity when calling isInstantApp Prior to this change, we were calling the public isInstantApp method without first clearing calling identity from grantEphemeralAccess. As a result, when interactions across user boundaries took place, approved or not, we would encounter this permission failure when simply setting a state in the background. Fixes: 141288362 Test: Work profile setup Change-Id: I2cb8338c2a68bc9c4a61c075398d767980c504ed (cherry picked from commit aa152c4742e6642913293c4d591780e3b66ba1c7) --- .../java/com/android/server/pm/PackageManagerService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index fe3d2c8fa9816..65528895b7b36 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -23391,7 +23391,10 @@ public class PackageManagerService extends IPackageManager.Stub return; } - if (isInstantApp(callingPackage.packageName, userId)) { + final long caller = Binder.clearCallingIdentity(); + final boolean instantApp = isInstantApp(callingPackage.packageName, userId); + Binder.restoreCallingIdentity(caller); + if (instantApp) { mInstantAppRegistry.grantInstantAccessLPw(userId, intent, callingAppId, targetAppId); } else { From fea2fb2cb011005e4ad53ee4a0b482c426399001 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Fri, 20 Sep 2019 07:54:47 -0700 Subject: [PATCH 018/182] Breaks isInstantApp into public and internal This change breaks isInstantApp up into a public and internal implementation so that internal interfaces have a means of calling without any permission checks that only apply to public callers. Fixes: 141288362 Test: Work profile setup Change-Id: I2cb8338c2a68bc9c4a61c075398d767980c504ed (cherry picked from commit b6e729783e75184bd2712a6cfdb50cb4188321e6) --- .../content/pm/PackageManagerInternal.java | 4 +-- .../com/android/server/am/ActiveServices.java | 4 +-- .../server/am/ActivityManagerService.java | 4 +-- .../server/pm/PackageManagerService.java | 26 ++++++++++++------- .../android/server/wm/ActivityStarter.java | 2 +- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 24ee21360ed88..3e4649f786e52 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -334,11 +334,11 @@ public abstract class PackageManagerInternal { *

* @param userId the user * @param intent the intent that triggered the grant - * @param callingAppId The app ID of the calling application + * @param callingUid The uid of the calling application * @param targetAppId The app ID of the target application */ public abstract void grantImplicitAccess( - @UserIdInt int userId, Intent intent, @AppIdInt int callingAppId, + @UserIdInt int userId, Intent intent, int callingUid, @AppIdInt int targetAppId); public abstract boolean isInstantAppInstallerComponent(ComponentName component); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index e7569bee239e0..08f75e600bc5c 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1749,7 +1749,7 @@ public final class ActiveServices { // Once the apps have become associated, if one of them is caller is ephemeral // the target app should now be able to see the calling app mAm.grantImplicitAccess(callerApp.userId, service, - UserHandle.getAppId(callerApp.uid), UserHandle.getAppId(s.appInfo.uid)); + callerApp.uid, UserHandle.getAppId(s.appInfo.uid)); AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); ConnectionRecord c = new ConnectionRecord(b, activity, @@ -2802,7 +2802,7 @@ public final class ActiveServices { mAm.mUgmInternal.grantUriPermissionUncheckedFromIntent(si.neededGrants, si.getUriPermissionsLocked()); } - mAm.grantImplicitAccess(r.userId, si.intent, UserHandle.getAppId(si.callingId), + mAm.grantImplicitAccess(r.userId, si.intent, si.callingId, UserHandle.getAppId(r.appInfo.uid) ); bumpServiceExecutingLocked(r, execInFg, "start"); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3c7cb88174e11..c07f67b902ac9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6118,9 +6118,9 @@ public class ActivityManagerService extends IActivityManager.Stub } @VisibleForTesting - public void grantImplicitAccess(int userId, Intent intent, int callingAppId, int targetAppId) { + public void grantImplicitAccess(int userId, Intent intent, int callingUid, int targetAppId) { getPackageManagerInternalLocked(). - grantImplicitAccess(userId, intent, callingAppId, targetAppId); + grantImplicitAccess(userId, intent, callingUid, targetAppId); } /** diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2a85c89fdcccb..123e65e5b9ac4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -8187,15 +8187,20 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isInstantApp(String packageName, int userId) { - mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId, + final int callingUid = Binder.getCallingUid(); + mPermissionManager.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "isInstantApp"); + + return isInstantAppInternal(packageName, userId, callingUid); + } + + private boolean isInstantAppInternal(String packageName, @UserIdInt int userId, + int callingUid) { if (HIDE_EPHEMERAL_APIS) { return false; } - synchronized (mLock) { - int callingUid = Binder.getCallingUid(); if (Process.isIsolated(callingUid)) { callingUid = mIsolatedOwners.get(callingUid); } @@ -23129,19 +23134,20 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void grantImplicitAccess(int userId, Intent intent, - int callingAppId, int targetAppId) { + int callingUid, int targetAppId) { synchronized (mLock) { - final PackageParser.Package callingPackage = getPackage( - UserHandle.getUid(userId, callingAppId)); - final PackageParser.Package targetPackage = getPackage( - UserHandle.getUid(userId, targetAppId)); + final PackageParser.Package callingPackage = getPackage(callingUid); + final PackageParser.Package targetPackage = + getPackage(UserHandle.getUid(userId, targetAppId)); if (callingPackage == null || targetPackage == null) { return; } - if (isInstantApp(callingPackage.packageName, userId)) { + final boolean instantApp = isInstantAppInternal(callingPackage.packageName, userId, + callingUid); + if (instantApp) { mInstantAppRegistry.grantInstantAccessLPw(userId, intent, - callingAppId, targetAppId); + UserHandle.getAppId(callingUid), targetAppId); } else { mAppsFilter.grantImplicitAccess( callingPackage.packageName, targetPackage.packageName, userId); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 47be792802a07..dbf06a5802825 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1552,7 +1552,7 @@ class ActivityStarter { mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.mUserId); mService.getPackageManagerInternalLocked().grantImplicitAccess( mStartActivity.mUserId, mIntent, - UserHandle.getAppId(mCallingUid), + mCallingUid, UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) ); if (newTask) { From ed5c1a08d319103897fc52d929fafbe1e8f02543 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 24 Sep 2019 12:03:18 -0700 Subject: [PATCH 019/182] SurfaceView: Release Surfaces where SurfaceControl are released. Following the same logic as the revision "Destroy SurfaceControl from RenderThread" we have a similar race condition with the native object behind the mSurface object. In addition that CL introduces a logic error...previously in positionLost we assumed if mSurfaceControl != null then mSurface had not been released, but now we release the Surface but wait on the RenderThread to release the SurfaceControl when it tries to grab the frame number to create the deferred transaction the Surface has already been released and we go on to crash. Releasing them all in the same place fixes this. Bug: 141525040 Test: go/wm-smoke Change-Id: I7c938cd498a9260146f34f2d6e18744854d69946 (cherry picked from commit 172bdbc5026fdafb30905e7e462c5184c8cd840f) --- core/java/android/view/SurfaceView.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 262b9e50ad009..db3ef20d5859c 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -675,6 +675,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mTmpTransaction.remove(mBackgroundControl); mBackgroundControl = null; } + mSurface.release(); mTmpTransaction.apply(); } } @@ -962,7 +963,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } finally { mIsCreating = false; if (mSurfaceControl != null && !mSurfaceCreated) { - mSurface.release(); releaseSurfaces(); } } @@ -1143,6 +1143,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mRtTransaction.remove(mBackgroundControl); mSurfaceControl = null; mBackgroundControl = null; + mSurface.release(); } mRtHandlingPositionUpdates = false; } From 600c10c26a49889878777cdfc0b794363b8b3785 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 1 Oct 2019 12:59:39 -0700 Subject: [PATCH 020/182] Fix NavigationBarController NPE SystemUI would crash if NavigationBarFragment wasn't available yet. Test: mp sysuig # boots Test: atest NavigationBarControllerTest Fixes: 139609145 Change-Id: I1e099c5cc3c23c05140d550dd870722f57055013 (cherry picked from commit 6c1b804105599a98ca03fe32c05f36b1089fbbf3) --- .../systemui/statusbar/NavigationBarController.java | 3 ++- .../systemui/statusbar/NavigationBarControllerTest.java | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java index 09f80455a1b01..16cdfaa18a532 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java @@ -237,6 +237,7 @@ public class NavigationBarController implements Callbacks { /** @return {@link AssistHandleViewController} (only on the default display). */ public AssistHandleViewController getAssistHandlerViewController() { - return getDefaultNavigationBarFragment().getAssistHandlerViewController(); + NavigationBarFragment navBar = getDefaultNavigationBarFragment(); + return navBar == null ? null : navBar.getAssistHandlerViewController(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java index 7d2ccdc8f0a98..618272cbcab06 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -240,4 +241,10 @@ public class NavigationBarControllerTest extends SysuiTestCase { verify(mSecondaryNavBar).disableAnimationsDuringHide(eq(500L)); } + + @Test + public void testGetAssistHandlerViewController_noCrash() { + reset(mNavigationBarController.mNavigationBars); + mNavigationBarController.getAssistHandlerViewController(); + } } From c61a0861baa6c0252e0f1c92279efac04b4816b1 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 1 Oct 2019 12:59:39 -0700 Subject: [PATCH 021/182] Fix NavigationBarController NPE SystemUI would crash if NavigationBarFragment wasn't available yet. Test: mp sysuig # boots Test: atest NavigationBarControllerTest Fixes: 141939419 Change-Id: I1e099c5cc3c23c05140d550dd870722f57055013 (cherry picked from commit 131c76d485d8fa927556d3874b9dfd33a5251299) --- .../systemui/statusbar/NavigationBarController.java | 3 ++- .../systemui/statusbar/NavigationBarControllerTest.java | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java index 09f80455a1b01..16cdfaa18a532 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java @@ -237,6 +237,7 @@ public class NavigationBarController implements Callbacks { /** @return {@link AssistHandleViewController} (only on the default display). */ public AssistHandleViewController getAssistHandlerViewController() { - return getDefaultNavigationBarFragment().getAssistHandlerViewController(); + NavigationBarFragment navBar = getDefaultNavigationBarFragment(); + return navBar == null ? null : navBar.getAssistHandlerViewController(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java index 7d2ccdc8f0a98..618272cbcab06 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -240,4 +241,10 @@ public class NavigationBarControllerTest extends SysuiTestCase { verify(mSecondaryNavBar).disableAnimationsDuringHide(eq(500L)); } + + @Test + public void testGetAssistHandlerViewController_noCrash() { + reset(mNavigationBarController.mNavigationBars); + mNavigationBarController.getAssistHandlerViewController(); + } } From a15b7585f438a64d589328efdb29575e5c02824d Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Thu, 3 Oct 2019 00:51:58 +0000 Subject: [PATCH 022/182] Revert "Remove many (most) of the calls to Dependency.get() from StatusBar." This reverts commit f4d6d1c158afa473ef8308ed64911cfbbf41950f. Reason for revert: http://b/141996663 Change-Id: Ic0fc4cbb38a89f8107441dec582b3a1641666f64 (cherry picked from commit 82679b58c1135f7459aca913f79277ae442053ab) --- .../android/systemui/DependencyBinder.java | 7 - .../systemui/statusbar/phone/StatusBar.java | 124 ++++++---- .../phone/NavigationBarFragmentTest.java | 6 +- .../statusbar/phone/StatusBarTest.java | 215 ++++++------------ 4 files changed, 160 insertions(+), 192 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java index c4dce1e700514..818b5e1c69f44 100644 --- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java +++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java @@ -30,7 +30,6 @@ import com.android.systemui.qs.QSHost; import com.android.systemui.qs.QSTileHost; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.StatusBarStateControllerImpl; -import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl; @@ -235,10 +234,4 @@ public abstract class DependencyBinder { */ @Binds public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl); - - /** - */ - @Binds - public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController( - StatusBarStateControllerImpl statusBarStateControllerImpl); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index e79f14175377d..5fc2d9beab894 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -347,10 +347,10 @@ public class StatusBar extends SystemUI implements DemoMode, private BrightnessMirrorController mBrightnessMirrorController; private boolean mBrightnessMirrorVisible; protected BiometricUnlockController mBiometricUnlockController; - @Inject LightBarController mLightBarController; + private LightBarController mLightBarController; protected LockscreenWallpaper mLockscreenWallpaper; @VisibleForTesting - @Inject AutoHideController mAutoHideController; + protected AutoHideController mAutoHideController; private int mNaturalBarHeight = -1; @@ -361,7 +361,7 @@ public class StatusBar extends SystemUI implements DemoMode, private int mStatusBarWindowState = WINDOW_STATE_SHOWING; protected StatusBarWindowController mStatusBarWindowController; @VisibleForTesting - @Inject KeyguardUpdateMonitor mKeyguardUpdateMonitor; + KeyguardUpdateMonitor mKeyguardUpdateMonitor; @VisibleForTesting DozeServiceHost mDozeServiceHost = new DozeServiceHost(); private boolean mWakeUpComingFromTouch; @@ -369,7 +369,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final Object mQueueLock = new Object(); - @Inject StatusBarIconController mIconController; + protected StatusBarIconController mIconController; @Inject DozeLog mDozeLog; @Inject @@ -400,7 +400,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected FalsingManager mFalsingManager; @VisibleForTesting - @Inject BroadcastDispatcher mBroadcastDispatcher; + BroadcastDispatcher mBroadcastDispatcher; // expanded notifications protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window @@ -413,7 +413,8 @@ public class StatusBar extends SystemUI implements DemoMode, // RemoteInputView to be activated after unlock private View mPendingRemoteInputView; - @Inject RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler; + private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler = + Dependency.get(RemoteInputQuickSettingsDisabler.class); private View mReportRejectedTouch; @@ -422,17 +423,18 @@ public class StatusBar extends SystemUI implements DemoMode, private final int[] mAbsPos = new int[2]; private final ArrayList mPostCollapseRunnables = new ArrayList<>(); - @Inject NotificationGutsManager mGutsManager; - @Inject NotificationLogger mNotificationLogger; - @Inject NotificationEntryManager mEntryManager; + private NotificationGutsManager mGutsManager; + protected NotificationLogger mNotificationLogger; + protected NotificationEntryManager mEntryManager; private NotificationListController mNotificationListController; - @Inject NotificationInterruptionStateProvider mNotificationInterruptionStateProvider; - @Inject NotificationViewHierarchyManager mViewHierarchyManager; - @Inject ForegroundServiceController mForegroundServiceController; - @Inject AppOpsController mAppOpsController; - @Inject KeyguardViewMediator mKeyguardViewMediator; - @Inject ZenModeController mZenController; - @Inject NotificationAlertingManager mNotificationAlertingManager; + private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider; + protected NotificationViewHierarchyManager mViewHierarchyManager; + protected ForegroundServiceController mForegroundServiceController; + protected AppOpsController mAppOpsController; + protected KeyguardViewMediator mKeyguardViewMediator; + private ZenModeController mZenController; + private final NotificationAlertingManager mNotificationAlertingManager = + Dependency.get(NotificationAlertingManager.class); // for disabling the status bar private int mDisabled1 = 0; @@ -443,7 +445,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final Rect mLastFullscreenStackBounds = new Rect(); private final Rect mLastDockedStackBounds = new Rect(); - @Inject DisplayMetrics mDisplayMetrics; + private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class); // XXX: gesture research private final GestureRecorder mGestureRec = DEBUG_GESTURES @@ -452,7 +454,7 @@ public class StatusBar extends SystemUI implements DemoMode, private ScreenPinningRequest mScreenPinningRequest; - @Inject MetricsLogger mMetricsLogger; + private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); // ensure quick settings is disabled until the current user makes it through the setup wizard @VisibleForTesting @@ -489,14 +491,14 @@ public class StatusBar extends SystemUI implements DemoMode, private ViewMediatorCallback mKeyguardViewMediatorCallback; protected ScrimController mScrimController; protected DozeScrimController mDozeScrimController; - @Inject UiOffloadThread mUiOffloadThread; + private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class); protected boolean mDozing; private boolean mDozingRequested; - @Inject NotificationMediaManager mMediaManager; - @Inject NotificationLockscreenUserManager mLockscreenUserManager; - @Inject NotificationRemoteInputManager mRemoteInputManager; + private NotificationMediaManager mMediaManager; + protected NotificationLockscreenUserManager mLockscreenUserManager; + protected NotificationRemoteInputManager mRemoteInputManager; private boolean mWallpaperSupported; private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() { @@ -567,18 +569,18 @@ public class StatusBar extends SystemUI implements DemoMode, }; private KeyguardUserSwitcher mKeyguardUserSwitcher; - @Inject UserSwitcherController mUserSwitcherController; - @Inject NetworkController mNetworkController; - @Inject BatteryController mBatteryController; + protected UserSwitcherController mUserSwitcherController; + private NetworkController mNetworkController; + private BatteryController mBatteryController; protected boolean mPanelExpanded; private UiModeManager mUiModeManager; protected boolean mIsKeyguard; private LogMaker mStatusBarStateLog; protected NotificationIconAreaController mNotificationIconAreaController; @Nullable private View mAmbientIndicationContainer; - @Inject SysuiColorExtractor mColorExtractor; - @Inject ScreenLifecycle mScreenLifecycle; - @Inject @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle; + private SysuiColorExtractor mColorExtractor; + private ScreenLifecycle mScreenLifecycle; + @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle; private final View.OnClickListener mGoToLockedShadeListener = v -> { if (mState == StatusBarState.KEYGUARD) { @@ -587,7 +589,8 @@ public class StatusBar extends SystemUI implements DemoMode, } }; private boolean mNoAnimationOnNextBarModeChange; - @Inject SysuiStatusBarStateController mStatusBarStateController; + private final SysuiStatusBarStateController mStatusBarStateController = + (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class); private final KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @@ -608,18 +611,19 @@ public class StatusBar extends SystemUI implements DemoMode, private HeadsUpAppearanceController mHeadsUpAppearanceController; private boolean mVibrateOnOpening; - @Inject VibratorHelper mVibratorHelper; + private VibratorHelper mVibratorHelper; private ActivityLaunchAnimator mActivityLaunchAnimator; protected StatusBarNotificationPresenter mPresenter; private NotificationActivityStarter mNotificationActivityStarter; private boolean mPulsing; - @Inject BubbleController mBubbleController; + protected BubbleController mBubbleController; private final BubbleController.BubbleExpandListener mBubbleExpandListener = (isExpanding, key) -> { mEntryManager.updateNotifications(); updateScrimController(); }; private ActivityIntentHelper mActivityIntentHelper; + private ShadeController mShadeController; @Override public void onActiveStateChanged(int code, int uid, String packageName, boolean active) { @@ -637,13 +641,41 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void start() { + mGroupManager = Dependency.get(NotificationGroupManager.class); + mGroupAlertTransferHelper = Dependency.get(NotificationGroupAlertTransferHelper.class); + mVisualStabilityManager = Dependency.get(VisualStabilityManager.class); + mNotificationLogger = Dependency.get(NotificationLogger.class); + mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class); + mNotificationListener = Dependency.get(NotificationListener.class); mNotificationListener.registerAsSystemService(); + mNetworkController = Dependency.get(NetworkController.class); + mUserSwitcherController = Dependency.get(UserSwitcherController.class); + mScreenLifecycle = Dependency.get(ScreenLifecycle.class); mScreenLifecycle.addObserver(mScreenObserver); + mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class); mWakefulnessLifecycle.addObserver(mWakefulnessObserver); + mBatteryController = Dependency.get(BatteryController.class); + mAssistManager = Dependency.get(AssistManager.class); mUiModeManager = mContext.getSystemService(UiModeManager.class); + mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class); + mGutsManager = Dependency.get(NotificationGutsManager.class); + mMediaManager = Dependency.get(NotificationMediaManager.class); + mEntryManager = Dependency.get(NotificationEntryManager.class); mBypassHeadsUpNotifier.setUp(mEntryManager); + mNotificationInterruptionStateProvider = + Dependency.get(NotificationInterruptionStateProvider.class); + mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class); + mForegroundServiceController = Dependency.get(ForegroundServiceController.class); + mAppOpsController = Dependency.get(AppOpsController.class); + mZenController = Dependency.get(ZenModeController.class); + mKeyguardViewMediator = getComponent(KeyguardViewMediator.class); + mColorExtractor = Dependency.get(SysuiColorExtractor.class); + mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); + mNavigationBarController = Dependency.get(NavigationBarController.class); + mBubbleController = Dependency.get(BubbleController.class); mBubbleController.setExpandListener(mBubbleExpandListener); mActivityIntentHelper = new ActivityIntentHelper(mContext); + mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class); KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance(); if (sliceProvider != null) { sliceProvider.initDependencies(mMediaManager, mStatusBarStateController, @@ -666,6 +698,7 @@ public class StatusBar extends SystemUI implements DemoMode, mVibrateOnOpening = mContext.getResources().getBoolean( R.bool.config_vibrateOnIconAnimation); + mVibratorHelper = Dependency.get(VibratorHelper.class); DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER)); putComponent(StatusBar.class, this); @@ -679,6 +712,7 @@ public class StatusBar extends SystemUI implements DemoMode, mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @@ -867,6 +901,7 @@ public class StatusBar extends SystemUI implements DemoMode, .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG) .commit(); + mIconController = Dependency.get(StatusBarIconController.class); mHeadsUpManager.setUp(mStatusBarWindow, mGroupManager, this, mVisualStabilityManager); Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager); @@ -912,8 +947,11 @@ public class StatusBar extends SystemUI implements DemoMode, } }); + mAutoHideController = Dependency.get(AutoHideController.class); mAutoHideController.setStatusBar(this); + mLightBarController = Dependency.get(LightBarController.class); + ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind); ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front); ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble); @@ -1085,6 +1123,7 @@ public class StatusBar extends SystemUI implements DemoMode, final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback = (StatusBarRemoteInputCallback) Dependency.get( NotificationRemoteInputManager.Callback.class); + mShadeController = Dependency.get(ShadeController.class); final ActivityStarter activityStarter = Dependency.get(ActivityStarter.class); mNotificationActivityStarter = new StatusBarNotificationActivityStarter(mContext, @@ -1092,7 +1131,7 @@ public class StatusBar extends SystemUI implements DemoMode, mHeadsUpManager, activityStarter, mActivityLaunchAnimator, mBarService, mStatusBarStateController, mKeyguardManager, mDreamManager, mRemoteInputManager, mStatusBarRemoteInputCallback, mGroupManager, - mLockscreenUserManager, this, mKeyguardStateController, + mLockscreenUserManager, mShadeController, mKeyguardStateController, mNotificationInterruptionStateProvider, mMetricsLogger, new LockPatternUtils(mContext), Dependency.get(MAIN_HANDLER), Dependency.get(BG_HANDLER), mActivityIntentHelper, mBubbleController); @@ -1101,7 +1140,7 @@ public class StatusBar extends SystemUI implements DemoMode, mEntryManager.setRowBinder(rowBinder); rowBinder.setNotificationClicker(new NotificationClicker( - this, mBubbleController, mNotificationActivityStarter)); + this, Dependency.get(BubbleController.class), mNotificationActivityStarter)); mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager); mNotificationListController.bind(); @@ -4188,11 +4227,12 @@ public class StatusBar extends SystemUI implements DemoMode, // all notifications protected ViewGroup mStackScroller; - @Inject NotificationGroupManager mGroupManager; - @Inject NotificationGroupAlertTransferHelper mGroupAlertTransferHelper; + protected NotificationGroupManager mGroupManager; + + protected NotificationGroupAlertTransferHelper mGroupAlertTransferHelper; // handling reordering - @Inject VisualStabilityManager mVisualStabilityManager; + protected VisualStabilityManager mVisualStabilityManager; protected AccessibilityManager mAccessibilityManager; @@ -4208,9 +4248,10 @@ public class StatusBar extends SystemUI implements DemoMode, protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; protected KeyguardManager mKeyguardManager; - @Inject DeviceProvisionedController mDeviceProvisionedController; + private DeviceProvisionedController mDeviceProvisionedController + = Dependency.get(DeviceProvisionedController.class); - @Inject protected NavigationBarController mNavigationBarController; + protected NavigationBarController mNavigationBarController; // UI-specific methods @@ -4226,7 +4267,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected NotificationShelf mNotificationShelf; protected EmptyShadeView mEmptyShadeView; - @Inject AssistManager mAssistManager; + protected AssistManager mAssistManager; public boolean isDeviceInteractive() { return mDeviceInteractive; @@ -4285,7 +4326,7 @@ public class StatusBar extends SystemUI implements DemoMode, } } - @Inject NotificationListener mNotificationListener; + protected NotificationListener mNotificationListener; public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) { if (snoozeOption.getSnoozeCriterion() != null) { @@ -4421,7 +4462,8 @@ public class StatusBar extends SystemUI implements DemoMode, executeActionDismissingKeyguard(() -> { try { intent.send(null, 0, null, null, null, null, getActivityOptions( - mActivityLaunchAnimator.getLaunchAnimation(associatedView, isOccluded()))); + mActivityLaunchAnimator.getLaunchAnimation(associatedView, + mShadeController.isOccluded()))); } catch (PendingIntent.CanceledException e) { // the stack trace isn't very helpful here. // Just log the exception message. 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 237f6ac0f420c..0bff5aa9e9913 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 @@ -80,7 +80,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) -@RunWithLooper(setAsMainLooper = true) +@RunWithLooper() @SmallTest public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { private static final int EXTERNAL_DISPLAY_ID = 2; @@ -217,7 +217,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { // Set IME window status for default NavBar. mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true, false); - processAllMessages(); + Handler.getMain().runWithScissors(() -> { }, 500); // Verify IME window state will be updated in default NavBar & external NavBar state reset. assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN, @@ -228,7 +228,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { // Set IME window status for external NavBar. mCommandQueue.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null, IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true, false); - processAllMessages(); + Handler.getMain().runWithScissors(() -> { }, 500); // Verify IME window state will be updated in external NavBar & default NavBar state reset. assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index f163886193b4d..7de7f9e238135 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -59,7 +59,6 @@ import android.support.test.metricshelper.MetricsAsserts; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; -import android.util.DisplayMetrics; import android.util.SparseArray; import android.view.ViewGroup.LayoutParams; @@ -74,19 +73,16 @@ import com.android.systemui.Dependency; import com.android.systemui.ForegroundServiceController; import com.android.systemui.InitController; import com.android.systemui.R; +import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.UiOffloadThread; import com.android.systemui.appops.AppOpsController; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; -import com.android.systemui.classifier.FalsingManagerFake; -import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.doze.DozeEvent; import com.android.systemui.doze.DozeHost; -import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; import com.android.systemui.plugins.FalsingManager; @@ -102,18 +98,14 @@ import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationViewHierarchyManager; -import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateControllerImpl; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.NotificationAlertingManager; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationData; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -124,7 +116,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.statusbar.policy.UserSwitcherController; import org.junit.Before; @@ -157,7 +148,10 @@ public class StatusBarTest extends SysuiTestCase { @Mock private ArrayList mNotificationList; @Mock private BiometricUnlockController mBiometricUnlockController; @Mock private NotificationData mNotificationData; - @Mock private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor; + @Mock + private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor; + + // Mock dependencies: @Mock private NotificationViewHierarchyManager mViewHierarchyManager; @Mock private VisualStabilityManager mVisualStabilityManager; @Mock private NotificationListener mNotificationListener; @@ -169,38 +163,51 @@ public class StatusBarTest extends SysuiTestCase { @Mock private BatteryController mBatteryController; @Mock private DeviceProvisionedController mDeviceProvisionedController; @Mock private StatusBarNotificationPresenter mNotificationPresenter; - @Mock private NotificationEntryListener mEntryListener; - @Mock private NotificationFilter mNotificationFilter; - @Mock private NotificationAlertingManager mNotificationAlertingManager; - @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger; - @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration; - @Mock private StatusBarWindowView mStatusBarWindowView; - @Mock private BroadcastDispatcher mBroadcastDispatcher; - @Mock private AssistManager mAssistManager; - @Mock private NotificationGutsManager mNotificationGutsManager; - @Mock private NotificationMediaManager mNotificationMediaManager; - @Mock private ForegroundServiceController mForegroundServiceController; - @Mock private AppOpsController mAppOpsController; - @Mock private NavigationBarController mNavigationBarController; - @Mock private BypassHeadsUpNotifier mBypassHeadsUpNotifier; - @Mock private SysuiColorExtractor mColorExtractor; - @Mock private DozeLog mDozeLog; - @Mock private PulseExpansionHandler mPulseExpansionHandler; - @Mock private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler; - @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - @Mock private KeyguardBypassController mKeyguardBypassController; + @Mock + private NotificationEntryListener mEntryListener; + @Mock + private NotificationFilter mNotificationFilter; + @Mock + private NotificationAlertingManager mNotificationAlertingManager; + @Mock + private NotificationLogger.ExpansionStateLogger mExpansionStateLogger; + @Mock + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock + private AmbientDisplayConfiguration mAmbientDisplayConfiguration; + @Mock + private StatusBarWindowView mStatusBarWindowView; + @Mock + private BroadcastDispatcher mBroadcastDispatcher; private TestableStatusBar mStatusBar; private FakeMetricsLogger mMetricsLogger; private PowerManager mPowerManager; + private TestableNotificationEntryManager mEntryManager; private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider; + private NotificationLogger mNotificationLogger; private CommandQueue mCommandQueue; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); + mDependency.injectMockDependency(AssistManager.class); + mDependency.injectMockDependency(NotificationGutsManager.class); + mDependency.injectMockDependency(NotificationMediaManager.class); + mDependency.injectMockDependency(ForegroundServiceController.class); + mDependency.injectTestDependency(NotificationViewHierarchyManager.class, + mViewHierarchyManager); + mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager); + mDependency.injectTestDependency(NotificationListener.class, mNotificationListener); + mDependency.injectTestDependency(AppOpsController.class, mock(AppOpsController.class)); + mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController); + mDependency.injectTestDependency(DeviceProvisionedController.class, + mDeviceProvisionedController); + mDependency.injectMockDependency(BubbleController.class); mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter); + mDependency.injectTestDependency(NotificationAlertingManager.class, + mNotificationAlertingManager); + mDependency.injectTestDependency(BroadcastDispatcher.class, mBroadcastDispatcher); IPowerManager powerManagerService = mock(IPowerManager.class); mPowerManager = new PowerManager(mContext, powerManagerService, @@ -210,17 +217,21 @@ public class StatusBarTest extends SysuiTestCase { new TestableNotificationInterruptionStateProvider(mContext, mPowerManager, mDreamManager, mAmbientDisplayConfiguration, mNotificationFilter, mStatusBarStateController, mBatteryController); + mDependency.injectTestDependency(NotificationInterruptionStateProvider.class, + mNotificationInterruptionStateProvider); + mDependency.injectMockDependency(NavigationBarController.class); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class)); mMetricsLogger = new FakeMetricsLogger(); - TestableNotificationEntryManager entryManager = new TestableNotificationEntryManager( - mContext); - NotificationLogger notificationLogger = new NotificationLogger(mNotificationListener, - Dependency.get(UiOffloadThread.class), entryManager, mStatusBarStateController, + mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); + mEntryManager = new TestableNotificationEntryManager(mContext); + mNotificationLogger = new NotificationLogger(mNotificationListener, + Dependency.get(UiOffloadThread.class), mEntryManager, mStatusBarStateController, mExpansionStateLogger); - notificationLogger.setVisibilityReporter(mock(Runnable.class)); + mNotificationLogger.setVisibilityReporter(mock(Runnable.class)); + mDependency.injectTestDependency(NotificationLogger.class, mNotificationLogger); mCommandQueue = mock(CommandQueue.class); when(mCommandQueue.asBinder()).thenReturn(new Binder()); @@ -249,71 +260,32 @@ public class StatusBarTest extends SysuiTestCase { mHeadsUpManager, mHeadsUpSuppressor); when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController); - mStatusBar = new TestableStatusBar( - mStatusBarKeyguardViewManager, - mKeyguardIndicationController, - mStackScroller, - mPowerManager, - mNotificationPanelView, - mBarService, - mNotificationListener, - notificationLogger, - mVisualStabilityManager, - mViewHierarchyManager, - entryManager, - mScrimController, - mBiometricUnlockController, - mKeyguardViewMediator, - mRemoteInputManager, - mock(NotificationGroupManager.class), - mock(NotificationGroupAlertTransferHelper.class), - new FalsingManagerFake(), - mock(StatusBarWindowController.class), - mock(NotificationIconAreaController.class), - mDozeScrimController, - mock(NotificationShelf.class), - mLockscreenUserManager, - mCommandQueue, - mNotificationPresenter, - mock(BubbleController.class), - mNavigationBarController, - mock(AutoHideController.class), - mKeyguardUpdateMonitor, - mStatusBarWindowView, - mBroadcastDispatcher, - mAssistManager, - mNotificationGutsManager, - mNotificationMediaManager, - mForegroundServiceController, - mAppOpsController, - mStatusBarStateController, - mDeviceProvisionedController, - mNotificationAlertingManager, - mNotificationInterruptionStateProvider, - mMetricsLogger, - mHeadsUpManager, - mKeyguardStateController, - new ScreenLifecycle(), - mBypassHeadsUpNotifier, - mColorExtractor, - new DisplayMetrics(), - Dependency.get(UiOffloadThread.class), - mDozeLog, - mPulseExpansionHandler, - new RemoteInputQuickSettingsDisabler( - mContext, - new ConfigurationControllerImpl(mContext) - ), - mNotificationWakeUpCoordinator, - mKeyguardBypassController); + mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, + mKeyguardIndicationController, mStackScroller, + mPowerManager, mNotificationPanelView, mBarService, mNotificationListener, + mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager, + mEntryManager, mScrimController, mBiometricUnlockController, + mKeyguardViewMediator, mRemoteInputManager, mock(NotificationGroupManager.class), + mock(NotificationGroupAlertTransferHelper.class), mock(FalsingManager.class), + mock(StatusBarWindowController.class), mock(NotificationIconAreaController.class), + mDozeScrimController, mock(NotificationShelf.class), + mLockscreenUserManager, mCommandQueue, mNotificationPresenter, + mock(BubbleController.class), mock(NavigationBarController.class), + mock(AutoHideController.class), mKeyguardUpdateMonitor, mStatusBarWindowView, + mBroadcastDispatcher); mStatusBar.mContext = mContext; mStatusBar.mComponents = mContext.getComponents(); + SystemUIFactory.getInstance().getRootComponent() + .getStatusBarInjector() + .createStatusBar(mStatusBar); + mStatusBar.mKeyguardStateController = mKeyguardStateController; + mStatusBar.setHeadsUpManager(mHeadsUpManager); mStatusBar.putComponent(StatusBar.class, mStatusBar); Dependency.get(InitController.class).executePostInitTasks(); - entryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller, + mEntryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller, mHeadsUpManager, mNotificationData); - entryManager.addNotificationEntryListener(mEntryListener); - notificationLogger.setUpWithContainer(mStackScroller); + mEntryManager.addNotificationEntryListener(mEntryListener); + mNotificationLogger.setUpWithContainer(mStackScroller); } @Test @@ -849,28 +821,7 @@ public class StatusBarTest extends SysuiTestCase { AutoHideController autoHideController, KeyguardUpdateMonitor keyguardUpdateMonitor, StatusBarWindowView statusBarWindow, - BroadcastDispatcher broadcastDispatcher, - AssistManager assistManager, - NotificationGutsManager notificationGutsManager, - NotificationMediaManager notificationMediaManager, - ForegroundServiceController foregroundServiceController, - AppOpsController appOpsController, - SysuiStatusBarStateController statusBarStateController, - DeviceProvisionedController deviceProvisionedController, - NotificationAlertingManager notificationAlertingManager, - NotificationInterruptionStateProvider notificationInterruptionStateProvider, - MetricsLogger metricsLogger, - HeadsUpManagerPhone headsUpManager, - KeyguardStateController keyguardStateController, - ScreenLifecycle screenLifecycle, - BypassHeadsUpNotifier bypassHeadsUpNotifier, - SysuiColorExtractor colorExtractor, DisplayMetrics displayMetrics, - UiOffloadThread uiOffloadThread, - DozeLog dozeLog, - PulseExpansionHandler pulseExpansionHandler, - RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, - NotificationWakeUpCoordinator notificationWakeUpCoordinator, - KeyguardBypassController keyguardBypassController) { + BroadcastDispatcher broadcastDispatcher) { mStatusBarKeyguardViewManager = man; mKeyguardIndicationController = key; mStackScroller = stack; @@ -905,28 +856,6 @@ public class StatusBarTest extends SysuiTestCase { mStatusBarWindow = statusBarWindow; mDozeServiceHost.mWakeLockScreenPerformsAuth = false; mBroadcastDispatcher = broadcastDispatcher; - mAssistManager = assistManager; - mGutsManager = notificationGutsManager; - mMediaManager = notificationMediaManager; - mForegroundServiceController = foregroundServiceController; - mAppOpsController = appOpsController; - mStatusBarStateController = statusBarStateController; - mDeviceProvisionedController = deviceProvisionedController; - mNotificationAlertingManager = notificationAlertingManager; - mNotificationInterruptionStateProvider = notificationInterruptionStateProvider; - mMetricsLogger = metricsLogger; - mHeadsUpManager = headsUpManager; - mKeyguardStateController = keyguardStateController; - mScreenLifecycle = screenLifecycle; - mBypassHeadsUpNotifier = bypassHeadsUpNotifier; - mColorExtractor = colorExtractor; - mDisplayMetrics = displayMetrics; - mUiOffloadThread = uiOffloadThread; - mDozeLog = dozeLog; - mPulseExpansionHandler = pulseExpansionHandler; - mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler; - mWakeUpCoordinator = notificationWakeUpCoordinator; - mKeyguardBypassController = keyguardBypassController; } private WakefulnessLifecycle createAwakeWakefulnessLifecycle() { @@ -945,6 +874,10 @@ public class StatusBarTest extends SysuiTestCase { mState = state; } + void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) { + mHeadsUpManager = headsUpManager; + } + public void setUserSetupForTest(boolean userSetup) { mUserSetup = userSetup; } From a2c9ab5ef6e081dff3355a4377989b3bd9dce229 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Tue, 8 Oct 2019 14:23:25 -0400 Subject: [PATCH 023/182] Ensure that view is initialized properlly upon inflation. Bug: 142299585 Test: manual Change-Id: Ia17e3a3ab29dd46134fa13861024b1d58a6b3d4e (cherry picked from commit 4889186cfb3f1a21247a5293589431405948dcd1) --- .../android/systemui/statusbar/phone/NotificationPanelView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index c7fe4a8d9a3af..00736b73f12ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -518,6 +518,7 @@ public class NotificationPanelView extends PanelView implements * Call after this view has been fully inflated and had its children attached. */ public void onChildrenAttached() { + loadDimens(); mKeyguardStatusBar = findViewById(R.id.keyguard_header); mKeyguardStatusView = findViewById(R.id.keyguard_status_view); From 3c5355b346b464178074b56892fa85de4200cd16 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 8 Oct 2019 14:42:00 -0700 Subject: [PATCH 024/182] Make KeyguardUpdateMonitor a singleton It was already supposed to be a singleton, but multiple instances ended up being created during the Dagger migration. Fixes: 142219747 Bug: 141751146 Bug: 136279712 Test: manual Change-Id: Iada305bd424c7de53bc3148459afb3a4b764e44c (cherry picked from commit ab39e80e6f911baf9c9a4efcf456eccbd470afc4) --- .../src/com/android/keyguard/KeyguardUpdateMonitor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index dc8ee16e8645d..9bcccbc903dc9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -118,12 +118,14 @@ import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Singleton; /** * Watches for updates that may be interesting to the keyguard, and provides * the up to date information as well as a registration for callbacks that care * to be updated. */ +@Singleton public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final String TAG = "KeyguardUpdateMonitor"; From e5e4a8f97f2c8affbd620c90ffe300f67dc8c414 Mon Sep 17 00:00:00 2001 From: John Reck Date: Tue, 8 Oct 2019 23:28:41 +0000 Subject: [PATCH 025/182] Revert "Drop all caches in UI_HIDDEN" This reverts commit 8a207962ec84904a0fb8c7b5ce547ed2d1b59794. Bug: 142301356 Test: none, speculative Reason for revert: Seems to break alarm? Change-Id: Ia1680d1a937b596297c2eab3e54476daf9589347 (cherry picked from commit f846aeec9d87cb0cef58061d400efe3af7008903) --- libs/hwui/renderthread/CacheManager.cpp | 2 +- libs/hwui/renderthread/CanvasContext.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index dc07f0d84d186..8eb81533fda8c 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -135,7 +135,7 @@ void CacheManager::trimStaleResources() { return; } mGrContext->flush(); - mGrContext->performDeferredCleanup(std::chrono::seconds(30)); + mGrContext->purgeResourcesNotUsedInMs(std::chrono::seconds(30)); } sp CacheManager::acquireVectorDrawableAtlas() { diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 93fd0c87a361b..30cc007d454b1 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -646,11 +646,11 @@ void CanvasContext::trimMemory(RenderThread& thread, int level) { ATRACE_CALL(); if (!thread.getGrContext()) return; ATRACE_CALL(); - if (level >= TRIM_MEMORY_UI_HIDDEN) { - thread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::Complete); - } if (level >= TRIM_MEMORY_COMPLETE) { + thread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::Complete); thread.destroyRenderingContext(); + } else if (level >= TRIM_MEMORY_UI_HIDDEN) { + thread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::UiHidden); } } From a07f8ab2fdc4b132f1940a41f256d7c22403db34 Mon Sep 17 00:00:00 2001 From: Andrei-Valentin Onea Date: Wed, 16 Oct 2019 10:10:36 +0000 Subject: [PATCH 026/182] Revert "Example for disabling changes at test time" This reverts commit 12765612f3adf69e9e1b170ab724c99acb26f699. Reason for revert: http://b/142758681 Change-Id: I3e844bf1794e355187934a0370cdc94ece44deb8 (cherry picked from commit 64d5222a95413f9872d2e4845771e2765353c08a) --- tests/Gating/Android.bp | 17 ---- tests/Gating/AndroidManifest.xml | 11 --- tests/Gating/AndroidTest.xml | 30 ------ .../src/com/android/compat/DummyApi.java | 90 ------------------ .../com/android/tests/gating/GatingTest.java | 95 ------------------- 5 files changed, 243 deletions(-) delete mode 100644 tests/Gating/Android.bp delete mode 100644 tests/Gating/AndroidManifest.xml delete mode 100644 tests/Gating/AndroidTest.xml delete mode 100644 tests/Gating/src/com/android/compat/DummyApi.java delete mode 100644 tests/Gating/src/com/android/tests/gating/GatingTest.java diff --git a/tests/Gating/Android.bp b/tests/Gating/Android.bp deleted file mode 100644 index b6c00948f5f3f..0000000000000 --- a/tests/Gating/Android.bp +++ /dev/null @@ -1,17 +0,0 @@ -android_test { - name: "Gating", - // Only compile source java files in this apk. - srcs: ["src/**/*.java"], - certificate: "platform", - libs: [ - "android.test.runner", - "android.test.base", - ], - static_libs: [ - "junit", - "android-support-test", - "mockito-target-minus-junit4", - "truth-prebuilt", - "platform_compat-test-rules" - ], -} diff --git a/tests/Gating/AndroidManifest.xml b/tests/Gating/AndroidManifest.xml deleted file mode 100644 index 7f14b83fbc751..0000000000000 --- a/tests/Gating/AndroidManifest.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/tests/Gating/AndroidTest.xml b/tests/Gating/AndroidTest.xml deleted file mode 100644 index 730e74a6d3372..0000000000000 --- a/tests/Gating/AndroidTest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - diff --git a/tests/Gating/src/com/android/compat/DummyApi.java b/tests/Gating/src/com/android/compat/DummyApi.java deleted file mode 100644 index 93d60d07e63e2..0000000000000 --- a/tests/Gating/src/com/android/compat/DummyApi.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2016 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.compat; - -import android.compat.Compatibility; -import android.content.Context; -import android.os.RemoteException; -import android.os.ServiceManager; - -import com.android.internal.compat.IPlatformCompat; - -/** - * This is a dummy API to test gating - * - * @hide - */ -public class DummyApi { - - public static final long CHANGE_ID = 666013; - public static final long CHANGE_ID_1 = 666014; - public static final long CHANGE_ID_2 = 666015; - public static final long CHANGE_SYSTEM_SERVER = 666016; - - /** - * Dummy method - * @return "A" if change is enabled, "B" otherwise. - */ - public static String dummyFunc() { - if (Compatibility.isChangeEnabled(CHANGE_ID)) { - return "A"; - } - return "B"; - } - - /** - * Dummy combined method - * @return "0" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is disabled, - "1" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is enabled, - "2" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is disabled, - "3" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is enabled. - */ - public static String dummyCombinedFunc() { - if (!Compatibility.isChangeEnabled(CHANGE_ID_1) - && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { - return "0"; - } else if (!Compatibility.isChangeEnabled(CHANGE_ID_1) - && Compatibility.isChangeEnabled(CHANGE_ID_2)) { - return "1"; - } else if (Compatibility.isChangeEnabled(CHANGE_ID_1) - && !Compatibility.isChangeEnabled(CHANGE_ID_2)) { - return "2"; - } - return "3"; - } - - /** - * Dummy api using system server API. - */ - public static String dummySystemServer(Context context) { - IPlatformCompat platformCompat = IPlatformCompat.Stub - .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); - if (platformCompat == null) { - throw new RuntimeException("Could not obtain IPlatformCompat instance!"); - } - String packageName = context.getPackageName(); - try { - if (platformCompat.isChangeEnabledByPackageName(CHANGE_SYSTEM_SERVER, packageName)) { - return "True"; - } else { - return "False"; - } - } catch (RemoteException e) { - throw new RuntimeException("Could not get change value!", e); - } - } -} diff --git a/tests/Gating/src/com/android/tests/gating/GatingTest.java b/tests/Gating/src/com/android/tests/gating/GatingTest.java deleted file mode 100644 index 08676242b1bda..0000000000000 --- a/tests/Gating/src/com/android/tests/gating/GatingTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.tests.gating; - -import static com.google.common.truth.Truth.assertThat; - -import android.compat.CompatChangeRule; -import android.compat.CompatChangeRule.DisableCompatChanges; -import android.compat.CompatChangeRule.EnableCompatChanges; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import com.android.compat.DummyApi; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; - -/** - * Tests for platform compatibility change gating. - */ -@RunWith(AndroidJUnit4.class) -public class GatingTest { - - @Rule - public TestRule compatChangeRule = new CompatChangeRule(); - - @Test - @EnableCompatChanges({DummyApi.CHANGE_ID}) - public void testDummyGatingPositive() { - assertThat(DummyApi.dummyFunc()).isEqualTo("A"); - } - - @Test - @DisableCompatChanges({DummyApi.CHANGE_ID}) - public void testDummyGatingNegative() { - assertThat(DummyApi.dummyFunc()).isEqualTo("B"); - } - - @Test - @DisableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) - public void testDummyGatingCombined0() { - assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("0"); - } - - @Test - @DisableCompatChanges({DummyApi.CHANGE_ID_1}) - @EnableCompatChanges({DummyApi.CHANGE_ID_2}) - public void testDummyGatingCombined1() { - assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("1"); - } - - @Test - @EnableCompatChanges({DummyApi.CHANGE_ID_1}) - @DisableCompatChanges({DummyApi.CHANGE_ID_2}) - public void testDummyGatingCombined2() { - assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("2"); - } - - @Test - @EnableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2}) - public void testDummyGatingCombined3() { - assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("3"); - } - - @Test - @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) - public void testDummyGatingPositiveSystemServer() { - assertThat( - DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isEqualTo( - "True"); - } - - @Test - @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) - public void testDummyGatingNegativeSystemServer() { - assertThat( - DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isEqualTo( - "False"); - } -} From aa13034ef89be6802b5302516da79cd8948ce0bf Mon Sep 17 00:00:00 2001 From: atrost Date: Tue, 22 Oct 2019 15:26:16 +0100 Subject: [PATCH 027/182] Add userId to the package name API. The service would query package manager with the provided userId, and will return true if the package is not visible. Bug: 142942524 Bug: 143129258 Test: m, treehugger Change-Id: I92ea650b49743c388bff9943a7ec620e3d61a5d6 (cherry picked from commit 53bca9377da58f31e0eb21bbcef16cffc5b1f687) --- .../internal/compat/IPlatformCompat.aidl | 8 +++++--- .../internal/compat/IPlatformCompatNative.aidl | 6 ++++-- .../android/server/compat/PlatformCompat.java | 18 +++++++++--------- .../server/compat/PlatformCompatNative.java | 8 ++++---- .../DevicePolicyManagerService.java | 2 +- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index 4099cfa51b333..8391ad2f12c26 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -49,9 +49,10 @@ interface IPlatformCompat * you do not need to call this API directly. The change will be reported for you. * * @param changeId The ID of the compatibility change taking effect. + * @param userId The ID of the user that the operation is done for. * @param packageName The package name of the app in question. */ - void reportChangeByPackageName(long changeId, in String packageName); + void reportChangeByPackageName(long changeId, in String packageName, int userId); /** * Reports that a compatibility change is affecting an app process now. @@ -86,7 +87,7 @@ interface IPlatformCompat * be called when implementing functionality on behalf of the affected app. * *

Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a package name - * instead of an {@link ApplicationInfo} + * and userId instead of an {@link ApplicationInfo} * object, and finds an app info object based on the package name. Returns {@code true} if * there is no installed package by that name. * @@ -100,9 +101,10 @@ interface IPlatformCompat * * @param changeId The ID of the compatibility change in question. * @param packageName The package name of the app in question. + * @param userId The ID of the user that the operation is done for. * @return {@code true} if the change is enabled for the current app. */ - boolean isChangeEnabledByPackageName(long changeId, in String packageName); + boolean isChangeEnabledByPackageName(long changeId, in String packageName, int userId); /** * Query if a given compatibility change is enabled for an app process. This method should diff --git a/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl b/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl index c022388e0aa8b..347e4e8ebe4b2 100644 --- a/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl +++ b/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl @@ -33,9 +33,10 @@ interface IPlatformCompatNative * you do not need to call this API directly. The change will be reported for you. * * @param changeId The ID of the compatibility change taking effect. + * @param userId The ID of the user that the operation is done for. * @param packageName The package name of the app in question. */ - void reportChangeByPackageName(long changeId, @utf8InCpp String packageName); + void reportChangeByPackageName(long changeId, @utf8InCpp String packageName, int userId); /** * Reports that a compatibility change is affecting an app process now. @@ -64,9 +65,10 @@ interface IPlatformCompatNative * * @param changeId The ID of the compatibility change in question. * @param packageName The package name of the app in question. + * @param userId The ID of the user that the operation is done for. * @return {@code true} if the change is enabled for the current app. */ - boolean isChangeEnabledByPackageName(long changeId, @utf8InCpp String packageName); + boolean isChangeEnabledByPackageName(long changeId, @utf8InCpp String packageName, int userId); /** * Query if a given compatibility change is enabled for an app process. This method should diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 854f16aeb54ea..9ac9955493ccb 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -19,7 +19,7 @@ package com.android.server.compat; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.os.Process; +import android.os.UserHandle; import android.util.Slog; import android.util.StatsLog; @@ -54,8 +54,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override - public void reportChangeByPackageName(long changeId, String packageName) { - ApplicationInfo appInfo = getApplicationInfo(packageName); + public void reportChangeByPackageName(long changeId, String packageName, int userId) { + ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return; } @@ -80,8 +80,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override - public boolean isChangeEnabledByPackageName(long changeId, String packageName) { - ApplicationInfo appInfo = getApplicationInfo(packageName); + public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) { + ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return true; } @@ -96,7 +96,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } boolean enabled = true; for (String packageName : packages) { - enabled = enabled && isChangeEnabledByPackageName(changeId, packageName); + enabled = enabled && isChangeEnabledByPackageName(changeId, packageName, + UserHandle.getUserId(uid)); } return enabled; } @@ -127,10 +128,9 @@ public class PlatformCompat extends IPlatformCompat.Stub { mChangeReporter.resetReportedChanges(appInfo.uid); } - private ApplicationInfo getApplicationInfo(String packageName) { + private ApplicationInfo getApplicationInfo(String packageName, int userId) { try { - return mContext.getPackageManager().getApplicationInfoAsUser(packageName, 0, - Process.myUid()); + return mContext.getPackageManager().getApplicationInfoAsUser(packageName, 0, userId); } catch (PackageManager.NameNotFoundException e) { Slog.e(TAG, "No installed package " + packageName); } diff --git a/services/core/java/com/android/server/compat/PlatformCompatNative.java b/services/core/java/com/android/server/compat/PlatformCompatNative.java index 839967139baae..85dfbf411667a 100644 --- a/services/core/java/com/android/server/compat/PlatformCompatNative.java +++ b/services/core/java/com/android/server/compat/PlatformCompatNative.java @@ -29,8 +29,8 @@ public class PlatformCompatNative extends IPlatformCompatNative.Stub { } @Override - public void reportChangeByPackageName(long changeId, String packageName) { - mPlatformCompat.reportChangeByPackageName(changeId, packageName); + public void reportChangeByPackageName(long changeId, String packageName, int userId) { + mPlatformCompat.reportChangeByPackageName(changeId, packageName, userId); } @Override @@ -39,8 +39,8 @@ public class PlatformCompatNative extends IPlatformCompatNative.Stub { } @Override - public boolean isChangeEnabledByPackageName(long changeId, String packageName) { - return mPlatformCompat.isChangeEnabledByPackageName(changeId, packageName); + public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) { + return mPlatformCompat.isChangeEnabledByPackageName(changeId, packageName, userId); } @Override diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index c4adc035d6139..21bcaa87431f2 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4178,7 +4178,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private boolean passwordQualityInvocationOrderCheckEnabled(String packageName, int userId) { try { return mIPlatformCompat.isChangeEnabledByPackageName(ADMIN_APP_PASSWORD_COMPLEXITY, - packageName); + packageName, userId); } catch (RemoteException e) { Log.e(LOG_TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e); } From e4bf3393f099bea34a4b49e1da3e6527497196c1 Mon Sep 17 00:00:00 2001 From: Ned Burns Date: Thu, 24 Oct 2019 13:35:47 -0400 Subject: [PATCH 028/182] Mark BiometricUnlockController as @Singleton We were creating more than one, which was causing NPEs. Test: atest Bug: 143258869 Change-Id: I500fdb62a53ab95a532777a667933c93a140b91b (cherry picked from commit cb235b232abb0c225f43ebc906ddc76569018f57) --- .../systemui/statusbar/phone/BiometricUnlockController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index bd3d848eaf7f5..ffcbc40e7b706 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -47,10 +47,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; +import javax.inject.Singleton; /** * Controller which coordinates all the biometric unlocking actions with the UI. */ +@Singleton public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { private static final String TAG = "BiometricUnlockCtrl"; From 13df8146aae61a201c6a5cfc1090092077d9336b Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 25 Oct 2019 18:47:50 +0800 Subject: [PATCH 029/182] Ensure next home activity is ready before finish FallbackHome NexusLaunch could be created but haven't idle before we destroy FallbackHome, add more state check for it. Bug: 143199498 Test: atest ActivityRecordTests Change-Id: Icbe436afd66d2c2e5a9b884433e2fea84c119513 (cherry picked from commit 5901007d16312cb4f183afbc8b1a35b753dcb28f) --- .../core/java/com/android/server/wm/ActivityRecord.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 3853841b63ffa..4692fcf386729 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -299,10 +299,10 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; -import com.android.internal.R; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.XmlUtils; import com.android.server.AttributeCache; @@ -2724,9 +2724,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // TODO(b/137329632): Exclude current activity when looking for the next one with // ActivityDisplay#topRunningActivity(). final ActivityRecord next = display.topRunningActivity(); - final boolean isLastStackOverEmptyHome = - next == null && stack.isFocusedStackOnDisplay() && display.getHomeStack() != null; - if (isLastStackOverEmptyHome) { + final boolean isLastStackOverUnreadyHome = display.getHomeStack() != null + && (next == null || (next.isActivityTypeHome() && !next.isState(RESUMED))) + && stack.isFocusedStackOnDisplay(); + if (isLastStackOverUnreadyHome) { // Don't destroy activity immediately if this is the last activity on the display and // the display contains home stack. Although there is no next activity at the moment, // another home activity should be started later. Keep this activity alive until next From d16058e1a6ec1b5314cbe45661c53e1983b13a75 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 25 Oct 2019 12:28:06 -0700 Subject: [PATCH 030/182] Revert "Move DozeServiceHost out of StatusBar." Fixes: 143334366 Test: manual This reverts commit a85704052b7a909f43f9d26cb9ba1ddb3896940e. Change-Id: Ia5b5302a659f073cff6ab557bd70bfdbb070d86d (cherry picked from commit 22b934f1d8311bc8eaa9ea8a6a19dc65091bd08a) --- .../systemui/statusbar/car/CarStatusBar.java | 11 +- .../systemui/dagger/DependencyBinder.java | 9 +- .../phone/BiometricUnlockController.java | 6 +- .../statusbar/phone/DozeParameters.java | 8 +- .../statusbar/phone/DozeScrimController.java | 2 - .../statusbar/phone/DozeServiceHost.java | 465 ------------------ .../statusbar/phone/ScrimController.java | 2 - .../systemui/statusbar/phone/StatusBar.java | 357 ++++++++++++-- .../statusbar/phone/DozeServiceHostTest.java | 224 --------- .../statusbar/phone/StatusBarTest.java | 108 +++- 10 files changed, 431 insertions(+), 761 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 52aaf4f41eec4..16073ae5e4a6a 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -32,7 +32,6 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.PowerManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.GestureDetector; @@ -110,8 +109,6 @@ import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.DozeParameters; -import com.android.systemui.statusbar.phone.DozeScrimController; -import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LightBarController; @@ -304,9 +301,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt ScrimController scrimController, Lazy lockscreenWallpaperLazy, Lazy biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - DozeScrimController dozeScrimController, /* Car Settings injected components. */ NavigationBarViewFactory navigationBarViewFactory) { @@ -370,10 +364,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt dozeParameters, scrimController, lockscreenWallpaperLazy, - biometricUnlockControllerLazy, - dozeServiceHost, - powerManager, - dozeScrimController); + biometricUnlockControllerLazy); mScrimController = scrimController; mNavigationBarViewFactory = navigationBarViewFactory; } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java index 9032c6fc86390..6674c12ab6138 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java @@ -20,7 +20,6 @@ import com.android.systemui.ActivityStarterDelegate; import com.android.systemui.appops.AppOpsController; import com.android.systemui.appops.AppOpsControllerImpl; import com.android.systemui.classifier.FalsingManagerProxy; -import com.android.systemui.doze.DozeHost; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.FalsingManager; @@ -34,7 +33,6 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl; -import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -243,10 +241,5 @@ public abstract class DependencyBinder { /** */ @Binds - public abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl); - - /** - */ - @Binds - public abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost); + public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index ffcbc40e7b706..033171a28c626 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -55,10 +55,10 @@ import javax.inject.Singleton; @Singleton public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { - private static final String TAG = "BiometricUnlockCtrl"; + private static final String TAG = "BiometricUnlockController"; private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK; private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000; - private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock"; + private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock"; @IntDef(prefix = { "MODE_" }, value = { MODE_NONE, @@ -134,7 +134,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { private final KeyguardBypassController mKeyguardBypassController; private PowerManager.WakeLock mWakeLock; private final KeyguardUpdateMonitor mUpdateMonitor; - private DozeParameters mDozeParameters; + private final DozeParameters mDozeParameters; private final KeyguardStateController mKeyguardStateController; private final StatusBarWindowController mStatusBarWindowController; private final Context mContext; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index bc482353753d9..50d33a70fed52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -24,6 +24,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.MathUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.MainResources; import com.android.systemui.doze.AlwaysOnDisplayPolicy; @@ -187,7 +188,12 @@ public class DozeParameters implements TunerService.Tunable, return; } mControlScreenOffAnimation = controlScreenOffAnimation; - mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation); + getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation); + } + + @VisibleForTesting + protected PowerManager getPowerManager() { + return mPowerManager; } private boolean getBoolean(String propName, int resId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index 1ecc4899d5e70..fe3c04e3cda3d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -29,12 +29,10 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller which handles all the doze animations of the scrims. */ -@Singleton public class DozeScrimController implements StateListener { private static final String TAG = "DozeScrimController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java deleted file mode 100644 index 28543555bf4d3..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * 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.statusbar.phone; - -import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; -import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; - -import android.annotation.NonNull; -import android.os.Bundle; -import android.os.PowerManager; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.doze.DozeEvent; -import com.android.systemui.doze.DozeHost; -import com.android.systemui.doze.DozeLog; -import com.android.systemui.doze.DozeReceiver; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; - -import java.util.ArrayList; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import dagger.Lazy; - -/** - * Implementation of DozeHost for SystemUI. - */ -@Singleton -public final class DozeServiceHost implements DozeHost { - private static final String TAG = "DozeServiceHost"; - private final ArrayList mCallbacks = new ArrayList<>(); - private final DozeLog mDozeLog; - private final PowerManager mPowerManager; - private boolean mAnimateWakeup; - private boolean mAnimateScreenOff; - private boolean mIgnoreTouchWhilePulsing; - private Runnable mPendingScreenOffCallback; - @VisibleForTesting - boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean( - "persist.sysui.wake_performs_auth", true); - private boolean mDozingRequested; - private boolean mDozing; - private boolean mPulsing; - private WakefulnessLifecycle mWakefulnessLifecycle; - private final SysuiStatusBarStateController mStatusBarStateController; - private final DeviceProvisionedController mDeviceProvisionedController; - private final HeadsUpManagerPhone mHeadsUpManagerPhone; - private final BatteryController mBatteryController; - private final ScrimController mScrimController; - private final Lazy mBiometricUnlockControllerLazy; - private BiometricUnlockController mBiometricUnlockController; - private final KeyguardViewMediator mKeyguardViewMediator; - private final AssistManager mAssistManager; - private final DozeScrimController mDozeScrimController; - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final VisualStabilityManager mVisualStabilityManager; - private final PulseExpansionHandler mPulseExpansionHandler; - private final StatusBarWindowController mStatusBarWindowController; - private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - private NotificationIconAreaController mNotificationIconAreaController; - private StatusBarWindowViewController mStatusBarWindowViewController; - private StatusBarWindowView mStatusBarWindow; - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - private NotificationPanelView mNotificationPanel; - private View mAmbientIndicationContainer; - private StatusBar mStatusBar; - - @Inject - public DozeServiceHost(DozeLog dozeLog, PowerManager powerManager, - WakefulnessLifecycle wakefulnessLifecycle, - SysuiStatusBarStateController statusBarStateController, - DeviceProvisionedController deviceProvisionedController, - HeadsUpManagerPhone headsUpManagerPhone, BatteryController batteryController, - ScrimController scrimController, - Lazy biometricUnlockControllerLazy, - KeyguardViewMediator keyguardViewMediator, - AssistManager assistManager, - DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, - VisualStabilityManager visualStabilityManager, - PulseExpansionHandler pulseExpansionHandler, - StatusBarWindowController statusBarWindowController, - NotificationWakeUpCoordinator notificationWakeUpCoordinator) { - super(); - mDozeLog = dozeLog; - mPowerManager = powerManager; - mWakefulnessLifecycle = wakefulnessLifecycle; - mStatusBarStateController = statusBarStateController; - mDeviceProvisionedController = deviceProvisionedController; - mHeadsUpManagerPhone = headsUpManagerPhone; - mBatteryController = batteryController; - mScrimController = scrimController; - mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; - mKeyguardViewMediator = keyguardViewMediator; - mAssistManager = assistManager; - mDozeScrimController = dozeScrimController; - mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mVisualStabilityManager = visualStabilityManager; - mPulseExpansionHandler = pulseExpansionHandler; - mStatusBarWindowController = statusBarWindowController; - mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; - } - - // TODO: we should try to not pass status bar in here if we can avoid it. - - /** - * Initialize instance with objects only available later during execution. - */ - public void initialize(StatusBar statusBar, - NotificationIconAreaController notificationIconAreaController, - StatusBarWindowViewController statusBarWindowViewController, - StatusBarWindowView statusBarWindow, - StatusBarKeyguardViewManager statusBarKeyguardViewManager, - NotificationPanelView notificationPanel, View ambientIndicationContainer) { - mStatusBar = statusBar; - mNotificationIconAreaController = notificationIconAreaController; - mStatusBarWindowViewController = statusBarWindowViewController; - mStatusBarWindow = statusBarWindow; - mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; - mNotificationPanel = notificationPanel; - mAmbientIndicationContainer = ambientIndicationContainer; - mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); - } - - @Override - public String toString() { - return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; - } - - void firePowerSaveChanged(boolean active) { - for (Callback callback : mCallbacks) { - callback.onPowerSaveChanged(active); - } - } - - void fireNotificationPulse(NotificationEntry entry) { - Runnable pulseSuppressedListener = () -> { - entry.setPulseSuppressed(true); - mNotificationIconAreaController.updateAodNotificationIcons(); - }; - for (Callback callback : mCallbacks) { - callback.onNotificationAlerted(pulseSuppressedListener); - } - } - - boolean getDozingRequested() { - return mDozingRequested; - } - - boolean isPulsing() { - return mPulsing; - } - - - @Override - public void addCallback(@NonNull Callback callback) { - mCallbacks.add(callback); - } - - @Override - public void removeCallback(@NonNull Callback callback) { - mCallbacks.remove(callback); - } - - @Override - public void startDozing() { - if (!mDozingRequested) { - mDozingRequested = true; - mDozeLog.traceDozing(mDozing); - updateDozing(); - mStatusBar.updateIsKeyguard(); - } - } - - void updateDozing() { - // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. - boolean - dozing = - mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD - || mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; - // When in wake-and-unlock we may not have received a change to StatusBarState - // but we still should not be dozing, manually set to false. - if (mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK) { - dozing = false; - } - - - mStatusBarStateController.setIsDozing(dozing); - } - - @Override - public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { - if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, - "com.android.systemui:LONG_PRESS"); - mAssistManager.startAssist(new Bundle()); - return; - } - - if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { - mScrimController.setWakeLockScreenSensorActive(true); - } - - if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) { - mStatusBarWindowViewController.suppressWakeUpGesture(true); - } - - boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN - && mWakeLockScreenPerformsAuth; - // Set the state to pulsing, so ScrimController will know what to do once we ask it to - // execute the transition. The pulse callback will then be invoked when the scrims - // are black, indicating that StatusBar is ready to present the rest of the UI. - mPulsing = true; - mDozeScrimController.pulse(new PulseCallback() { - @Override - public void onPulseStarted() { - callback.onPulseStarted(); - mStatusBar.updateNotificationPanelTouchState(); - setPulsing(true); - } - - @Override - public void onPulseFinished() { - mPulsing = false; - callback.onPulseFinished(); - mStatusBar.updateNotificationPanelTouchState(); - mScrimController.setWakeLockScreenSensorActive(false); - if (mStatusBarWindow != null) { - mStatusBarWindowViewController.suppressWakeUpGesture(false); - } - setPulsing(false); - } - - private void setPulsing(boolean pulsing) { - mStatusBarStateController.setPulsing(pulsing); - mStatusBarKeyguardViewManager.setPulsing(pulsing); - mKeyguardViewMediator.setPulsing(pulsing); - mNotificationPanel.setPulsing(pulsing); - mVisualStabilityManager.setPulsing(pulsing); - mStatusBarWindowViewController.setPulsing(pulsing); - mIgnoreTouchWhilePulsing = false; - if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) { - mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */); - } - mStatusBar.updateScrimController(); - mPulseExpansionHandler.setPulsing(pulsing); - mNotificationWakeUpCoordinator.setPulsing(pulsing); - } - }, reason); - // DozeScrimController is in pulse state, now let's ask ScrimController to start - // pulsing and draw the black frame, if necessary. - mStatusBar.updateScrimController(); - } - - @Override - public void stopDozing() { - if (mDozingRequested) { - mDozingRequested = false; - mDozeLog.traceDozing(mDozing); - updateDozing(); - } - } - - @Override - public void onIgnoreTouchWhilePulsing(boolean ignore) { - if (ignore != mIgnoreTouchWhilePulsing) { - mDozeLog.tracePulseTouchDisabledByProx(ignore); - } - mIgnoreTouchWhilePulsing = ignore; - if (mDozing && ignore) { - mStatusBarWindowViewController.cancelCurrentTouch(); - } - } - - @Override - public void dozeTimeTick() { - mNotificationPanel.dozeTimeTick(); - if (mAmbientIndicationContainer instanceof DozeReceiver) { - ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick(); - } - } - - @Override - public boolean isPowerSaveActive() { - return mBatteryController.isAodPowerSave(); - } - - @Override - public boolean isPulsingBlocked() { - return mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; - } - - @Override - public boolean isProvisioned() { - return mDeviceProvisionedController.isDeviceProvisioned() - && mDeviceProvisionedController.isCurrentUserSetup(); - } - - @Override - public boolean isBlockingDoze() { - if (mBiometricUnlockController.hasPendingAuthentication()) { - Log.i(StatusBar.TAG, "Blocking AOD because fingerprint has authenticated"); - return true; - } - return false; - } - - @Override - public void extendPulse(int reason) { - if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { - mScrimController.setWakeLockScreenSensorActive(true); - } - if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) { - mHeadsUpManagerPhone.extendHeadsUp(); - } else { - mDozeScrimController.extendPulse(); - } - } - - @Override - public void stopPulsing() { - if (mDozeScrimController.isPulsing()) { - mDozeScrimController.pulseOutNow(); - } - } - - @Override - public void setAnimateWakeup(boolean animateWakeup) { - if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE - || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) { - // Too late to change the wakeup animation. - return; - } - mAnimateWakeup = animateWakeup; - } - - @Override - public void setAnimateScreenOff(boolean animateScreenOff) { - mAnimateScreenOff = animateScreenOff; - } - - @Override - public void onSlpiTap(float screenX, float screenY) { - if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null - && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { - int[] locationOnScreen = new int[2]; - mAmbientIndicationContainer.getLocationOnScreen(locationOnScreen); - float viewX = screenX - locationOnScreen[0]; - float viewY = screenY - locationOnScreen[1]; - if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth() - && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) { - - // Dispatch a tap - long now = SystemClock.elapsedRealtime(); - MotionEvent ev = MotionEvent.obtain( - now, now, MotionEvent.ACTION_DOWN, screenX, screenY, 0); - mAmbientIndicationContainer.dispatchTouchEvent(ev); - ev.recycle(); - ev = MotionEvent.obtain( - now, now, MotionEvent.ACTION_UP, screenX, screenY, 0); - mAmbientIndicationContainer.dispatchTouchEvent(ev); - ev.recycle(); - } - } - } - - @Override - public void setDozeScreenBrightness(int value) { - mStatusBarWindowController.setDozeScreenBrightness(value); - } - - @Override - public void setAodDimmingScrim(float scrimOpacity) { - mScrimController.setAodFrontScrimAlpha(scrimOpacity); - } - - - - @Override - public void prepareForGentleSleep(Runnable onDisplayOffCallback) { - if (mPendingScreenOffCallback != null) { - Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one."); - } - mPendingScreenOffCallback = onDisplayOffCallback; - mStatusBar.updateScrimController(); - } - - @Override - public void cancelGentleSleep() { - mPendingScreenOffCallback = null; - if (mScrimController.getState() == ScrimState.OFF) { - mStatusBar.updateScrimController(); - } - } - - /** - * When the dozing host is waiting for scrims to fade out to change the display state. - */ - boolean hasPendingScreenOffCallback() { - return mPendingScreenOffCallback != null; - } - - /** - * Executes an nullifies the pending display state callback. - * - * @see #hasPendingScreenOffCallback() - * @see #prepareForGentleSleep(Runnable) - */ - void executePendingScreenOffCallback() { - if (mPendingScreenOffCallback == null) { - return; - } - mPendingScreenOffCallback.run(); - mPendingScreenOffCallback = null; - } - - boolean shouldAnimateWakeup() { - return mAnimateWakeup; - } - - boolean shouldAnimateScreenOff() { - return mAnimateScreenOff; - } - - public void setDozing(boolean dozing) { - mDozing = dozing; - } - - boolean getIgnoreTouchWhilePulsing() { - return mIgnoreTouchWhilePulsing; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 35039a0d74f94..6064fbedf63dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -60,13 +60,11 @@ import java.lang.annotation.RetentionPolicy; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls both the scrim behind the notifications and in front of the notifications (when a * security method gets shown). */ -@Singleton public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index b8adfea8b0591..4e0af647da10f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -50,6 +50,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; @@ -156,8 +157,10 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.doze.DozeEvent; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; +import com.android.systemui.doze.DozeReceiver; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.KeyguardSliceProvider; @@ -344,7 +347,7 @@ public class StatusBar extends SystemUI implements DemoMode, /** * The {@link StatusBarState} of the status bar. */ - protected int mState; // TODO: remove this. Just use StatusBarStateController + protected int mState; protected boolean mBouncerShowing; private PhoneStatusBarPolicy mIconPolicy; @@ -370,7 +373,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected StatusBarWindowController mStatusBarWindowController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @VisibleForTesting - DozeServiceHost mDozeServiceHost; + DozeServiceHost mDozeServiceHost = new DozeServiceHost(); private boolean mWakeUpComingFromTouch; private PointF mWakeUpTouchLocation; @@ -490,6 +493,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final UiOffloadThread mUiOffloadThread; protected boolean mDozing; + private boolean mDozingRequested; private final NotificationMediaManager mMediaManager; private final NotificationLockscreenUserManager mLockscreenUserManager; @@ -608,6 +612,7 @@ public class StatusBar extends SystemUI implements DemoMode, private ActivityLaunchAnimator mActivityLaunchAnimator; protected StatusBarNotificationPresenter mPresenter; private NotificationActivityStarter mNotificationActivityStarter; + private boolean mPulsing; private final BubbleController mBubbleController; private final BubbleController.BubbleExpandListener mBubbleExpandListener; @@ -688,10 +693,7 @@ public class StatusBar extends SystemUI implements DemoMode, DozeParameters dozeParameters, ScrimController scrimController, Lazy lockscreenWallpaperLazy, - Lazy biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - DozeScrimController dozeScrimController) { + Lazy biometricUnlockControllerLazy) { super(context); mFeatureFlags = featureFlags; mLightBarController = lightBarController; @@ -748,12 +750,9 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarWindowController = statusBarWindowController; mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder; mNotifLog = notifLog; - mDozeServiceHost = dozeServiceHost; - mPowerManager = powerManager; mDozeParameters = dozeParameters; mScrimController = scrimController; mLockscreenWallpaperLazy = lockscreenWallpaperLazy; - mDozeScrimController = dozeScrimController; mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; mBubbleExpandListener = @@ -806,6 +805,7 @@ public class StatusBar extends SystemUI implements DemoMode, mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @@ -905,9 +905,6 @@ public class StatusBar extends SystemUI implements DemoMode, startKeyguard(); mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); - mDozeServiceHost.initialize(this, mNotificationIconAreaController, - mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager, - mNotificationPanel, mAmbientIndicationContainer); putComponent(DozeHost.class, mDozeServiceHost); mScreenPinningRequest = new ScreenPinningRequest(mContext); @@ -1072,6 +1069,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf, mHeadsUpManager, mNotificationIconAreaController, mScrimController); + mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog); BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop); mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), @@ -1732,7 +1730,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (isDozing() && isHeadsUp) { entry.setPulseSuppressed(false); mDozeServiceHost.fireNotificationPulse(entry); - if (mDozeServiceHost.isPulsing()) { + if (mPulsing) { mDozeScrimController.cancelPendingPulseTimeout(); } } @@ -1764,7 +1762,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public boolean isPulsing() { - return mDozeServiceHost.isPulsing(); + return mPulsing; } public boolean hideStatusBarIconsWhenExpanded() { @@ -2827,7 +2825,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP && mKeyguardStateController.canDismissLockScreen() && !mStatusBarStateController.leaveOpenOnKeyguardHide() - && mDozeServiceHost.isPulsing()) { + && isPulsing()) { // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse. // TODO: Factor this transition out of BiometricUnlockController. mBiometricUnlockController.startWakeAndUnlock( @@ -3158,7 +3156,7 @@ public class StatusBar extends SystemUI implements DemoMode, return mState == StatusBarState.FULLSCREEN_USER_SWITCHER; } - boolean updateIsKeyguard() { + private boolean updateIsKeyguard() { boolean wakeAndUnlocking = mBiometricUnlockController.getMode() == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; @@ -3166,8 +3164,8 @@ public class StatusBar extends SystemUI implements DemoMode, // there's no surface we can show to the user. Note that the device goes fully interactive // late in the transition, so we also allow the device to start dozing once the screen has // turned off fully. - boolean keyguardForDozing = mDozeServiceHost.getDozingRequested() - && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); + boolean keyguardForDozing = mDozingRequested && + (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested() || keyguardForDozing) && !wakeAndUnlocking; if (keyguardForDozing) { @@ -3583,7 +3581,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void onStateChanged(int newState) { mState = newState; updateReportRejectedTouchVisibility(); - mDozeServiceHost.updateDozing(); + updateDozing(); updateTheme(); mNavigationBarController.touchAutoDim(mDisplayId); Trace.beginSection("StatusBar#updateKeyguardState"); @@ -3621,23 +3619,36 @@ public class StatusBar extends SystemUI implements DemoMode, public void onDozingChanged(boolean isDozing) { Trace.beginSection("StatusBar#updateDozing"); mDozing = isDozing; - mDozeServiceHost.setDozing(mDozing); // Collapse the notification panel if open - boolean dozingAnimated = mDozeServiceHost.getDozingRequested() - && mDozeParameters.shouldControlScreenOff(); + boolean dozingAnimated = mDozingRequested && mDozeParameters.shouldControlScreenOff(); mNotificationPanel.resetViews(dozingAnimated); updateQsExpansionEnabled(); mKeyguardViewMediator.setDozing(mDozing); mEntryManager.updateNotifications("onDozingChanged"); - mDozeServiceHost.updateDozing(); + updateDozingState(); updateScrimController(); updateReportRejectedTouchVisibility(); Trace.endSection(); } + private void updateDozing() { + // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. + boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD + || mBiometricUnlockController.getMode() + == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; + // When in wake-and-unlock we may not have received a change to mState + // but we still should not be dozing, manually set to false. + if (mBiometricUnlockController.getMode() == + BiometricUnlockController.MODE_WAKE_AND_UNLOCK) { + dozing = false; + } + + mStatusBarStateController.setIsDozing(dozing); + } + private void updateKeyguardState() { mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(), mStatusBarKeyguardViewManager.isOccluded()); @@ -3862,11 +3873,10 @@ public class StatusBar extends SystemUI implements DemoMode, * collapse the panel after we expanded it, and thus we would end up with a blank * Keyguard. */ - void updateNotificationPanelTouchState() { + private void updateNotificationPanelTouchState() { boolean goingToSleepWithoutAnimation = isGoingToSleep() && !mDozeParameters.shouldControlScreenOff(); - boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing()) - || goingToSleepWithoutAnimation; + boolean disabled = (!mDeviceInteractive && !mPulsing) || goingToSleepWithoutAnimation; mNotificationPanel.setTouchAndAnimationDisabled(disabled); mNotificationIconAreaController.setAnimationsEnabled(!disabled); } @@ -4016,7 +4026,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public void notifyBiometricAuthModeChanged() { - mDozeServiceHost.updateDozing(); + updateDozing(); updateScrimController(); mStatusBarWindowViewController.onBiometricAuthModeChanged( mBiometricUnlockController.isWakeAndUnlock(), @@ -4052,7 +4062,7 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } else if (mBrightnessMirrorVisible) { mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); - } else if (mDozeServiceHost.isPulsing()) { + } else if (isPulsing()) { mScrimController.transitionTo(ScrimState.PULSING, mDozeScrimController.getScrimCallback()); } else if (mDozeServiceHost.hasPendingScreenOffCallback()) { @@ -4082,8 +4092,295 @@ public class StatusBar extends SystemUI implements DemoMode, return mStatusBarKeyguardViewManager.isShowing(); } + @VisibleForTesting + final class DozeServiceHost implements DozeHost { + private final ArrayList mCallbacks = new ArrayList<>(); + private boolean mAnimateWakeup; + private boolean mAnimateScreenOff; + private boolean mIgnoreTouchWhilePulsing; + private Runnable mPendingScreenOffCallback; + @VisibleForTesting + boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean( + "persist.sysui.wake_performs_auth", true); + + @Override + public String toString() { + return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; + } + + public void firePowerSaveChanged(boolean active) { + for (Callback callback : mCallbacks) { + callback.onPowerSaveChanged(active); + } + } + + public void fireNotificationPulse(NotificationEntry entry) { + Runnable pulseSupressedListener = () -> { + entry.setPulseSuppressed(true); + mNotificationIconAreaController.updateAodNotificationIcons(); + }; + for (Callback callback : mCallbacks) { + callback.onNotificationAlerted(pulseSupressedListener); + } + } + + @Override + public void addCallback(@NonNull Callback callback) { + mCallbacks.add(callback); + } + + @Override + public void removeCallback(@NonNull Callback callback) { + mCallbacks.remove(callback); + } + + @Override + public void startDozing() { + if (!mDozingRequested) { + mDozingRequested = true; + mDozeLog.traceDozing(mDozing); + updateDozing(); + updateIsKeyguard(); + } + } + + @Override + public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { + if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) { + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui:LONG_PRESS"); + startAssist(new Bundle()); + return; + } + + if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mScrimController.setWakeLockScreenSensorActive(true); + } + + if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) { + mStatusBarWindowViewController.suppressWakeUpGesture(true); + } + + boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN + && mWakeLockScreenPerformsAuth; + // Set the state to pulsing, so ScrimController will know what to do once we ask it to + // execute the transition. The pulse callback will then be invoked when the scrims + // are black, indicating that StatusBar is ready to present the rest of the UI. + mPulsing = true; + mDozeScrimController.pulse(new PulseCallback() { + @Override + public void onPulseStarted() { + callback.onPulseStarted(); + updateNotificationPanelTouchState(); + setPulsing(true); + } + + @Override + public void onPulseFinished() { + mPulsing = false; + callback.onPulseFinished(); + updateNotificationPanelTouchState(); + mScrimController.setWakeLockScreenSensorActive(false); + if (mStatusBarWindow != null) { + mStatusBarWindowViewController.suppressWakeUpGesture(false); + } + setPulsing(false); + } + + private void setPulsing(boolean pulsing) { + mStatusBarStateController.setPulsing(pulsing); + mStatusBarKeyguardViewManager.setPulsing(pulsing); + mKeyguardViewMediator.setPulsing(pulsing); + mNotificationPanel.setPulsing(pulsing); + mVisualStabilityManager.setPulsing(pulsing); + mStatusBarWindowViewController.setPulsing(pulsing); + mIgnoreTouchWhilePulsing = false; + if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) { + mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */); + } + updateScrimController(); + mPulseExpansionHandler.setPulsing(pulsing); + mWakeUpCoordinator.setPulsing(pulsing); + } + }, reason); + // DozeScrimController is in pulse state, now let's ask ScrimController to start + // pulsing and draw the black frame, if necessary. + updateScrimController(); + } + + @Override + public void stopDozing() { + if (mDozingRequested) { + mDozingRequested = false; + mDozeLog.traceDozing(mDozing); + updateDozing(); + } + } + + @Override + public void onIgnoreTouchWhilePulsing(boolean ignore) { + if (ignore != mIgnoreTouchWhilePulsing) { + mDozeLog.tracePulseTouchDisabledByProx(ignore); + } + mIgnoreTouchWhilePulsing = ignore; + if (isDozing() && ignore) { + mStatusBarWindowViewController.cancelCurrentTouch(); + } + } + + @Override + public void dozeTimeTick() { + mNotificationPanel.dozeTimeTick(); + if (mAmbientIndicationContainer instanceof DozeReceiver) { + ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick(); + } + } + + @Override + public boolean isPowerSaveActive() { + return mBatteryController.isAodPowerSave(); + } + + @Override + public boolean isPulsingBlocked() { + return mBiometricUnlockController.getMode() + == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; + } + + @Override + public boolean isProvisioned() { + return mDeviceProvisionedController.isDeviceProvisioned() + && mDeviceProvisionedController.isCurrentUserSetup(); + } + + @Override + public boolean isBlockingDoze() { + if (mBiometricUnlockController.hasPendingAuthentication()) { + Log.i(TAG, "Blocking AOD because fingerprint has authenticated"); + return true; + } + return false; + } + + @Override + public void extendPulse(int reason) { + if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mScrimController.setWakeLockScreenSensorActive(true); + } + if (mDozeScrimController.isPulsing() && mHeadsUpManager.hasNotifications()) { + mHeadsUpManager.extendHeadsUp(); + } else { + mDozeScrimController.extendPulse(); + } + } + + @Override + public void stopPulsing() { + if (mDozeScrimController.isPulsing()) { + mDozeScrimController.pulseOutNow(); + } + } + + @Override + public void setAnimateWakeup(boolean animateWakeup) { + if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) { + // Too late to change the wakeup animation. + return; + } + mAnimateWakeup = animateWakeup; + } + + @Override + public void setAnimateScreenOff(boolean animateScreenOff) { + mAnimateScreenOff = animateScreenOff; + } + + @Override + public void onSlpiTap(float screenX, float screenY) { + if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null + && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { + mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2); + float viewX = screenX - mTmpInt2[0]; + float viewY = screenY - mTmpInt2[1]; + if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth() + && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) { + dispatchTap(mAmbientIndicationContainer, viewX, viewY); + } + } + } + + @Override + public void setDozeScreenBrightness(int value) { + mStatusBarWindowController.setDozeScreenBrightness(value); + } + + @Override + public void setAodDimmingScrim(float scrimOpacity) { + mScrimController.setAodFrontScrimAlpha(scrimOpacity); + } + + @Override + public void prepareForGentleSleep(Runnable onDisplayOffCallback) { + if (mPendingScreenOffCallback != null) { + Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one."); + } + mPendingScreenOffCallback = onDisplayOffCallback; + updateScrimController(); + } + + @Override + public void cancelGentleSleep() { + mPendingScreenOffCallback = null; + if (mScrimController.getState() == ScrimState.OFF) { + updateScrimController(); + } + } + + /** + * When the dozing host is waiting for scrims to fade out to change the display state. + */ + boolean hasPendingScreenOffCallback() { + return mPendingScreenOffCallback != null; + } + + /** + * Executes an nullifies the pending display state callback. + * + * @see #hasPendingScreenOffCallback() + * @see #prepareForGentleSleep(Runnable) + */ + void executePendingScreenOffCallback() { + if (mPendingScreenOffCallback == null) { + return; + } + mPendingScreenOffCallback.run(); + mPendingScreenOffCallback = null; + } + + private void dispatchTap(View view, float x, float y) { + long now = SystemClock.elapsedRealtime(); + dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN); + dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP); + } + + private void dispatchTouchEvent(View view, float x, float y, long now, int action) { + MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */); + view.dispatchTouchEvent(ev); + ev.recycle(); + } + + private boolean shouldAnimateWakeup() { + return mAnimateWakeup; + } + + public boolean shouldAnimateScreenOff() { + return mAnimateScreenOff; + } + } + public boolean shouldIgnoreTouch() { - return isDozing() && mDozeServiceHost.getIgnoreTouchWhilePulsing(); + return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing; } // Begin Extra BaseStatusBar methods. @@ -4110,7 +4407,7 @@ public class StatusBar extends SystemUI implements DemoMode, private boolean mVisibleToUser; protected DevicePolicyManager mDevicePolicyManager; - private final PowerManager mPowerManager; + protected PowerManager mPowerManager; protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; protected KeyguardManager mKeyguardManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java deleted file mode 100644 index b05172c6d7c2e..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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.statusbar.phone; - -import static org.junit.Assert.assertFalse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.os.PowerManager; -import android.testing.AndroidTestingRunner; -import android.view.View; - -import androidx.test.filters.SmallTest; - -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.doze.DozeEvent; -import com.android.systemui.doze.DozeHost; -import com.android.systemui.doze.DozeLog; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.StatusBarStateControllerImpl; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; - -import dagger.Lazy; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -public class DozeServiceHostTest extends SysuiTestCase { - - private DozeServiceHost mDozeServiceHost; - - @Mock private HeadsUpManagerPhone mHeadsUpManager; - @Mock private ScrimController mScrimController; - @Mock private DozeScrimController mDozeScrimController; - @Mock private Lazy mBiometricUnlockControllerLazy; - @Mock private VisualStabilityManager mVisualStabilityManager; - @Mock private KeyguardViewMediator mKeyguardViewMediator; - @Mock private StatusBarStateControllerImpl mStatusBarStateController; - @Mock private BatteryController mBatteryController; - @Mock private DeviceProvisionedController mDeviceProvisionedController; - @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock private AssistManager mAssistManager; - @Mock private DozeLog mDozeLog; - @Mock private PulseExpansionHandler mPulseExpansionHandler; - @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - @Mock private StatusBarWindowController mStatusBarWindowController; - @Mock private PowerManager mPowerManager; - @Mock private WakefulnessLifecycle mWakefullnessLifecycle; - @Mock private StatusBar mStatusBar; - @Mock private NotificationIconAreaController mNotificationIconAreaController; - @Mock private StatusBarWindowViewController mStatusBarWindowViewController; - @Mock private StatusBarWindowView mStatusBarWindow; - @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - @Mock private NotificationPanelView mNotificationPanel; - @Mock private View mAmbientIndicationContainer; - @Mock private BiometricUnlockController mBiometricUnlockController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController); - mDozeServiceHost = new DozeServiceHost(mDozeLog, mPowerManager, mWakefullnessLifecycle, - mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager, - mBatteryController, mScrimController, mBiometricUnlockControllerLazy, - mKeyguardViewMediator, mAssistManager, mDozeScrimController, mKeyguardUpdateMonitor, - mVisualStabilityManager, mPulseExpansionHandler, mStatusBarWindowController, - mNotificationWakeUpCoordinator); - - mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController, - mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager, - mNotificationPanel, mAmbientIndicationContainer); - } - - @Test - public void testStartStopDozing() { - when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); - when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - - assertFalse(mDozeServiceHost.getDozingRequested()); - - mDozeServiceHost.startDozing(); - verify(mStatusBarStateController).setIsDozing(eq(true)); - verify(mStatusBar).updateIsKeyguard(); - - mDozeServiceHost.stopDozing(); - verify(mStatusBarStateController).setIsDozing(eq(false)); - } - - - @Test - public void testPulseWhileDozing_updatesScrimController() { - mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); - mStatusBar.showKeyguardImpl(); - - // Keep track of callback to be able to stop the pulse -// DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; -// doAnswer(invocation -> { -// pulseCallback[0] = invocation.getArgument(0); -// return null; -// }).when(mDozeScrimController).pulse(any(), anyInt()); - - // Starting a pulse should change the scrim controller to the pulsing state - mDozeServiceHost.pulseWhileDozing(new DozeHost.PulseCallback() { - @Override - public void onPulseStarted() { - } - - @Override - public void onPulseFinished() { - } - }, DozeEvent.PULSE_REASON_NOTIFICATION); - - ArgumentCaptor pulseCallbackArgumentCaptor = - ArgumentCaptor.forClass(DozeHost.PulseCallback.class); - - verify(mDozeScrimController).pulse( - pulseCallbackArgumentCaptor.capture(), eq(DozeEvent.PULSE_REASON_NOTIFICATION)); - verify(mStatusBar).updateScrimController(); - reset(mStatusBar); - - pulseCallbackArgumentCaptor.getValue().onPulseFinished(); - assertFalse(mDozeScrimController.isPulsing()); - verify(mStatusBar).updateScrimController(); - } - - - @Test - public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() { - // Keep track of callback to be able to stop the pulse - final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; - doAnswer(invocation -> { - pulseCallback[0] = invocation.getArgument(0); - return null; - }).when(mDozeScrimController).pulse(any(), anyInt()); - - // Starting a pulse while docking should suppress wakeup gesture - mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), - DozeEvent.PULSE_REASON_DOCKING); - verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true)); - - // Ending a pulse should restore wakeup gesture - pulseCallback[0].onPulseFinished(); - verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false)); - } - - @Test - public void testPulseWhileDozing_notifyAuthInterrupt() { - HashSet reasonsWantingAuth = new HashSet<>( - Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN)); - HashSet reasonsSkippingAuth = new HashSet<>( - Arrays.asList(DozeEvent.PULSE_REASON_INTENT, - DozeEvent.PULSE_REASON_NOTIFICATION, - DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, - DozeEvent.REASON_SENSOR_PICKUP, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, - DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, - DozeEvent.PULSE_REASON_DOCKING, - DozeEvent.REASON_SENSOR_WAKE_UP, - DozeEvent.REASON_SENSOR_TAP)); - HashSet reasonsThatDontPulse = new HashSet<>( - Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, - DozeEvent.REASON_SENSOR_TAP)); - - doAnswer(invocation -> { - DozeHost.PulseCallback callback = invocation.getArgument(0); - callback.onPulseStarted(); - return null; - }).when(mDozeScrimController).pulse(any(), anyInt()); - - mDozeServiceHost.mWakeLockScreenPerformsAuth = true; - for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { - reset(mKeyguardUpdateMonitor); - mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i); - if (reasonsWantingAuth.contains(i)) { - verify(mKeyguardUpdateMonitor).onAuthInterruptDetected(eq(true)); - } else if (reasonsSkippingAuth.contains(i) || reasonsThatDontPulse.contains(i)) { - verify(mKeyguardUpdateMonitor, never()).onAuthInterruptDetected(eq(true)); - } else { - throw new AssertionError("Reason " + i + " isn't specified as wanting or skipping" - + " passive auth. Please consider how this pulse reason should behave."); - } - } - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 66c01ca584914..f5e92e4f31818 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -85,6 +85,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.doze.DozeEvent; +import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -143,6 +145,9 @@ import org.mockito.MockitoAnnotations; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import dagger.Lazy; @@ -226,7 +231,6 @@ public class StatusBarTest extends SysuiTestCase { @Mock private DozeParameters mDozeParameters; @Mock private Lazy mLockscreenWallpaperLazy; @Mock private LockscreenWallpaper mLockscreenWallpaper; - @Mock private DozeServiceHost mDozeServiceHost; @Mock private LinearLayout mLockIconContainer; @Mock private ViewMediatorCallback mKeyguardVieMediatorCallback; @@ -361,10 +365,7 @@ public class StatusBarTest extends SysuiTestCase { mDozeParameters, mScrimController, mLockscreenWallpaperLazy, - mBiometricUnlockControllerLazy, - mDozeServiceHost, - mPowerManager, - mDozeScrimController); + mBiometricUnlockControllerLazy); when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn( mLockIconContainer); @@ -387,6 +388,7 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController; mStatusBar.mPresenter = mNotificationPresenter; mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController; + mStatusBar.mPowerManager = mPowerManager; mStatusBar.mBarService = mBarService; mStatusBar.mStackScroller = mStackScroller; mStatusBar.mStatusBarWindowViewController = mStatusBarWindowViewController; @@ -755,17 +757,82 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); mStatusBar.showKeyguardImpl(); + // Keep track of callback to be able to stop the pulse + DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; + doAnswer(invocation -> { + pulseCallback[0] = invocation.getArgument(0); + return null; + }).when(mDozeScrimController).pulse(any(), anyInt()); + // Starting a pulse should change the scrim controller to the pulsing state - when(mDozeServiceHost.isPulsing()).thenReturn(true); - mStatusBar.updateScrimController(); + mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), + DozeEvent.PULSE_REASON_NOTIFICATION); verify(mScrimController).transitionTo(eq(ScrimState.PULSING), any()); // Ending a pulse should take it back to keyguard state - when(mDozeServiceHost.isPulsing()).thenReturn(false); - mStatusBar.updateScrimController(); + pulseCallback[0].onPulseFinished(); verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD)); } + @Test + public void testPulseWhileDozing_notifyAuthInterrupt() { + HashSet reasonsWantingAuth = new HashSet<>( + Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN)); + HashSet reasonsSkippingAuth = new HashSet<>( + Arrays.asList(DozeEvent.PULSE_REASON_INTENT, + DozeEvent.PULSE_REASON_NOTIFICATION, + DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, + DozeEvent.REASON_SENSOR_PICKUP, + DozeEvent.REASON_SENSOR_DOUBLE_TAP, + DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, + DozeEvent.PULSE_REASON_DOCKING, + DozeEvent.REASON_SENSOR_WAKE_UP, + DozeEvent.REASON_SENSOR_TAP)); + HashSet reasonsThatDontPulse = new HashSet<>( + Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP, + DozeEvent.REASON_SENSOR_DOUBLE_TAP, + DozeEvent.REASON_SENSOR_TAP)); + + doAnswer(invocation -> { + DozeHost.PulseCallback callback = invocation.getArgument(0); + callback.onPulseStarted(); + return null; + }).when(mDozeScrimController).pulse(any(), anyInt()); + + mStatusBar.mDozeServiceHost.mWakeLockScreenPerformsAuth = true; + for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { + reset(mKeyguardUpdateMonitor); + mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i); + if (reasonsWantingAuth.contains(i)) { + verify(mKeyguardUpdateMonitor).onAuthInterruptDetected(eq(true)); + } else if (reasonsSkippingAuth.contains(i) || reasonsThatDontPulse.contains(i)) { + verify(mKeyguardUpdateMonitor, never()).onAuthInterruptDetected(eq(true)); + } else { + throw new AssertionError("Reason " + i + " isn't specified as wanting or skipping" + + " passive auth. Please consider how this pulse reason should behave."); + } + } + } + + @Test + public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() { + // Keep track of callback to be able to stop the pulse + final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; + doAnswer(invocation -> { + pulseCallback[0] = invocation.getArgument(0); + return null; + }).when(mDozeScrimController).pulse(any(), anyInt()); + + // Starting a pulse while docking should suppress wakeup gesture + mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), + DozeEvent.PULSE_REASON_DOCKING); + verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true)); + + // Ending a pulse should restore wakeup gesture + pulseCallback[0].onPulseFinished(); + verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false)); + } + @Test public void testSetState_changesIsFullScreenUserSwitcherState() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); @@ -791,18 +858,28 @@ public class StatusBarTest extends SysuiTestCase { verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER)); } + @Test + public void testStartStopDozing() { + mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); + when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); + + mStatusBar.mDozeServiceHost.startDozing(); + verify(mStatusBarStateController).setIsDozing(eq(true)); + + mStatusBar.mDozeServiceHost.stopDozing(); + verify(mStatusBarStateController).setIsDozing(eq(false)); + } + @Test public void testOnStartedWakingUp_isNotDozing() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - when(mDozeServiceHost.getDozingRequested()).thenReturn(true); - mStatusBar.updateIsKeyguard(); - // TODO: mNotificationPanelView.expand(false) gets called twice. Should be once. - verify(mNotificationPanelView, times(2)).expand(eq(false)); + mStatusBar.mDozeServiceHost.startDozing(); + verify(mStatusBarStateController).setIsDozing(eq(true)); clearInvocations(mNotificationPanelView); mStatusBar.mWakefulnessObserver.onStartedWakingUp(); - verify(mDozeServiceHost).stopDozing(); + verify(mStatusBarStateController).setIsDozing(eq(false)); verify(mNotificationPanelView).expand(eq(false)); } @@ -810,8 +887,7 @@ public class StatusBarTest extends SysuiTestCase { public void testOnStartedWakingUp_doesNotDismissBouncer_whenPulsing() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - when(mDozeServiceHost.getDozingRequested()).thenReturn(true); - mStatusBar.updateIsKeyguard(); + mStatusBar.mDozeServiceHost.startDozing(); clearInvocations(mNotificationPanelView); mStatusBar.setBouncerShowing(true); From 2362e55694aa87b7cdb72703dc16a3860e26f151 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 25 Oct 2019 11:39:10 -0700 Subject: [PATCH 031/182] Temporarily do not remove biometric view when animating to credential When animating to device credential, the biometric view animates its translation and opacity, then removes itself from the layout. Upon removal, we currently remove all things from the handler. This includes (racily) the callback to display device credential UI. Thus, temporarily do not remove the view. Will fix this properly in a follow-up CL. Test: manual test with BiometricPromptDemo 10+ times Test: atest com.android.systemui.biometrics Bug: 143174046 Change-Id: Ibdf7c17514062a08ff3919fad2c798f9127e4234 (cherry picked from commit bf2bf1bc09fef50cb84ab9c7c5c4096a8e2491d4) --- .../com/android/systemui/biometrics/AuthBiometricView.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index d20cd72f07126..d38b31ac9fca6 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -23,7 +23,6 @@ import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.admin.DevicePolicyManager; import android.content.Context; import android.hardware.biometrics.BiometricPrompt; import android.os.Bundle; @@ -33,7 +32,6 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; -import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; import android.widget.Button; import android.widget.ImageView; @@ -41,7 +39,6 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.widget.LockPatternUtils; import com.android.systemui.R; import java.lang.annotation.Retention; @@ -404,7 +401,7 @@ public abstract class AuthBiometricView extends LinearLayout { public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if (biometricView.getParent() != null) { - ((ViewGroup) biometricView.getParent()).removeView(biometricView); + // ((ViewGroup) biometricView.getParent()).removeView(biometricView); } mSize = newSize; } From bb75488fdb2e49d6784f879365fd6f7acc15d321 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 25 Oct 2019 18:47:50 +0800 Subject: [PATCH 032/182] Ensure next home activity is ready before finish FallbackHome NexusLaunch could be created but haven't idle before we destroy FallbackHome, add more state check for it. Bug: 143199498 Test: atest ActivityRecordTests Change-Id: Icbe436afd66d2c2e5a9b884433e2fea84c119513 (cherry picked from commit 5901007d16312cb4f183afbc8b1a35b753dcb28f) --- .../core/java/com/android/server/wm/ActivityRecord.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 0d9570697dbfd..f36d97c4d1237 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -297,10 +297,10 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; -import com.android.internal.R; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.XmlUtils; import com.android.server.AttributeCache; @@ -2676,9 +2676,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // TODO(b/137329632): Exclude current activity when looking for the next one with // ActivityDisplay#topRunningActivity(). final ActivityRecord next = display.topRunningActivity(); - final boolean isLastStackOverEmptyHome = - next == null && stack.isFocusedStackOnDisplay() && display.getHomeStack() != null; - if (isLastStackOverEmptyHome) { + final boolean isLastStackOverUnreadyHome = display.getHomeStack() != null + && (next == null || (next.isActivityTypeHome() && !next.isState(RESUMED))) + && stack.isFocusedStackOnDisplay(); + if (isLastStackOverUnreadyHome) { // Don't destroy activity immediately if this is the last activity on the display and // the display contains home stack. Although there is no next activity at the moment, // another home activity should be started later. Keep this activity alive until next From fca1f5b6c836e21793a3224dcd3dc97a631710bd Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 25 Oct 2019 12:28:06 -0700 Subject: [PATCH 033/182] Revert "Move DozeServiceHost out of StatusBar." Fixes: 143334366 Test: manual This reverts commit a85704052b7a909f43f9d26cb9ba1ddb3896940e. Change-Id: Ia5b5302a659f073cff6ab557bd70bfdbb070d86d (cherry picked from commit 22b934f1d8311bc8eaa9ea8a6a19dc65091bd08a) --- .../systemui/statusbar/car/CarStatusBar.java | 11 +- .../systemui/dagger/DependencyBinder.java | 9 +- .../phone/BiometricUnlockController.java | 6 +- .../statusbar/phone/DozeParameters.java | 8 +- .../statusbar/phone/DozeScrimController.java | 2 - .../statusbar/phone/DozeServiceHost.java | 465 ------------------ .../statusbar/phone/ScrimController.java | 2 - .../systemui/statusbar/phone/StatusBar.java | 357 ++++++++++++-- .../statusbar/phone/DozeServiceHostTest.java | 224 --------- .../statusbar/phone/StatusBarTest.java | 108 +++- 10 files changed, 431 insertions(+), 761 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index aebb62d7b069b..9d3362ee8c65d 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -32,7 +32,6 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.PowerManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.GestureDetector; @@ -108,8 +107,6 @@ import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.DozeParameters; -import com.android.systemui.statusbar.phone.DozeScrimController; -import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LightBarController; @@ -298,9 +295,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt ScrimController scrimController, Lazy lockscreenWallpaperLazy, Lazy biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - DozeScrimController dozeScrimController, /* Car Settings injected components. */ CarNavigationBarController carNavigationBarController) { @@ -364,10 +358,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt dozeParameters, scrimController, lockscreenWallpaperLazy, - biometricUnlockControllerLazy, - dozeServiceHost, - powerManager, - dozeScrimController); + biometricUnlockControllerLazy); mScrimController = scrimController; mCarNavigationBarController = carNavigationBarController; } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java index 9032c6fc86390..6674c12ab6138 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java @@ -20,7 +20,6 @@ import com.android.systemui.ActivityStarterDelegate; import com.android.systemui.appops.AppOpsController; import com.android.systemui.appops.AppOpsControllerImpl; import com.android.systemui.classifier.FalsingManagerProxy; -import com.android.systemui.doze.DozeHost; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.FalsingManager; @@ -34,7 +33,6 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl; -import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -243,10 +241,5 @@ public abstract class DependencyBinder { /** */ @Binds - public abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl); - - /** - */ - @Binds - public abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost); + public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index ffcbc40e7b706..033171a28c626 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -55,10 +55,10 @@ import javax.inject.Singleton; @Singleton public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { - private static final String TAG = "BiometricUnlockCtrl"; + private static final String TAG = "BiometricUnlockController"; private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK; private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000; - private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock"; + private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock"; @IntDef(prefix = { "MODE_" }, value = { MODE_NONE, @@ -134,7 +134,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { private final KeyguardBypassController mKeyguardBypassController; private PowerManager.WakeLock mWakeLock; private final KeyguardUpdateMonitor mUpdateMonitor; - private DozeParameters mDozeParameters; + private final DozeParameters mDozeParameters; private final KeyguardStateController mKeyguardStateController; private final StatusBarWindowController mStatusBarWindowController; private final Context mContext; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index bc482353753d9..50d33a70fed52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -24,6 +24,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.MathUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.MainResources; import com.android.systemui.doze.AlwaysOnDisplayPolicy; @@ -187,7 +188,12 @@ public class DozeParameters implements TunerService.Tunable, return; } mControlScreenOffAnimation = controlScreenOffAnimation; - mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation); + getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation); + } + + @VisibleForTesting + protected PowerManager getPowerManager() { + return mPowerManager; } private boolean getBoolean(String propName, int resId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index 1ecc4899d5e70..fe3c04e3cda3d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -29,12 +29,10 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller which handles all the doze animations of the scrims. */ -@Singleton public class DozeScrimController implements StateListener { private static final String TAG = "DozeScrimController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java deleted file mode 100644 index 28543555bf4d3..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * 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.statusbar.phone; - -import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; -import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; - -import android.annotation.NonNull; -import android.os.Bundle; -import android.os.PowerManager; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.doze.DozeEvent; -import com.android.systemui.doze.DozeHost; -import com.android.systemui.doze.DozeLog; -import com.android.systemui.doze.DozeReceiver; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; - -import java.util.ArrayList; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import dagger.Lazy; - -/** - * Implementation of DozeHost for SystemUI. - */ -@Singleton -public final class DozeServiceHost implements DozeHost { - private static final String TAG = "DozeServiceHost"; - private final ArrayList mCallbacks = new ArrayList<>(); - private final DozeLog mDozeLog; - private final PowerManager mPowerManager; - private boolean mAnimateWakeup; - private boolean mAnimateScreenOff; - private boolean mIgnoreTouchWhilePulsing; - private Runnable mPendingScreenOffCallback; - @VisibleForTesting - boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean( - "persist.sysui.wake_performs_auth", true); - private boolean mDozingRequested; - private boolean mDozing; - private boolean mPulsing; - private WakefulnessLifecycle mWakefulnessLifecycle; - private final SysuiStatusBarStateController mStatusBarStateController; - private final DeviceProvisionedController mDeviceProvisionedController; - private final HeadsUpManagerPhone mHeadsUpManagerPhone; - private final BatteryController mBatteryController; - private final ScrimController mScrimController; - private final Lazy mBiometricUnlockControllerLazy; - private BiometricUnlockController mBiometricUnlockController; - private final KeyguardViewMediator mKeyguardViewMediator; - private final AssistManager mAssistManager; - private final DozeScrimController mDozeScrimController; - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final VisualStabilityManager mVisualStabilityManager; - private final PulseExpansionHandler mPulseExpansionHandler; - private final StatusBarWindowController mStatusBarWindowController; - private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - private NotificationIconAreaController mNotificationIconAreaController; - private StatusBarWindowViewController mStatusBarWindowViewController; - private StatusBarWindowView mStatusBarWindow; - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - private NotificationPanelView mNotificationPanel; - private View mAmbientIndicationContainer; - private StatusBar mStatusBar; - - @Inject - public DozeServiceHost(DozeLog dozeLog, PowerManager powerManager, - WakefulnessLifecycle wakefulnessLifecycle, - SysuiStatusBarStateController statusBarStateController, - DeviceProvisionedController deviceProvisionedController, - HeadsUpManagerPhone headsUpManagerPhone, BatteryController batteryController, - ScrimController scrimController, - Lazy biometricUnlockControllerLazy, - KeyguardViewMediator keyguardViewMediator, - AssistManager assistManager, - DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, - VisualStabilityManager visualStabilityManager, - PulseExpansionHandler pulseExpansionHandler, - StatusBarWindowController statusBarWindowController, - NotificationWakeUpCoordinator notificationWakeUpCoordinator) { - super(); - mDozeLog = dozeLog; - mPowerManager = powerManager; - mWakefulnessLifecycle = wakefulnessLifecycle; - mStatusBarStateController = statusBarStateController; - mDeviceProvisionedController = deviceProvisionedController; - mHeadsUpManagerPhone = headsUpManagerPhone; - mBatteryController = batteryController; - mScrimController = scrimController; - mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; - mKeyguardViewMediator = keyguardViewMediator; - mAssistManager = assistManager; - mDozeScrimController = dozeScrimController; - mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mVisualStabilityManager = visualStabilityManager; - mPulseExpansionHandler = pulseExpansionHandler; - mStatusBarWindowController = statusBarWindowController; - mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; - } - - // TODO: we should try to not pass status bar in here if we can avoid it. - - /** - * Initialize instance with objects only available later during execution. - */ - public void initialize(StatusBar statusBar, - NotificationIconAreaController notificationIconAreaController, - StatusBarWindowViewController statusBarWindowViewController, - StatusBarWindowView statusBarWindow, - StatusBarKeyguardViewManager statusBarKeyguardViewManager, - NotificationPanelView notificationPanel, View ambientIndicationContainer) { - mStatusBar = statusBar; - mNotificationIconAreaController = notificationIconAreaController; - mStatusBarWindowViewController = statusBarWindowViewController; - mStatusBarWindow = statusBarWindow; - mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; - mNotificationPanel = notificationPanel; - mAmbientIndicationContainer = ambientIndicationContainer; - mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); - } - - @Override - public String toString() { - return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; - } - - void firePowerSaveChanged(boolean active) { - for (Callback callback : mCallbacks) { - callback.onPowerSaveChanged(active); - } - } - - void fireNotificationPulse(NotificationEntry entry) { - Runnable pulseSuppressedListener = () -> { - entry.setPulseSuppressed(true); - mNotificationIconAreaController.updateAodNotificationIcons(); - }; - for (Callback callback : mCallbacks) { - callback.onNotificationAlerted(pulseSuppressedListener); - } - } - - boolean getDozingRequested() { - return mDozingRequested; - } - - boolean isPulsing() { - return mPulsing; - } - - - @Override - public void addCallback(@NonNull Callback callback) { - mCallbacks.add(callback); - } - - @Override - public void removeCallback(@NonNull Callback callback) { - mCallbacks.remove(callback); - } - - @Override - public void startDozing() { - if (!mDozingRequested) { - mDozingRequested = true; - mDozeLog.traceDozing(mDozing); - updateDozing(); - mStatusBar.updateIsKeyguard(); - } - } - - void updateDozing() { - // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. - boolean - dozing = - mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD - || mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; - // When in wake-and-unlock we may not have received a change to StatusBarState - // but we still should not be dozing, manually set to false. - if (mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK) { - dozing = false; - } - - - mStatusBarStateController.setIsDozing(dozing); - } - - @Override - public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { - if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, - "com.android.systemui:LONG_PRESS"); - mAssistManager.startAssist(new Bundle()); - return; - } - - if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { - mScrimController.setWakeLockScreenSensorActive(true); - } - - if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) { - mStatusBarWindowViewController.suppressWakeUpGesture(true); - } - - boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN - && mWakeLockScreenPerformsAuth; - // Set the state to pulsing, so ScrimController will know what to do once we ask it to - // execute the transition. The pulse callback will then be invoked when the scrims - // are black, indicating that StatusBar is ready to present the rest of the UI. - mPulsing = true; - mDozeScrimController.pulse(new PulseCallback() { - @Override - public void onPulseStarted() { - callback.onPulseStarted(); - mStatusBar.updateNotificationPanelTouchState(); - setPulsing(true); - } - - @Override - public void onPulseFinished() { - mPulsing = false; - callback.onPulseFinished(); - mStatusBar.updateNotificationPanelTouchState(); - mScrimController.setWakeLockScreenSensorActive(false); - if (mStatusBarWindow != null) { - mStatusBarWindowViewController.suppressWakeUpGesture(false); - } - setPulsing(false); - } - - private void setPulsing(boolean pulsing) { - mStatusBarStateController.setPulsing(pulsing); - mStatusBarKeyguardViewManager.setPulsing(pulsing); - mKeyguardViewMediator.setPulsing(pulsing); - mNotificationPanel.setPulsing(pulsing); - mVisualStabilityManager.setPulsing(pulsing); - mStatusBarWindowViewController.setPulsing(pulsing); - mIgnoreTouchWhilePulsing = false; - if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) { - mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */); - } - mStatusBar.updateScrimController(); - mPulseExpansionHandler.setPulsing(pulsing); - mNotificationWakeUpCoordinator.setPulsing(pulsing); - } - }, reason); - // DozeScrimController is in pulse state, now let's ask ScrimController to start - // pulsing and draw the black frame, if necessary. - mStatusBar.updateScrimController(); - } - - @Override - public void stopDozing() { - if (mDozingRequested) { - mDozingRequested = false; - mDozeLog.traceDozing(mDozing); - updateDozing(); - } - } - - @Override - public void onIgnoreTouchWhilePulsing(boolean ignore) { - if (ignore != mIgnoreTouchWhilePulsing) { - mDozeLog.tracePulseTouchDisabledByProx(ignore); - } - mIgnoreTouchWhilePulsing = ignore; - if (mDozing && ignore) { - mStatusBarWindowViewController.cancelCurrentTouch(); - } - } - - @Override - public void dozeTimeTick() { - mNotificationPanel.dozeTimeTick(); - if (mAmbientIndicationContainer instanceof DozeReceiver) { - ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick(); - } - } - - @Override - public boolean isPowerSaveActive() { - return mBatteryController.isAodPowerSave(); - } - - @Override - public boolean isPulsingBlocked() { - return mBiometricUnlockController.getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; - } - - @Override - public boolean isProvisioned() { - return mDeviceProvisionedController.isDeviceProvisioned() - && mDeviceProvisionedController.isCurrentUserSetup(); - } - - @Override - public boolean isBlockingDoze() { - if (mBiometricUnlockController.hasPendingAuthentication()) { - Log.i(StatusBar.TAG, "Blocking AOD because fingerprint has authenticated"); - return true; - } - return false; - } - - @Override - public void extendPulse(int reason) { - if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { - mScrimController.setWakeLockScreenSensorActive(true); - } - if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) { - mHeadsUpManagerPhone.extendHeadsUp(); - } else { - mDozeScrimController.extendPulse(); - } - } - - @Override - public void stopPulsing() { - if (mDozeScrimController.isPulsing()) { - mDozeScrimController.pulseOutNow(); - } - } - - @Override - public void setAnimateWakeup(boolean animateWakeup) { - if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE - || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) { - // Too late to change the wakeup animation. - return; - } - mAnimateWakeup = animateWakeup; - } - - @Override - public void setAnimateScreenOff(boolean animateScreenOff) { - mAnimateScreenOff = animateScreenOff; - } - - @Override - public void onSlpiTap(float screenX, float screenY) { - if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null - && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { - int[] locationOnScreen = new int[2]; - mAmbientIndicationContainer.getLocationOnScreen(locationOnScreen); - float viewX = screenX - locationOnScreen[0]; - float viewY = screenY - locationOnScreen[1]; - if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth() - && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) { - - // Dispatch a tap - long now = SystemClock.elapsedRealtime(); - MotionEvent ev = MotionEvent.obtain( - now, now, MotionEvent.ACTION_DOWN, screenX, screenY, 0); - mAmbientIndicationContainer.dispatchTouchEvent(ev); - ev.recycle(); - ev = MotionEvent.obtain( - now, now, MotionEvent.ACTION_UP, screenX, screenY, 0); - mAmbientIndicationContainer.dispatchTouchEvent(ev); - ev.recycle(); - } - } - } - - @Override - public void setDozeScreenBrightness(int value) { - mStatusBarWindowController.setDozeScreenBrightness(value); - } - - @Override - public void setAodDimmingScrim(float scrimOpacity) { - mScrimController.setAodFrontScrimAlpha(scrimOpacity); - } - - - - @Override - public void prepareForGentleSleep(Runnable onDisplayOffCallback) { - if (mPendingScreenOffCallback != null) { - Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one."); - } - mPendingScreenOffCallback = onDisplayOffCallback; - mStatusBar.updateScrimController(); - } - - @Override - public void cancelGentleSleep() { - mPendingScreenOffCallback = null; - if (mScrimController.getState() == ScrimState.OFF) { - mStatusBar.updateScrimController(); - } - } - - /** - * When the dozing host is waiting for scrims to fade out to change the display state. - */ - boolean hasPendingScreenOffCallback() { - return mPendingScreenOffCallback != null; - } - - /** - * Executes an nullifies the pending display state callback. - * - * @see #hasPendingScreenOffCallback() - * @see #prepareForGentleSleep(Runnable) - */ - void executePendingScreenOffCallback() { - if (mPendingScreenOffCallback == null) { - return; - } - mPendingScreenOffCallback.run(); - mPendingScreenOffCallback = null; - } - - boolean shouldAnimateWakeup() { - return mAnimateWakeup; - } - - boolean shouldAnimateScreenOff() { - return mAnimateScreenOff; - } - - public void setDozing(boolean dozing) { - mDozing = dozing; - } - - boolean getIgnoreTouchWhilePulsing() { - return mIgnoreTouchWhilePulsing; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 35039a0d74f94..6064fbedf63dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -60,13 +60,11 @@ import java.lang.annotation.RetentionPolicy; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls both the scrim behind the notifications and in front of the notifications (when a * security method gets shown). */ -@Singleton public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 70dca2f8fc100..2e0fbfa6ea0b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -50,6 +50,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; @@ -156,8 +157,10 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.doze.DozeEvent; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; +import com.android.systemui.doze.DozeReceiver; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.KeyguardSliceProvider; @@ -344,7 +347,7 @@ public class StatusBar extends SystemUI implements DemoMode, /** * The {@link StatusBarState} of the status bar. */ - protected int mState; // TODO: remove this. Just use StatusBarStateController + protected int mState; protected boolean mBouncerShowing; private PhoneStatusBarPolicy mIconPolicy; @@ -370,7 +373,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected StatusBarWindowController mStatusBarWindowController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @VisibleForTesting - DozeServiceHost mDozeServiceHost; + DozeServiceHost mDozeServiceHost = new DozeServiceHost(); private boolean mWakeUpComingFromTouch; private PointF mWakeUpTouchLocation; @@ -490,6 +493,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final UiOffloadThread mUiOffloadThread; protected boolean mDozing; + private boolean mDozingRequested; private final NotificationMediaManager mMediaManager; private final NotificationLockscreenUserManager mLockscreenUserManager; @@ -608,6 +612,7 @@ public class StatusBar extends SystemUI implements DemoMode, private ActivityLaunchAnimator mActivityLaunchAnimator; protected StatusBarNotificationPresenter mPresenter; private NotificationActivityStarter mNotificationActivityStarter; + private boolean mPulsing; private final BubbleController mBubbleController; private final BubbleController.BubbleExpandListener mBubbleExpandListener; @@ -687,10 +692,7 @@ public class StatusBar extends SystemUI implements DemoMode, DozeParameters dozeParameters, ScrimController scrimController, Lazy lockscreenWallpaperLazy, - Lazy biometricUnlockControllerLazy, - DozeServiceHost dozeServiceHost, - PowerManager powerManager, - DozeScrimController dozeScrimController) { + Lazy biometricUnlockControllerLazy) { super(context); mFeatureFlags = featureFlags; mLightBarController = lightBarController; @@ -747,12 +749,9 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarWindowController = statusBarWindowController; mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder; mNotifLog = notifLog; - mDozeServiceHost = dozeServiceHost; - mPowerManager = powerManager; mDozeParameters = dozeParameters; mScrimController = scrimController; mLockscreenWallpaperLazy = lockscreenWallpaperLazy; - mDozeScrimController = dozeScrimController; mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; mBubbleExpandListener = @@ -805,6 +804,7 @@ public class StatusBar extends SystemUI implements DemoMode, mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @@ -904,9 +904,6 @@ public class StatusBar extends SystemUI implements DemoMode, startKeyguard(); mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); - mDozeServiceHost.initialize(this, mNotificationIconAreaController, - mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager, - mNotificationPanel, mAmbientIndicationContainer); putComponent(DozeHost.class, mDozeServiceHost); mScreenPinningRequest = new ScreenPinningRequest(mContext); @@ -1071,6 +1068,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf, mHeadsUpManager, mNotificationIconAreaController, mScrimController); + mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog); BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop); mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), @@ -1731,7 +1729,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (isDozing() && isHeadsUp) { entry.setPulseSuppressed(false); mDozeServiceHost.fireNotificationPulse(entry); - if (mDozeServiceHost.isPulsing()) { + if (mPulsing) { mDozeScrimController.cancelPendingPulseTimeout(); } } @@ -1763,7 +1761,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public boolean isPulsing() { - return mDozeServiceHost.isPulsing(); + return mPulsing; } public boolean hideStatusBarIconsWhenExpanded() { @@ -2826,7 +2824,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP && mKeyguardStateController.canDismissLockScreen() && !mStatusBarStateController.leaveOpenOnKeyguardHide() - && mDozeServiceHost.isPulsing()) { + && isPulsing()) { // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse. // TODO: Factor this transition out of BiometricUnlockController. mBiometricUnlockController.startWakeAndUnlock( @@ -3157,7 +3155,7 @@ public class StatusBar extends SystemUI implements DemoMode, return mState == StatusBarState.FULLSCREEN_USER_SWITCHER; } - boolean updateIsKeyguard() { + private boolean updateIsKeyguard() { boolean wakeAndUnlocking = mBiometricUnlockController.getMode() == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; @@ -3165,8 +3163,8 @@ public class StatusBar extends SystemUI implements DemoMode, // there's no surface we can show to the user. Note that the device goes fully interactive // late in the transition, so we also allow the device to start dozing once the screen has // turned off fully. - boolean keyguardForDozing = mDozeServiceHost.getDozingRequested() - && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); + boolean keyguardForDozing = mDozingRequested && + (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested() || keyguardForDozing) && !wakeAndUnlocking; if (keyguardForDozing) { @@ -3582,7 +3580,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void onStateChanged(int newState) { mState = newState; updateReportRejectedTouchVisibility(); - mDozeServiceHost.updateDozing(); + updateDozing(); updateTheme(); mNavigationBarController.touchAutoDim(mDisplayId); Trace.beginSection("StatusBar#updateKeyguardState"); @@ -3620,23 +3618,36 @@ public class StatusBar extends SystemUI implements DemoMode, public void onDozingChanged(boolean isDozing) { Trace.beginSection("StatusBar#updateDozing"); mDozing = isDozing; - mDozeServiceHost.setDozing(mDozing); // Collapse the notification panel if open - boolean dozingAnimated = mDozeServiceHost.getDozingRequested() - && mDozeParameters.shouldControlScreenOff(); + boolean dozingAnimated = mDozingRequested && mDozeParameters.shouldControlScreenOff(); mNotificationPanel.resetViews(dozingAnimated); updateQsExpansionEnabled(); mKeyguardViewMediator.setDozing(mDozing); mEntryManager.updateNotifications("onDozingChanged"); - mDozeServiceHost.updateDozing(); + updateDozingState(); updateScrimController(); updateReportRejectedTouchVisibility(); Trace.endSection(); } + private void updateDozing() { + // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. + boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD + || mBiometricUnlockController.getMode() + == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; + // When in wake-and-unlock we may not have received a change to mState + // but we still should not be dozing, manually set to false. + if (mBiometricUnlockController.getMode() == + BiometricUnlockController.MODE_WAKE_AND_UNLOCK) { + dozing = false; + } + + mStatusBarStateController.setIsDozing(dozing); + } + private void updateKeyguardState() { mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(), mStatusBarKeyguardViewManager.isOccluded()); @@ -3861,11 +3872,10 @@ public class StatusBar extends SystemUI implements DemoMode, * collapse the panel after we expanded it, and thus we would end up with a blank * Keyguard. */ - void updateNotificationPanelTouchState() { + private void updateNotificationPanelTouchState() { boolean goingToSleepWithoutAnimation = isGoingToSleep() && !mDozeParameters.shouldControlScreenOff(); - boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing()) - || goingToSleepWithoutAnimation; + boolean disabled = (!mDeviceInteractive && !mPulsing) || goingToSleepWithoutAnimation; mNotificationPanel.setTouchAndAnimationDisabled(disabled); mNotificationIconAreaController.setAnimationsEnabled(!disabled); } @@ -4015,7 +4025,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public void notifyBiometricAuthModeChanged() { - mDozeServiceHost.updateDozing(); + updateDozing(); updateScrimController(); mStatusBarWindowViewController.onBiometricAuthModeChanged( mBiometricUnlockController.isWakeAndUnlock(), @@ -4051,7 +4061,7 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } else if (mBrightnessMirrorVisible) { mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); - } else if (mDozeServiceHost.isPulsing()) { + } else if (isPulsing()) { mScrimController.transitionTo(ScrimState.PULSING, mDozeScrimController.getScrimCallback()); } else if (mDozeServiceHost.hasPendingScreenOffCallback()) { @@ -4081,8 +4091,295 @@ public class StatusBar extends SystemUI implements DemoMode, return mStatusBarKeyguardViewManager.isShowing(); } + @VisibleForTesting + final class DozeServiceHost implements DozeHost { + private final ArrayList mCallbacks = new ArrayList<>(); + private boolean mAnimateWakeup; + private boolean mAnimateScreenOff; + private boolean mIgnoreTouchWhilePulsing; + private Runnable mPendingScreenOffCallback; + @VisibleForTesting + boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean( + "persist.sysui.wake_performs_auth", true); + + @Override + public String toString() { + return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; + } + + public void firePowerSaveChanged(boolean active) { + for (Callback callback : mCallbacks) { + callback.onPowerSaveChanged(active); + } + } + + public void fireNotificationPulse(NotificationEntry entry) { + Runnable pulseSupressedListener = () -> { + entry.setPulseSuppressed(true); + mNotificationIconAreaController.updateAodNotificationIcons(); + }; + for (Callback callback : mCallbacks) { + callback.onNotificationAlerted(pulseSupressedListener); + } + } + + @Override + public void addCallback(@NonNull Callback callback) { + mCallbacks.add(callback); + } + + @Override + public void removeCallback(@NonNull Callback callback) { + mCallbacks.remove(callback); + } + + @Override + public void startDozing() { + if (!mDozingRequested) { + mDozingRequested = true; + mDozeLog.traceDozing(mDozing); + updateDozing(); + updateIsKeyguard(); + } + } + + @Override + public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { + if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) { + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui:LONG_PRESS"); + startAssist(new Bundle()); + return; + } + + if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mScrimController.setWakeLockScreenSensorActive(true); + } + + if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) { + mStatusBarWindowViewController.suppressWakeUpGesture(true); + } + + boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN + && mWakeLockScreenPerformsAuth; + // Set the state to pulsing, so ScrimController will know what to do once we ask it to + // execute the transition. The pulse callback will then be invoked when the scrims + // are black, indicating that StatusBar is ready to present the rest of the UI. + mPulsing = true; + mDozeScrimController.pulse(new PulseCallback() { + @Override + public void onPulseStarted() { + callback.onPulseStarted(); + updateNotificationPanelTouchState(); + setPulsing(true); + } + + @Override + public void onPulseFinished() { + mPulsing = false; + callback.onPulseFinished(); + updateNotificationPanelTouchState(); + mScrimController.setWakeLockScreenSensorActive(false); + if (mStatusBarWindow != null) { + mStatusBarWindowViewController.suppressWakeUpGesture(false); + } + setPulsing(false); + } + + private void setPulsing(boolean pulsing) { + mStatusBarStateController.setPulsing(pulsing); + mStatusBarKeyguardViewManager.setPulsing(pulsing); + mKeyguardViewMediator.setPulsing(pulsing); + mNotificationPanel.setPulsing(pulsing); + mVisualStabilityManager.setPulsing(pulsing); + mStatusBarWindowViewController.setPulsing(pulsing); + mIgnoreTouchWhilePulsing = false; + if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) { + mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */); + } + updateScrimController(); + mPulseExpansionHandler.setPulsing(pulsing); + mWakeUpCoordinator.setPulsing(pulsing); + } + }, reason); + // DozeScrimController is in pulse state, now let's ask ScrimController to start + // pulsing and draw the black frame, if necessary. + updateScrimController(); + } + + @Override + public void stopDozing() { + if (mDozingRequested) { + mDozingRequested = false; + mDozeLog.traceDozing(mDozing); + updateDozing(); + } + } + + @Override + public void onIgnoreTouchWhilePulsing(boolean ignore) { + if (ignore != mIgnoreTouchWhilePulsing) { + mDozeLog.tracePulseTouchDisabledByProx(ignore); + } + mIgnoreTouchWhilePulsing = ignore; + if (isDozing() && ignore) { + mStatusBarWindowViewController.cancelCurrentTouch(); + } + } + + @Override + public void dozeTimeTick() { + mNotificationPanel.dozeTimeTick(); + if (mAmbientIndicationContainer instanceof DozeReceiver) { + ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick(); + } + } + + @Override + public boolean isPowerSaveActive() { + return mBatteryController.isAodPowerSave(); + } + + @Override + public boolean isPulsingBlocked() { + return mBiometricUnlockController.getMode() + == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; + } + + @Override + public boolean isProvisioned() { + return mDeviceProvisionedController.isDeviceProvisioned() + && mDeviceProvisionedController.isCurrentUserSetup(); + } + + @Override + public boolean isBlockingDoze() { + if (mBiometricUnlockController.hasPendingAuthentication()) { + Log.i(TAG, "Blocking AOD because fingerprint has authenticated"); + return true; + } + return false; + } + + @Override + public void extendPulse(int reason) { + if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mScrimController.setWakeLockScreenSensorActive(true); + } + if (mDozeScrimController.isPulsing() && mHeadsUpManager.hasNotifications()) { + mHeadsUpManager.extendHeadsUp(); + } else { + mDozeScrimController.extendPulse(); + } + } + + @Override + public void stopPulsing() { + if (mDozeScrimController.isPulsing()) { + mDozeScrimController.pulseOutNow(); + } + } + + @Override + public void setAnimateWakeup(boolean animateWakeup) { + if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) { + // Too late to change the wakeup animation. + return; + } + mAnimateWakeup = animateWakeup; + } + + @Override + public void setAnimateScreenOff(boolean animateScreenOff) { + mAnimateScreenOff = animateScreenOff; + } + + @Override + public void onSlpiTap(float screenX, float screenY) { + if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null + && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { + mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2); + float viewX = screenX - mTmpInt2[0]; + float viewY = screenY - mTmpInt2[1]; + if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth() + && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) { + dispatchTap(mAmbientIndicationContainer, viewX, viewY); + } + } + } + + @Override + public void setDozeScreenBrightness(int value) { + mStatusBarWindowController.setDozeScreenBrightness(value); + } + + @Override + public void setAodDimmingScrim(float scrimOpacity) { + mScrimController.setAodFrontScrimAlpha(scrimOpacity); + } + + @Override + public void prepareForGentleSleep(Runnable onDisplayOffCallback) { + if (mPendingScreenOffCallback != null) { + Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one."); + } + mPendingScreenOffCallback = onDisplayOffCallback; + updateScrimController(); + } + + @Override + public void cancelGentleSleep() { + mPendingScreenOffCallback = null; + if (mScrimController.getState() == ScrimState.OFF) { + updateScrimController(); + } + } + + /** + * When the dozing host is waiting for scrims to fade out to change the display state. + */ + boolean hasPendingScreenOffCallback() { + return mPendingScreenOffCallback != null; + } + + /** + * Executes an nullifies the pending display state callback. + * + * @see #hasPendingScreenOffCallback() + * @see #prepareForGentleSleep(Runnable) + */ + void executePendingScreenOffCallback() { + if (mPendingScreenOffCallback == null) { + return; + } + mPendingScreenOffCallback.run(); + mPendingScreenOffCallback = null; + } + + private void dispatchTap(View view, float x, float y) { + long now = SystemClock.elapsedRealtime(); + dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN); + dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP); + } + + private void dispatchTouchEvent(View view, float x, float y, long now, int action) { + MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */); + view.dispatchTouchEvent(ev); + ev.recycle(); + } + + private boolean shouldAnimateWakeup() { + return mAnimateWakeup; + } + + public boolean shouldAnimateScreenOff() { + return mAnimateScreenOff; + } + } + public boolean shouldIgnoreTouch() { - return isDozing() && mDozeServiceHost.getIgnoreTouchWhilePulsing(); + return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing; } // Begin Extra BaseStatusBar methods. @@ -4109,7 +4406,7 @@ public class StatusBar extends SystemUI implements DemoMode, private boolean mVisibleToUser; protected DevicePolicyManager mDevicePolicyManager; - private final PowerManager mPowerManager; + protected PowerManager mPowerManager; protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; protected KeyguardManager mKeyguardManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java deleted file mode 100644 index b05172c6d7c2e..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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.statusbar.phone; - -import static org.junit.Assert.assertFalse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.os.PowerManager; -import android.testing.AndroidTestingRunner; -import android.view.View; - -import androidx.test.filters.SmallTest; - -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.doze.DozeEvent; -import com.android.systemui.doze.DozeHost; -import com.android.systemui.doze.DozeLog; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.statusbar.PulseExpansionHandler; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.StatusBarStateControllerImpl; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; - -import dagger.Lazy; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -public class DozeServiceHostTest extends SysuiTestCase { - - private DozeServiceHost mDozeServiceHost; - - @Mock private HeadsUpManagerPhone mHeadsUpManager; - @Mock private ScrimController mScrimController; - @Mock private DozeScrimController mDozeScrimController; - @Mock private Lazy mBiometricUnlockControllerLazy; - @Mock private VisualStabilityManager mVisualStabilityManager; - @Mock private KeyguardViewMediator mKeyguardViewMediator; - @Mock private StatusBarStateControllerImpl mStatusBarStateController; - @Mock private BatteryController mBatteryController; - @Mock private DeviceProvisionedController mDeviceProvisionedController; - @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock private AssistManager mAssistManager; - @Mock private DozeLog mDozeLog; - @Mock private PulseExpansionHandler mPulseExpansionHandler; - @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - @Mock private StatusBarWindowController mStatusBarWindowController; - @Mock private PowerManager mPowerManager; - @Mock private WakefulnessLifecycle mWakefullnessLifecycle; - @Mock private StatusBar mStatusBar; - @Mock private NotificationIconAreaController mNotificationIconAreaController; - @Mock private StatusBarWindowViewController mStatusBarWindowViewController; - @Mock private StatusBarWindowView mStatusBarWindow; - @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - @Mock private NotificationPanelView mNotificationPanel; - @Mock private View mAmbientIndicationContainer; - @Mock private BiometricUnlockController mBiometricUnlockController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController); - mDozeServiceHost = new DozeServiceHost(mDozeLog, mPowerManager, mWakefullnessLifecycle, - mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager, - mBatteryController, mScrimController, mBiometricUnlockControllerLazy, - mKeyguardViewMediator, mAssistManager, mDozeScrimController, mKeyguardUpdateMonitor, - mVisualStabilityManager, mPulseExpansionHandler, mStatusBarWindowController, - mNotificationWakeUpCoordinator); - - mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController, - mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager, - mNotificationPanel, mAmbientIndicationContainer); - } - - @Test - public void testStartStopDozing() { - when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); - when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - - assertFalse(mDozeServiceHost.getDozingRequested()); - - mDozeServiceHost.startDozing(); - verify(mStatusBarStateController).setIsDozing(eq(true)); - verify(mStatusBar).updateIsKeyguard(); - - mDozeServiceHost.stopDozing(); - verify(mStatusBarStateController).setIsDozing(eq(false)); - } - - - @Test - public void testPulseWhileDozing_updatesScrimController() { - mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); - mStatusBar.showKeyguardImpl(); - - // Keep track of callback to be able to stop the pulse -// DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; -// doAnswer(invocation -> { -// pulseCallback[0] = invocation.getArgument(0); -// return null; -// }).when(mDozeScrimController).pulse(any(), anyInt()); - - // Starting a pulse should change the scrim controller to the pulsing state - mDozeServiceHost.pulseWhileDozing(new DozeHost.PulseCallback() { - @Override - public void onPulseStarted() { - } - - @Override - public void onPulseFinished() { - } - }, DozeEvent.PULSE_REASON_NOTIFICATION); - - ArgumentCaptor pulseCallbackArgumentCaptor = - ArgumentCaptor.forClass(DozeHost.PulseCallback.class); - - verify(mDozeScrimController).pulse( - pulseCallbackArgumentCaptor.capture(), eq(DozeEvent.PULSE_REASON_NOTIFICATION)); - verify(mStatusBar).updateScrimController(); - reset(mStatusBar); - - pulseCallbackArgumentCaptor.getValue().onPulseFinished(); - assertFalse(mDozeScrimController.isPulsing()); - verify(mStatusBar).updateScrimController(); - } - - - @Test - public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() { - // Keep track of callback to be able to stop the pulse - final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; - doAnswer(invocation -> { - pulseCallback[0] = invocation.getArgument(0); - return null; - }).when(mDozeScrimController).pulse(any(), anyInt()); - - // Starting a pulse while docking should suppress wakeup gesture - mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), - DozeEvent.PULSE_REASON_DOCKING); - verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true)); - - // Ending a pulse should restore wakeup gesture - pulseCallback[0].onPulseFinished(); - verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false)); - } - - @Test - public void testPulseWhileDozing_notifyAuthInterrupt() { - HashSet reasonsWantingAuth = new HashSet<>( - Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN)); - HashSet reasonsSkippingAuth = new HashSet<>( - Arrays.asList(DozeEvent.PULSE_REASON_INTENT, - DozeEvent.PULSE_REASON_NOTIFICATION, - DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, - DozeEvent.REASON_SENSOR_PICKUP, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, - DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, - DozeEvent.PULSE_REASON_DOCKING, - DozeEvent.REASON_SENSOR_WAKE_UP, - DozeEvent.REASON_SENSOR_TAP)); - HashSet reasonsThatDontPulse = new HashSet<>( - Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, - DozeEvent.REASON_SENSOR_TAP)); - - doAnswer(invocation -> { - DozeHost.PulseCallback callback = invocation.getArgument(0); - callback.onPulseStarted(); - return null; - }).when(mDozeScrimController).pulse(any(), anyInt()); - - mDozeServiceHost.mWakeLockScreenPerformsAuth = true; - for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { - reset(mKeyguardUpdateMonitor); - mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i); - if (reasonsWantingAuth.contains(i)) { - verify(mKeyguardUpdateMonitor).onAuthInterruptDetected(eq(true)); - } else if (reasonsSkippingAuth.contains(i) || reasonsThatDontPulse.contains(i)) { - verify(mKeyguardUpdateMonitor, never()).onAuthInterruptDetected(eq(true)); - } else { - throw new AssertionError("Reason " + i + " isn't specified as wanting or skipping" - + " passive auth. Please consider how this pulse reason should behave."); - } - } - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 66c01ca584914..f5e92e4f31818 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -85,6 +85,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.doze.DozeEvent; +import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -143,6 +145,9 @@ import org.mockito.MockitoAnnotations; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import dagger.Lazy; @@ -226,7 +231,6 @@ public class StatusBarTest extends SysuiTestCase { @Mock private DozeParameters mDozeParameters; @Mock private Lazy mLockscreenWallpaperLazy; @Mock private LockscreenWallpaper mLockscreenWallpaper; - @Mock private DozeServiceHost mDozeServiceHost; @Mock private LinearLayout mLockIconContainer; @Mock private ViewMediatorCallback mKeyguardVieMediatorCallback; @@ -361,10 +365,7 @@ public class StatusBarTest extends SysuiTestCase { mDozeParameters, mScrimController, mLockscreenWallpaperLazy, - mBiometricUnlockControllerLazy, - mDozeServiceHost, - mPowerManager, - mDozeScrimController); + mBiometricUnlockControllerLazy); when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn( mLockIconContainer); @@ -387,6 +388,7 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController; mStatusBar.mPresenter = mNotificationPresenter; mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController; + mStatusBar.mPowerManager = mPowerManager; mStatusBar.mBarService = mBarService; mStatusBar.mStackScroller = mStackScroller; mStatusBar.mStatusBarWindowViewController = mStatusBarWindowViewController; @@ -755,17 +757,82 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); mStatusBar.showKeyguardImpl(); + // Keep track of callback to be able to stop the pulse + DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; + doAnswer(invocation -> { + pulseCallback[0] = invocation.getArgument(0); + return null; + }).when(mDozeScrimController).pulse(any(), anyInt()); + // Starting a pulse should change the scrim controller to the pulsing state - when(mDozeServiceHost.isPulsing()).thenReturn(true); - mStatusBar.updateScrimController(); + mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), + DozeEvent.PULSE_REASON_NOTIFICATION); verify(mScrimController).transitionTo(eq(ScrimState.PULSING), any()); // Ending a pulse should take it back to keyguard state - when(mDozeServiceHost.isPulsing()).thenReturn(false); - mStatusBar.updateScrimController(); + pulseCallback[0].onPulseFinished(); verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD)); } + @Test + public void testPulseWhileDozing_notifyAuthInterrupt() { + HashSet reasonsWantingAuth = new HashSet<>( + Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN)); + HashSet reasonsSkippingAuth = new HashSet<>( + Arrays.asList(DozeEvent.PULSE_REASON_INTENT, + DozeEvent.PULSE_REASON_NOTIFICATION, + DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, + DozeEvent.REASON_SENSOR_PICKUP, + DozeEvent.REASON_SENSOR_DOUBLE_TAP, + DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, + DozeEvent.PULSE_REASON_DOCKING, + DozeEvent.REASON_SENSOR_WAKE_UP, + DozeEvent.REASON_SENSOR_TAP)); + HashSet reasonsThatDontPulse = new HashSet<>( + Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP, + DozeEvent.REASON_SENSOR_DOUBLE_TAP, + DozeEvent.REASON_SENSOR_TAP)); + + doAnswer(invocation -> { + DozeHost.PulseCallback callback = invocation.getArgument(0); + callback.onPulseStarted(); + return null; + }).when(mDozeScrimController).pulse(any(), anyInt()); + + mStatusBar.mDozeServiceHost.mWakeLockScreenPerformsAuth = true; + for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { + reset(mKeyguardUpdateMonitor); + mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i); + if (reasonsWantingAuth.contains(i)) { + verify(mKeyguardUpdateMonitor).onAuthInterruptDetected(eq(true)); + } else if (reasonsSkippingAuth.contains(i) || reasonsThatDontPulse.contains(i)) { + verify(mKeyguardUpdateMonitor, never()).onAuthInterruptDetected(eq(true)); + } else { + throw new AssertionError("Reason " + i + " isn't specified as wanting or skipping" + + " passive auth. Please consider how this pulse reason should behave."); + } + } + } + + @Test + public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() { + // Keep track of callback to be able to stop the pulse + final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1]; + doAnswer(invocation -> { + pulseCallback[0] = invocation.getArgument(0); + return null; + }).when(mDozeScrimController).pulse(any(), anyInt()); + + // Starting a pulse while docking should suppress wakeup gesture + mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), + DozeEvent.PULSE_REASON_DOCKING); + verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true)); + + // Ending a pulse should restore wakeup gesture + pulseCallback[0].onPulseFinished(); + verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false)); + } + @Test public void testSetState_changesIsFullScreenUserSwitcherState() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); @@ -791,18 +858,28 @@ public class StatusBarTest extends SysuiTestCase { verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER)); } + @Test + public void testStartStopDozing() { + mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); + when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); + + mStatusBar.mDozeServiceHost.startDozing(); + verify(mStatusBarStateController).setIsDozing(eq(true)); + + mStatusBar.mDozeServiceHost.stopDozing(); + verify(mStatusBarStateController).setIsDozing(eq(false)); + } + @Test public void testOnStartedWakingUp_isNotDozing() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - when(mDozeServiceHost.getDozingRequested()).thenReturn(true); - mStatusBar.updateIsKeyguard(); - // TODO: mNotificationPanelView.expand(false) gets called twice. Should be once. - verify(mNotificationPanelView, times(2)).expand(eq(false)); + mStatusBar.mDozeServiceHost.startDozing(); + verify(mStatusBarStateController).setIsDozing(eq(true)); clearInvocations(mNotificationPanelView); mStatusBar.mWakefulnessObserver.onStartedWakingUp(); - verify(mDozeServiceHost).stopDozing(); + verify(mStatusBarStateController).setIsDozing(eq(false)); verify(mNotificationPanelView).expand(eq(false)); } @@ -810,8 +887,7 @@ public class StatusBarTest extends SysuiTestCase { public void testOnStartedWakingUp_doesNotDismissBouncer_whenPulsing() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - when(mDozeServiceHost.getDozingRequested()).thenReturn(true); - mStatusBar.updateIsKeyguard(); + mStatusBar.mDozeServiceHost.startDozing(); clearInvocations(mNotificationPanelView); mStatusBar.setBouncerShowing(true); From 061daa1bc5aa18c660df23b8a3a7e8e53feb2188 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 25 Oct 2019 18:47:50 +0800 Subject: [PATCH 034/182] Return resume result in resumeFocusedStacksTopActivities The method addToFinishingAndWaitForIdle cannot know the next home was successful resume because the last result of resumeTopActivityUncheckedLocked was not returned, so FallbackHome can be destroy immediately without wait next home activity become idled. Add test testCompleteFinishing_lastActivityAboveEmptyHomeStack Bug: 143199498 Test: atest ActivityRecordTests Test: atest MultiDisplaySystemDecorationTests ActivityVisibilityTests SplitScreenTests PinnedStackTests Change-Id: Icbe436afd66d2c2e5a9b884433e2fea84c119513 (cherry picked from commit a90ef31332bdfe2576994841b312f4bac2ce6bcb) --- .../server/wm/RootActivityContainer.java | 2 +- .../server/wm/ActivityRecordTests.java | 40 ++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index 9db6dc263944e..51a3e7205489b 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -1154,7 +1154,7 @@ class RootActivityContainer extends ConfigurationContainer // activity is started and resumed, and no recursion occurs. final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { - focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); + result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index aceb6335c4d36..7bd92aac2ed4d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -836,6 +836,14 @@ public class ActivityRecordTests extends ActivityTestsBase { // Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() - // this will cause NPE when updating task's process. mActivity.app = null; + + // If mActivity is at the last stack on display, it will wait till idle before destroyed, to + // test that it can be destroy, there will need another resumed activity. + final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build(); + topActivity.visible = true; + topActivity.nowVisible = true; + topActivity.setState(RESUMED, "true"); + assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REMOVED, mActivity.finishIfPossible("test", false /* oomAdj */)); assertTrue(mActivity.finishing); @@ -1102,8 +1110,11 @@ public class ActivityRecordTests extends ActivityTestsBase { // Add another stack to become focused and make the activity there visible. This way it // simulates finishing in non-focused stack in split-screen. final ActivityStack stack = new StackBuilder(mRootActivityContainer).build(); - stack.getChildAt(0).getChildAt(0).nowVisible = true; - stack.getChildAt(0).getChildAt(0).visible = true; + final ActivityRecord focusActivity = stack.getChildAt(0).getChildAt(0); + focusActivity.nowVisible = true; + focusActivity.visible = true; + focusActivity.setState(RESUMED, "test"); + stack.mResumedActivity = focusActivity; topActivity.completeFinishing("test"); @@ -1150,6 +1161,31 @@ public class ActivityRecordTests extends ActivityTestsBase { assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity)); } + /** + * Verify that complete finish request for visible activity must resume next home stack before + * destroy it immediately if it is the last running activity on a display with a home stack. We + * must wait for home activity to come up to avoid a black flash in this case. + */ + @Test + public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() { + // Empty the home stack. + final ActivityStack homeStack = mActivity.getDisplay().getHomeStack(); + for (TaskRecord t : homeStack.getAllTasks()) { + homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING); + } + mActivity.finishing = true; + spyOn(mStack); + + // Try to finish the last activity above the home stack. + mActivity.completeFinishing("test"); + + // Verify that the activity was not destroyed immediately, but waits for next one to come up + // instead. + verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString()); + assertEquals(FINISHING, mActivity.getState()); + assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity)); + } + /** * Test that the activity will be moved to destroying state and the message to destroy will be * sent to the client. From c9e923327f12c7012c77bba9ec177db7958d8fc9 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 25 Oct 2019 18:47:50 +0800 Subject: [PATCH 035/182] Return resume result in resumeFocusedStacksTopActivities The method addToFinishingAndWaitForIdle cannot know the next home was successful resume because the last result of resumeTopActivityUncheckedLocked was not returned, so FallbackHome can be destroy immediately without wait next home activity become idled. Add test testCompleteFinishing_lastActivityAboveEmptyHomeStack Bug: 143199498 Test: atest ActivityRecordTests Test: atest MultiDisplaySystemDecorationTests ActivityVisibilityTests SplitScreenTests PinnedStackTests Change-Id: Icbe436afd66d2c2e5a9b884433e2fea84c119513 (cherry picked from commit a90ef31332bdfe2576994841b312f4bac2ce6bcb) --- .../server/wm/RootActivityContainer.java | 2 +- .../server/wm/ActivityRecordTests.java | 40 ++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index 9db6dc263944e..51a3e7205489b 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -1154,7 +1154,7 @@ class RootActivityContainer extends ConfigurationContainer // activity is started and resumed, and no recursion occurs. final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { - focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); + result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 99ecdcb002a11..08d3b12f1ce99 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -836,6 +836,14 @@ public class ActivityRecordTests extends ActivityTestsBase { // Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() - // this will cause NPE when updating task's process. mActivity.app = null; + + // If mActivity is at the last stack on display, it will wait till idle before destroyed, to + // test that it can be destroy, there will need another resumed activity. + final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build(); + topActivity.visible = true; + topActivity.nowVisible = true; + topActivity.setState(RESUMED, "true"); + assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REMOVED, mActivity.finishIfPossible("test", false /* oomAdj */)); assertTrue(mActivity.finishing); @@ -1131,8 +1139,11 @@ public class ActivityRecordTests extends ActivityTestsBase { // Add another stack to become focused and make the activity there visible. This way it // simulates finishing in non-focused stack in split-screen. final ActivityStack stack = new StackBuilder(mRootActivityContainer).build(); - stack.getChildAt(0).getChildAt(0).nowVisible = true; - stack.getChildAt(0).getChildAt(0).visible = true; + final ActivityRecord focusActivity = stack.getChildAt(0).getChildAt(0); + focusActivity.nowVisible = true; + focusActivity.visible = true; + focusActivity.setState(RESUMED, "test"); + stack.mResumedActivity = focusActivity; topActivity.completeFinishing("test"); @@ -1179,6 +1190,31 @@ public class ActivityRecordTests extends ActivityTestsBase { assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity)); } + /** + * Verify that complete finish request for visible activity must resume next home stack before + * destroy it immediately if it is the last running activity on a display with a home stack. We + * must wait for home activity to come up to avoid a black flash in this case. + */ + @Test + public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() { + // Empty the home stack. + final ActivityStack homeStack = mActivity.getDisplay().getHomeStack(); + for (TaskRecord t : homeStack.getAllTasks()) { + homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING); + } + mActivity.finishing = true; + spyOn(mStack); + + // Try to finish the last activity above the home stack. + mActivity.completeFinishing("test"); + + // Verify that the activity was not destroyed immediately, but waits for next one to come up + // instead. + verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString()); + assertEquals(FINISHING, mActivity.getState()); + assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity)); + } + /** * Test that the activity will be moved to destroying state and the message to destroy will be * sent to the client. From d4d7409320aa11e773db5f97764bcb3c9bba58ae Mon Sep 17 00:00:00 2001 From: Soonil Nagarkar Date: Wed, 30 Oct 2019 16:59:11 -0700 Subject: [PATCH 036/182] Prevent crash when invoking GNSS apis GNSS APIs may crash when invoked on devices without GNSS, fix this implementation. Bug: 143591625 Test: manual Change-Id: I6de563df96bc4605852989243c38e5d5278cbda0 (cherry picked from commit c4a4833708e01065627501c37f02084974470eaa) --- .../android/location/LocationManager.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index c3aae7def593a..f33af14d2361b 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2750,9 +2750,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssStatusListener(); - return mService.registerGnssStatusCallback(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId()); + GnssStatusListener transport = new GnssStatusListener(); + if (mService.registerGnssStatusCallback(transport, mContext.getPackageName(), + mContext.getFeatureId())) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2810,10 +2815,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssMeasurementsListener(); - return mService.addGnssMeasurementsListener(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId(), - "gnss measurement callback"); + GnssMeasurementsListener transport = new GnssMeasurementsListener(); + if (mService.addGnssMeasurementsListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss measurement callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2847,10 +2856,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssNavigationMessageListener(); - return mService.addGnssNavigationMessageListener(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId(), - "gnss navigation callback"); + GnssNavigationMessageListener transport = new GnssNavigationMessageListener(); + if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss navigation callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2884,9 +2897,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new BatchedLocationCallback(); - return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName(), - mContext.getFeatureId(), "batched location callback"); + BatchedLocationCallback transport = new BatchedLocationCallback(); + if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(), + mContext.getFeatureId(), "batched location callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override From 0826cfe5855041cd802583f123e236d3a26f694c Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 25 Oct 2019 18:47:50 +0800 Subject: [PATCH 037/182] Return resume result in resumeFocusedStacksTopActivities The method addToFinishingAndWaitForIdle cannot know the next home was successful resume because the last result of resumeTopActivityUncheckedLocked was not returned, so FallbackHome can be destroy immediately without waiting for next home activity to be idle. Add test testCompleteFinishing_lastActivityAboveEmptyHomeStack Bug: 143199498 Test: atest ActivityRecordTests Test: atest MultiDisplaySystemDecorationTests ActivityVisibilityTests SplitScreenTests PinnedStackTests Change-Id: Icbe436afd66d2c2e5a9b884433e2fea84c119513 (cherry picked from commit 4c9824a5ae801bacbd5633900da624c4e2482637) --- .../server/wm/RootActivityContainer.java | 2 +- .../server/wm/ActivityRecordTests.java | 39 ++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index 9db6dc263944e..51a3e7205489b 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -1154,7 +1154,7 @@ class RootActivityContainer extends ConfigurationContainer // activity is started and resumed, and no recursion occurs. final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { - focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); + result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 99ecdcb002a11..38d6c9c1e4db9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -836,6 +836,14 @@ public class ActivityRecordTests extends ActivityTestsBase { // Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() - // this will cause NPE when updating task's process. mActivity.app = null; + + // Put a visible activity on top, so the finishing activity doesn't have to wait until the + // next activity reports idle to destroy it. + final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build(); + topActivity.visible = true; + topActivity.nowVisible = true; + topActivity.setState(RESUMED, "test"); + assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REMOVED, mActivity.finishIfPossible("test", false /* oomAdj */)); assertTrue(mActivity.finishing); @@ -1131,8 +1139,11 @@ public class ActivityRecordTests extends ActivityTestsBase { // Add another stack to become focused and make the activity there visible. This way it // simulates finishing in non-focused stack in split-screen. final ActivityStack stack = new StackBuilder(mRootActivityContainer).build(); - stack.getChildAt(0).getChildAt(0).nowVisible = true; - stack.getChildAt(0).getChildAt(0).visible = true; + final ActivityRecord focusedActivity = stack.getChildAt(0).getChildAt(0); + focusedActivity.nowVisible = true; + focusedActivity.visible = true; + focusedActivity.setState(RESUMED, "test"); + stack.mResumedActivity = focusedActivity; topActivity.completeFinishing("test"); @@ -1179,6 +1190,30 @@ public class ActivityRecordTests extends ActivityTestsBase { assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity)); } + /** + * Verify that complete finish request for visible activity must resume next home stack before + * destroying it immediately if it is the last running activity on a display with a home stack. + * We must wait for home activity to come up to avoid a black flash in this case. + */ + @Test + public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() { + // Empty the home stack. + final ActivityStack homeStack = mActivity.getDisplay().getHomeStack(); + for (TaskRecord t : homeStack.getAllTasks()) { + homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING); + } + mActivity.finishing = true; + spyOn(mStack); + + // Try to finish the last activity above the home stack. + mActivity.completeFinishing("test"); + + // Verify that the activity is not destroyed immediately, but waits for next one to come up. + verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString()); + assertEquals(FINISHING, mActivity.getState()); + assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity)); + } + /** * Test that the activity will be moved to destroying state and the message to destroy will be * sent to the client. From 3005aa78c7a02b54241858ee582618670bacddce Mon Sep 17 00:00:00 2001 From: Soonil Nagarkar Date: Wed, 30 Oct 2019 16:59:11 -0700 Subject: [PATCH 038/182] Prevent crash when invoking GNSS apis GNSS APIs may crash when invoked on devices without GNSS, fix this implementation. Bug: 143591625 Test: manual Change-Id: I6de563df96bc4605852989243c38e5d5278cbda0 (cherry picked from commit c4a4833708e01065627501c37f02084974470eaa) --- .../android/location/LocationManager.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 87b3be9cc26da..ca9d4d3e88126 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2757,9 +2757,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssStatusListener(); - return mService.registerGnssStatusCallback(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId()); + GnssStatusListener transport = new GnssStatusListener(); + if (mService.registerGnssStatusCallback(transport, mContext.getPackageName(), + mContext.getFeatureId())) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2817,10 +2822,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssMeasurementsListener(); - return mService.addGnssMeasurementsListener(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId(), - "gnss measurement callback"); + GnssMeasurementsListener transport = new GnssMeasurementsListener(); + if (mService.addGnssMeasurementsListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss measurement callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2854,10 +2863,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new GnssNavigationMessageListener(); - return mService.addGnssNavigationMessageListener(mListenerTransport, - mContext.getPackageName(), mContext.getFeatureId(), - "gnss navigation callback"); + GnssNavigationMessageListener transport = new GnssNavigationMessageListener(); + if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss navigation callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override @@ -2891,9 +2904,14 @@ public class LocationManager { protected boolean registerService() throws RemoteException { Preconditions.checkState(mListenerTransport == null); - mListenerTransport = new BatchedLocationCallback(); - return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName(), - mContext.getFeatureId(), "batched location callback"); + BatchedLocationCallback transport = new BatchedLocationCallback(); + if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(), + mContext.getFeatureId(), "batched location callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } } @Override From 00d8cbb291b114f5a6da941862401d4d99ced3e4 Mon Sep 17 00:00:00 2001 From: Andrei Onea Date: Wed, 30 Oct 2019 18:08:24 +0000 Subject: [PATCH 039/182] Initialize AppCompatCallbacks in system server This ensures that any calls made (intentionally or not) in the system server using the Compatibility (in-app process) gating APIs will always return true, and log the gated feature. Bug: 143591326 Test: m Change-Id: I96792cf852f4167fc39d5055704f8617efaae25e (cherry picked from commit f965d151cc4ddcc7c343b048e4493d011d379644) --- services/java/com/android/server/SystemServer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 58830487a0feb..c16f3e8d08da3 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -27,6 +27,7 @@ import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_ import android.annotation.NonNull; import android.annotation.StringRes; import android.app.ActivityThread; +import android.app.AppCompatCallbacks; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; @@ -646,6 +647,7 @@ public final class SystemServer { ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat); ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, new PlatformCompatNative(platformCompat)); + AppCompatCallbacks.install(new long[0]); t.traceEnd(); // Wait for installd to finish starting up so that it has a chance to From 8782993fb5dbc5eba4f6f74347d4de927a05aded Mon Sep 17 00:00:00 2001 From: Soonil Nagarkar Date: Fri, 1 Nov 2019 15:59:22 +0000 Subject: [PATCH 040/182] Revert "Create unit tests for GnssManagerService" This reverts commit b9f26b4c053764601456ba8f673e633980d9cd14. Reason for revert: Has broken RVC dogfood somehow. Bug: 143677802 Change-Id: I1c5150b65b03540017df769a6e7ba9eeee329c09 (cherry picked from commit a569845614b99eac4eda05a3247af7379944822b) --- .../android/server/GnssManagerService.java | 10 +- .../android/server/LocationUsageLogger.java | 2 +- .../server/location/GnssLocationProvider.java | 23 +- .../location/GnssMeasurementsProvider.java | 4 +- .../GnssNavigationMessageProvider.java | 4 +- .../server/GnssManagerServiceTest.java | 743 ------------------ 6 files changed, 13 insertions(+), 773 deletions(-) delete mode 100644 services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java diff --git a/services/core/java/com/android/server/GnssManagerService.java b/services/core/java/com/android/server/GnssManagerService.java index cbf2a622fd2e4..274e2f1b53f84 100644 --- a/services/core/java/com/android/server/GnssManagerService.java +++ b/services/core/java/com/android/server/GnssManagerService.java @@ -67,7 +67,7 @@ import java.util.function.Function; /** Manages Gnss providers and related Gnss functions for LocationManagerService. */ public class GnssManagerService { - private static final String TAG = "GnssManagerService"; + private static final String TAG = "LocationManagerService"; private static final boolean D = Log.isLoggable(TAG, Log.DEBUG); // Providers @@ -124,7 +124,7 @@ public class GnssManagerService { // Can use this constructor to inject GnssLocationProvider for testing @VisibleForTesting - public GnssManagerService(LocationManagerService locationManagerService, + GnssManagerService(LocationManagerService locationManagerService, Context context, GnssLocationProvider gnssLocationProvider, LocationUsageLogger locationUsageLogger) { @@ -719,10 +719,8 @@ public class GnssManagerService { * @param listener called when navigation message is received */ public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { - synchronized (mGnssNavigationMessageListeners) { - removeGnssDataListener( - listener, mGnssNavigationMessageProvider, mGnssNavigationMessageListeners); - } + removeGnssDataListener( + listener, mGnssNavigationMessageProvider, mGnssNavigationMessageListeners); } /** diff --git a/services/core/java/com/android/server/LocationUsageLogger.java b/services/core/java/com/android/server/LocationUsageLogger.java index a8a3cc47cfb0e..4ca74bf3aa915 100644 --- a/services/core/java/com/android/server/LocationUsageLogger.java +++ b/services/core/java/com/android/server/LocationUsageLogger.java @@ -30,7 +30,7 @@ import java.time.Instant; /** * Logger for Location API usage logging. */ -public class LocationUsageLogger { +class LocationUsageLogger { private static final String TAG = "LocationUsageLogger"; private static final boolean D = Log.isLoggable(TAG, Log.DEBUG); diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 11b9ac44ff7f0..8bf01a366f65c 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -67,7 +67,6 @@ import android.util.StatsLog; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.location.GpsNetInitiatedHandler; import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification; @@ -305,9 +304,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL); - private static boolean sIsInitialized = false; - private static boolean sStaticTestOverride = false; - // True if we are enabled @GuardedBy("mLock") private boolean mGpsEnabled; @@ -580,15 +576,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } - @VisibleForTesting - public static void setIsSupportedForTest(boolean override) { - sStaticTestOverride = override; - } - public static boolean isSupported() { - if (sStaticTestOverride) { - return true; - } return native_is_supported(); } @@ -610,13 +598,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements Looper looper) { super(context, locationProviderManager); - synchronized (mLock) { - if (!sIsInitialized) { - class_init_native(); - } - sIsInitialized = true; - } - mLooper = looper; // Create a wake lock @@ -2243,6 +2224,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // preallocated to avoid memory allocation in reportNmea() private byte[] mNmeaBuffer = new byte[120]; + static { + class_init_native(); + } + private static native void class_init_native(); private static native boolean native_is_supported(); diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java index 55e427f70180f..ec05c310e68da 100644 --- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java +++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java @@ -47,7 +47,7 @@ public abstract class GnssMeasurementsProvider } @VisibleForTesting - public GnssMeasurementsProvider( + GnssMeasurementsProvider( Context context, Handler handler, GnssMeasurementProviderNative aNative) { super(context, handler, TAG); mNative = aNative; @@ -158,7 +158,7 @@ public abstract class GnssMeasurementsProvider } @VisibleForTesting - public static class GnssMeasurementProviderNative { + static class GnssMeasurementProviderNative { public boolean isMeasurementSupported() { return native_is_measurement_supported(); } diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java index 983d1daa23679..4c45ef6657894 100644 --- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java +++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java @@ -45,7 +45,7 @@ public abstract class GnssNavigationMessageProvider } @VisibleForTesting - public GnssNavigationMessageProvider(Context context, Handler handler, + GnssNavigationMessageProvider(Context context, Handler handler, GnssNavigationMessageProviderNative aNative) { super(context, handler, TAG); mNative = aNative; @@ -142,7 +142,7 @@ public abstract class GnssNavigationMessageProvider } @VisibleForTesting - public static class GnssNavigationMessageProviderNative { + static class GnssNavigationMessageProviderNative { public boolean isNavigationMessageSupported() { return native_is_navigation_message_supported(); } diff --git a/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java deleted file mode 100644 index 9692c257079df..0000000000000 --- a/services/tests/servicestests/src/com/android/server/GnssManagerServiceTest.java +++ /dev/null @@ -1,743 +0,0 @@ -/* - * 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.server; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.testng.Assert.assertThrows; - -import android.Manifest; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.GnssClock; -import android.location.GnssMeasurementCorrections; -import android.location.GnssMeasurementsEvent; -import android.location.GnssNavigationMessage; -import android.location.GnssSingleSatCorrection; -import android.location.IBatchedLocationCallback; -import android.location.IGnssMeasurementsListener; -import android.location.IGnssNavigationMessageListener; -import android.location.IGnssStatusListener; -import android.location.INetInitiatedListener; -import android.location.Location; -import android.os.Handler; -import android.os.IBinder; -import android.os.IInterface; -import android.os.Message; -import android.os.RemoteException; - -import com.android.server.location.GnssBatchingProvider; -import com.android.server.location.GnssCapabilitiesProvider; -import com.android.server.location.GnssLocationProvider; -import com.android.server.location.GnssMeasurementCorrectionsProvider; -import com.android.server.location.GnssMeasurementsProvider; -import com.android.server.location.GnssMeasurementsProvider.GnssMeasurementProviderNative; -import com.android.server.location.GnssNavigationMessageProvider; -import com.android.server.location.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative; -import com.android.server.location.GnssStatusListenerHelper; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.AdditionalMatchers; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; - -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for {@link com.android.server.GnssManagerService}. - */ -public class GnssManagerServiceTest { - - // Gnss Providers - @Mock - private GnssLocationProvider mMockGnssLocationProvider; - @Mock - private GnssBatchingProvider mMockGnssBatchingProvider; - @Mock - private GnssLocationProvider.GnssSystemInfoProvider mMockGnssSystemInfoProvider; - @Mock - private GnssCapabilitiesProvider mMockGnssCapabilitiesProvider; - @Mock - private GnssMeasurementCorrectionsProvider mMockGnssMeasurementCorrectionsProvider; - @Mock - private INetInitiatedListener mMockNetInitiatedListener; - private GnssMeasurementsProvider mTestGnssMeasurementsProvider; - private GnssStatusListenerHelper mTestGnssStatusProvider; - private GnssNavigationMessageProvider mTestGnssNavigationMessageProvider; - - // Managers and services - @Mock - private AppOpsManager mMockAppOpsManager; - @Mock - private ActivityManager mMockActivityManager; - @Mock - private LocationManagerService mMockLocationManagerService; - - // Context and handler - @Mock - private Handler mMockHandler; - @Mock - private Context mMockContext; - - // Class under test - private GnssManagerService mGnssManagerService; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - GnssLocationProvider.setIsSupportedForTest(true); - - // Set up mock context - when(mMockContext.getSystemServiceName(AppOpsManager.class)).thenReturn( - Context.APP_OPS_SERVICE); - when(mMockContext.getSystemServiceName(ActivityManager.class)).thenReturn( - Context.ACTIVITY_SERVICE); - when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn( - mMockAppOpsManager); - when(mMockContext.getSystemService( - eq(Context.ACTIVITY_SERVICE))).thenReturn( - mMockActivityManager); - enableLocationPermissions(); - - // Mock Handler will execute posted runnables immediately - when(mMockHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer( - (InvocationOnMock invocation) -> { - Message msg = (Message) (invocation.getArguments()[0]); - msg.getCallback().run(); - return null; - }); - - // Setup providers - mTestGnssMeasurementsProvider = createGnssMeasurementsProvider( - mMockContext, mMockHandler); - mTestGnssStatusProvider = createGnssStatusListenerHelper( - mMockContext, mMockHandler); - mTestGnssNavigationMessageProvider = createGnssNavigationMessageProvider( - mMockContext, mMockHandler); - - // Setup GnssLocationProvider to return providers - when(mMockGnssLocationProvider.getGnssStatusProvider()).thenReturn( - mTestGnssStatusProvider); - when(mMockGnssLocationProvider.getGnssBatchingProvider()).thenReturn( - mMockGnssBatchingProvider); - when(mMockGnssLocationProvider.getGnssCapabilitiesProvider()).thenReturn( - mMockGnssCapabilitiesProvider); - when(mMockGnssLocationProvider.getGnssSystemInfoProvider()).thenReturn( - mMockGnssSystemInfoProvider); - when(mMockGnssLocationProvider.getGnssMeasurementCorrectionsProvider()).thenReturn( - mMockGnssMeasurementCorrectionsProvider); - when(mMockGnssLocationProvider.getGnssMeasurementsProvider()).thenReturn( - mTestGnssMeasurementsProvider); - when(mMockGnssLocationProvider.getGnssNavigationMessageProvider()).thenReturn( - mTestGnssNavigationMessageProvider); - when(mMockGnssLocationProvider.getNetInitiatedListener()).thenReturn( - mMockNetInitiatedListener); - - // Setup GnssBatching provider - when(mMockGnssBatchingProvider.start(anyLong(), anyBoolean())).thenReturn(true); - when(mMockGnssBatchingProvider.stop()).thenReturn(true); - - // Create GnssManagerService - mGnssManagerService = new GnssManagerService(mMockLocationManagerService, mMockContext, - mMockGnssLocationProvider, new LocationUsageLogger()); - } - - private void overrideAsBinder(IInterface mockListener) { - IBinder mockBinder = mock(IBinder.class); - when(mockListener.asBinder()).thenReturn(mockBinder); - } - - private IGnssStatusListener createMockGnssStatusListener() { - IGnssStatusListener mockListener = mock(IGnssStatusListener.class); - overrideAsBinder(mockListener); - return mockListener; - } - - private IGnssMeasurementsListener createMockGnssMeasurementsListener() { - IGnssMeasurementsListener mockListener = mock( - IGnssMeasurementsListener.class); - overrideAsBinder(mockListener); - return mockListener; - } - - private IBatchedLocationCallback createMockBatchedLocationCallback() { - IBatchedLocationCallback mockedCallback = mock(IBatchedLocationCallback.class); - overrideAsBinder(mockedCallback); - return mockedCallback; - } - - private IGnssNavigationMessageListener createMockGnssNavigationMessageListener() { - IGnssNavigationMessageListener mockListener = mock(IGnssNavigationMessageListener.class); - overrideAsBinder(mockListener); - return mockListener; - } - - private GnssMeasurementCorrections createDummyGnssMeasurementCorrections() { - GnssSingleSatCorrection gnssSingleSatCorrection = - new GnssSingleSatCorrection.Builder().build(); - return - new GnssMeasurementCorrections.Builder().setSingleSatelliteCorrectionList( - Arrays.asList(gnssSingleSatCorrection)).build(); - } - - private void enableLocationPermissions() { - Mockito.doThrow(new SecurityException()).when( - mMockContext).enforceCallingPermission( - AdditionalMatchers.and( - AdditionalMatchers.not(eq(Manifest.permission.LOCATION_HARDWARE)), - AdditionalMatchers.not(eq(Manifest.permission.ACCESS_FINE_LOCATION))), - anyString()); - when(mMockContext.checkPermission( - eq(android.Manifest.permission.LOCATION_HARDWARE), anyInt(), anyInt())).thenReturn( - PackageManager.PERMISSION_GRANTED); - - // AppOpsManager will return true if OP_FINE_LOCATION is checked - when(mMockAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer( - (InvocationOnMock invocation) -> { - int code = (int) (invocation.getArguments()[0]); - if (code == AppOpsManager.OP_FINE_LOCATION) { - return AppOpsManager.MODE_ALLOWED; - } - return AppOpsManager.MODE_ERRORED; - }); - } - - private void disableLocationPermissions() { - Mockito.doThrow(new SecurityException()).when( - mMockContext).enforceCallingPermission(anyString(), anyString()); - Mockito.doThrow(new SecurityException()).when( - mMockContext).checkPermission(anyString(), anyInt(), anyInt()); - - when(mMockAppOpsManager.checkOp(anyInt(), anyInt(), - anyString())).thenReturn(AppOpsManager.MODE_ERRORED); - } - - private GnssStatusListenerHelper createGnssStatusListenerHelper(Context context, - Handler handler) { - return new GnssStatusListenerHelper( - context, handler) { - @Override - protected boolean isAvailableInPlatform() { - return true; - } - - @Override - protected boolean isGpsEnabled() { - return true; - } - }; - } - - private GnssMeasurementsProvider createGnssMeasurementsProvider(Context context, - Handler handler) { - GnssMeasurementProviderNative - mockGnssMeasurementProviderNative = mock(GnssMeasurementProviderNative.class); - return new GnssMeasurementsProvider( - context, handler, mockGnssMeasurementProviderNative) { - @Override - protected boolean isGpsEnabled() { - return true; - } - }; - } - - private GnssNavigationMessageProvider createGnssNavigationMessageProvider(Context context, - Handler handler) { - GnssNavigationMessageProviderNative mockGnssNavigationMessageProviderNative = mock( - GnssNavigationMessageProviderNative.class); - return new GnssNavigationMessageProvider(context, handler, - mockGnssNavigationMessageProviderNative) { - @Override - protected boolean isGpsEnabled() { - return true; - } - }; - } - - @Test - public void getGnssYearOfHardwareTest() { - final int gnssYearOfHardware = 2012; - when(mMockGnssSystemInfoProvider.getGnssYearOfHardware()).thenReturn(gnssYearOfHardware); - enableLocationPermissions(); - - assertThat(mGnssManagerService.getGnssYearOfHardware()).isEqualTo(gnssYearOfHardware); - } - - @Test - public void getGnssHardwareModelNameTest() { - final String gnssHardwareModelName = "hardwarename"; - when(mMockGnssSystemInfoProvider.getGnssHardwareModelName()).thenReturn( - gnssHardwareModelName); - enableLocationPermissions(); - - assertThat(mGnssManagerService.getGnssHardwareModelName()).isEqualTo( - gnssHardwareModelName); - } - - @Test - public void getGnssCapabilitiesWithoutPermissionsTest() { - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.getGnssCapabilities("com.android.server")); - } - - @Test - public void getGnssCapabilitiesWithPermissionsTest() { - final long mGnssCapabilities = 23132L; - when(mMockGnssCapabilitiesProvider.getGnssCapabilities()).thenReturn(mGnssCapabilities); - enableLocationPermissions(); - - assertThat(mGnssManagerService.getGnssCapabilities("com.android.server")).isEqualTo( - mGnssCapabilities); - } - - @Test - public void getGnssBatchSizeWithoutPermissionsTest() { - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.getGnssBatchSize("com.android.server")); - } - - @Test - public void getGnssBatchSizeWithPermissionsTest() { - final int gnssBatchSize = 10; - when(mMockGnssBatchingProvider.getBatchSize()).thenReturn(gnssBatchSize); - enableLocationPermissions(); - - assertThat(mGnssManagerService.getGnssBatchSize("com.android.server")).isEqualTo( - gnssBatchSize); - } - - @Test - public void startGnssBatchWithoutPermissionsTest() { - final long periodNanos = 100L; - final boolean wakeOnFifoFull = true; - - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.startGnssBatch(periodNanos, wakeOnFifoFull, - "com.android.server")); - verify(mMockGnssBatchingProvider, times(0)).start(periodNanos, wakeOnFifoFull); - } - - @Test - public void startGnssBatchWithPermissionsTest() { - final long periodNanos = 100L; - final boolean wakeOnFifoFull = true; - - enableLocationPermissions(); - - assertThat(mGnssManagerService.startGnssBatch(periodNanos, wakeOnFifoFull, - "com.android.server")) - .isEqualTo( - true); - verify(mMockGnssBatchingProvider, times(1)).start(100L, true); - } - - @Test - public void addGnssBatchCallbackWithoutPermissionsTest() throws RemoteException { - IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback(); - List mockLocationList = (List) mock(List.class); - - disableLocationPermissions(); - - assertThrows(SecurityException.class, () -> mGnssManagerService.addGnssBatchingCallback( - mockBatchedLocationCallback, "com.android.server", "abcd123", - "TestBatchedLocationCallback")); - - mGnssManagerService.onReportLocation(mockLocationList); - - verify(mockBatchedLocationCallback, times(0)).onLocationBatch(mockLocationList); - } - - @Test - public void addGnssBatchCallbackWithPermissionsTest() throws RemoteException { - IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback(); - List mockLocationList = (List) mock(List.class); - - enableLocationPermissions(); - - assertThat(mGnssManagerService.addGnssBatchingCallback( - mockBatchedLocationCallback, "com.android.server", - "abcd123", "TestBatchedLocationCallback")).isEqualTo(true); - - mGnssManagerService.onReportLocation(mockLocationList); - - verify(mockBatchedLocationCallback, times(1)).onLocationBatch(mockLocationList); - } - - @Test - public void replaceGnssBatchCallbackTest() throws RemoteException { - IBatchedLocationCallback mockBatchedLocationCallback1 = createMockBatchedLocationCallback(); - IBatchedLocationCallback mockBatchedLocationCallback2 = createMockBatchedLocationCallback(); - List mockLocationList = (List) mock(List.class); - - enableLocationPermissions(); - - assertThat(mGnssManagerService.addGnssBatchingCallback( - mockBatchedLocationCallback1, "com.android.server", - "abcd123", "TestBatchedLocationCallback")).isEqualTo(true); - assertThat(mGnssManagerService.addGnssBatchingCallback( - mockBatchedLocationCallback2, "com.android.server", - "abcd123", "TestBatchedLocationCallback")).isEqualTo(true); - - mGnssManagerService.onReportLocation(mockLocationList); - - verify(mockBatchedLocationCallback1, times(0)).onLocationBatch(mockLocationList); - verify(mockBatchedLocationCallback2, times(1)).onLocationBatch(mockLocationList); - } - - @Test - public void flushGnssBatchWithoutPermissionsTest() { - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.flushGnssBatch("com.android.server")); - verify(mMockGnssBatchingProvider, times(0)).flush(); - } - - @Test - public void flushGnssBatchWithPermissionsTest() { - enableLocationPermissions(); - mGnssManagerService.flushGnssBatch("com.android.server"); - - verify(mMockGnssBatchingProvider, times(1)).flush(); - } - - @Test - public void removeGnssBatchingCallbackWithoutPermissionsTest() throws RemoteException { - IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback(); - List mockLocationList = (List) mock(List.class); - - enableLocationPermissions(); - - mGnssManagerService.addGnssBatchingCallback(mockBatchedLocationCallback, - "com.android.server", "abcd123", "TestBatchedLocationCallback"); - - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.removeGnssBatchingCallback()); - - mGnssManagerService.onReportLocation(mockLocationList); - - verify(mockBatchedLocationCallback, times(1)).onLocationBatch(mockLocationList); - } - - @Test - public void removeGnssBatchingCallbackWithPermissionsTest() throws RemoteException { - IBatchedLocationCallback mockBatchedLocationCallback = createMockBatchedLocationCallback(); - List mockLocationList = (List) mock(List.class); - - enableLocationPermissions(); - - mGnssManagerService.addGnssBatchingCallback(mockBatchedLocationCallback, - "com.android.server", "abcd123", "TestBatchedLocationCallback"); - - mGnssManagerService.removeGnssBatchingCallback(); - - mGnssManagerService.onReportLocation(mockLocationList); - - verify(mockBatchedLocationCallback, times(0)).onLocationBatch(mockLocationList); - } - - @Test - public void stopGnssBatchWithoutPermissionsTest() { - disableLocationPermissions(); - - assertThrows(SecurityException.class, () -> mGnssManagerService.stopGnssBatch()); - verify(mMockGnssBatchingProvider, times(0)).stop(); - } - - @Test - public void stopGnssBatchWithPermissionsTest() { - enableLocationPermissions(); - - assertThat(mGnssManagerService.stopGnssBatch()).isEqualTo(true); - verify(mMockGnssBatchingProvider, times(1)).stop(); - } - - @Test - public void registerGnssStatusCallbackWithoutPermissionsTest() throws RemoteException { - final int timeToFirstFix = 20000; - IGnssStatusListener mockGnssStatusListener = createMockGnssStatusListener(); - - disableLocationPermissions(); - - assertThrows(SecurityException.class, () -> mGnssManagerService - .registerGnssStatusCallback( - mockGnssStatusListener, "com.android.server", "abcd123")); - - mTestGnssStatusProvider.onFirstFix(timeToFirstFix); - - verify(mockGnssStatusListener, times(0)).onFirstFix(timeToFirstFix); - } - - @Test - public void registerGnssStatusCallbackWithPermissionsTest() throws RemoteException { - final int timeToFirstFix = 20000; - IGnssStatusListener mockGnssStatusListener = createMockGnssStatusListener(); - - enableLocationPermissions(); - - assertThat(mGnssManagerService.registerGnssStatusCallback( - mockGnssStatusListener, "com.android.server", "abcd123")).isEqualTo(true); - - mTestGnssStatusProvider.onFirstFix(timeToFirstFix); - - verify(mockGnssStatusListener, times(1)).onFirstFix(timeToFirstFix); - } - - @Test - public void unregisterGnssStatusCallbackWithPermissionsTest() throws RemoteException { - final int timeToFirstFix = 20000; - IGnssStatusListener mockGnssStatusListener = createMockGnssStatusListener(); - - enableLocationPermissions(); - - mGnssManagerService.registerGnssStatusCallback( - mockGnssStatusListener, "com.android.server", "abcd123"); - - mGnssManagerService.unregisterGnssStatusCallback(mockGnssStatusListener); - - mTestGnssStatusProvider.onFirstFix(timeToFirstFix); - - verify(mockGnssStatusListener, times(0)).onFirstFix(timeToFirstFix); - } - - @Test - public void addGnssMeasurementsListenerWithoutPermissionsTest() throws RemoteException { - IGnssMeasurementsListener mockGnssMeasurementsListener = - createMockGnssMeasurementsListener(); - GnssMeasurementsEvent gnssMeasurementsEvent = new GnssMeasurementsEvent(new GnssClock(), - null); - - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.addGnssMeasurementsListener( - mockGnssMeasurementsListener, - "com.android.server", "abcd123", "TestGnssMeasurementsListener")); - - mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent); - verify(mockGnssMeasurementsListener, times(0)).onGnssMeasurementsReceived( - gnssMeasurementsEvent); - } - - @Test - public void addGnssMeasurementsListenerWithPermissionsTest() throws RemoteException { - IGnssMeasurementsListener mockGnssMeasurementsListener = - createMockGnssMeasurementsListener(); - GnssMeasurementsEvent gnssMeasurementsEvent = new GnssMeasurementsEvent(new GnssClock(), - null); - - enableLocationPermissions(); - - assertThat(mGnssManagerService.addGnssMeasurementsListener(mockGnssMeasurementsListener, - "com.android.server", "abcd123", "TestGnssMeasurementsListener")).isEqualTo(true); - - mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent); - verify(mockGnssMeasurementsListener, times(1)).onGnssMeasurementsReceived( - gnssMeasurementsEvent); - } - - @Test - public void injectGnssMeasurementCorrectionsWithoutPermissionsTest() { - GnssMeasurementCorrections gnssMeasurementCorrections = - createDummyGnssMeasurementCorrections(); - - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.injectGnssMeasurementCorrections( - gnssMeasurementCorrections, "com.android.server")); - verify(mMockGnssMeasurementCorrectionsProvider, times(0)) - .injectGnssMeasurementCorrections( - gnssMeasurementCorrections); - } - - @Test - public void injectGnssMeasurementCorrectionsWithPermissionsTest() { - GnssMeasurementCorrections gnssMeasurementCorrections = - createDummyGnssMeasurementCorrections(); - - enableLocationPermissions(); - - mGnssManagerService.injectGnssMeasurementCorrections( - gnssMeasurementCorrections, "com.android.server"); - verify(mMockGnssMeasurementCorrectionsProvider, times(1)) - .injectGnssMeasurementCorrections( - gnssMeasurementCorrections); - } - - @Test - public void removeGnssMeasurementsListenerWithoutPermissionsTest() throws RemoteException { - IGnssMeasurementsListener mockGnssMeasurementsListener = - createMockGnssMeasurementsListener(); - GnssMeasurementsEvent gnssMeasurementsEvent = new GnssMeasurementsEvent(new GnssClock(), - null); - - enableLocationPermissions(); - - mGnssManagerService.addGnssMeasurementsListener(mockGnssMeasurementsListener, - "com.android.server", "abcd123", "TestGnssMeasurementsListener"); - - disableLocationPermissions(); - - mGnssManagerService.removeGnssMeasurementsListener( - mockGnssMeasurementsListener); - - mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent); - verify(mockGnssMeasurementsListener, times(0)).onGnssMeasurementsReceived( - gnssMeasurementsEvent); - } - - @Test - public void removeGnssMeasurementsListenerWithPermissionsTest() throws RemoteException { - IGnssMeasurementsListener mockGnssMeasurementsListener = - createMockGnssMeasurementsListener(); - GnssMeasurementsEvent gnssMeasurementsEvent = new GnssMeasurementsEvent(new GnssClock(), - null); - - enableLocationPermissions(); - - mGnssManagerService.addGnssMeasurementsListener(mockGnssMeasurementsListener, - "com.android.server", "abcd123", "TestGnssMeasurementsListener"); - - disableLocationPermissions(); - - mGnssManagerService.removeGnssMeasurementsListener( - mockGnssMeasurementsListener); - - mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent); - verify(mockGnssMeasurementsListener, times(0)).onGnssMeasurementsReceived( - gnssMeasurementsEvent); - } - - @Test - public void addGnssNavigationMessageListenerWithoutPermissionsTest() throws RemoteException { - IGnssNavigationMessageListener mockGnssNavigationMessageListener = - createMockGnssNavigationMessageListener(); - GnssNavigationMessage gnssNavigationMessage = new GnssNavigationMessage(); - - disableLocationPermissions(); - - assertThrows(SecurityException.class, - () -> mGnssManagerService.addGnssNavigationMessageListener( - mockGnssNavigationMessageListener, "com.android.server", - "abcd123", "TestGnssNavigationMessageListener")); - - mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage); - - verify(mockGnssNavigationMessageListener, times(0)).onGnssNavigationMessageReceived( - gnssNavigationMessage); - } - - @Test - public void addGnssNavigationMessageListenerWithPermissionsTest() throws RemoteException { - IGnssNavigationMessageListener mockGnssNavigationMessageListener = - createMockGnssNavigationMessageListener(); - GnssNavigationMessage gnssNavigationMessage = new GnssNavigationMessage(); - - enableLocationPermissions(); - - assertThat(mGnssManagerService.addGnssNavigationMessageListener( - mockGnssNavigationMessageListener, "com.android.server", - "abcd123", "TestGnssNavigationMessageListener")).isEqualTo(true); - - mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage); - - verify(mockGnssNavigationMessageListener, times(1)).onGnssNavigationMessageReceived( - gnssNavigationMessage); - } - - @Test - public void removeGnssNavigationMessageListenerWithoutPermissionsTest() throws RemoteException { - IGnssNavigationMessageListener mockGnssNavigationMessageListener = - createMockGnssNavigationMessageListener(); - GnssNavigationMessage gnssNavigationMessage = new GnssNavigationMessage(); - - enableLocationPermissions(); - - mGnssManagerService.addGnssNavigationMessageListener( - mockGnssNavigationMessageListener, "com.android.server", - "abcd123", "TestGnssNavigationMessageListener"); - - disableLocationPermissions(); - - mGnssManagerService.removeGnssNavigationMessageListener( - mockGnssNavigationMessageListener); - - mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage); - - verify(mockGnssNavigationMessageListener, times(0)).onGnssNavigationMessageReceived( - gnssNavigationMessage); - } - - @Test - public void removeGnssNavigationMessageListenerWithPermissionsTest() throws RemoteException { - IGnssNavigationMessageListener mockGnssNavigationMessageListener = - createMockGnssNavigationMessageListener(); - GnssNavigationMessage gnssNavigationMessage = new GnssNavigationMessage(); - - enableLocationPermissions(); - - mGnssManagerService.addGnssNavigationMessageListener( - mockGnssNavigationMessageListener, "com.android.server", - "abcd123", "TestGnssNavigationMessageListener"); - - mGnssManagerService.removeGnssNavigationMessageListener( - mockGnssNavigationMessageListener); - - mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage); - - verify(mockGnssNavigationMessageListener, times(0)).onGnssNavigationMessageReceived( - gnssNavigationMessage); - } - - @Test - public void sendNiResponseWithPermissionsTest() throws RemoteException { - when(mMockNetInitiatedListener.sendNiResponse(anyInt(), anyInt())).thenReturn(true); - - int notifId = 0; - int userResponse = 0; - enableLocationPermissions(); - - assertThat(mGnssManagerService.sendNiResponse(notifId, userResponse)).isEqualTo(true); - - verify(mMockNetInitiatedListener, times(1)).sendNiResponse(notifId, userResponse); - } -} From 494249aa7fbf4e725fd54010598b875b67b2d2b7 Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 8 Nov 2019 15:44:21 -0500 Subject: [PATCH 041/182] Call appOps changed from main thread Since it can cause an update to notification views and changes to the views must be done on the main thread Test: atest ForegroundServiceControllerTest Fixes: 144170894 Change-Id: I788d9b31c0f1ad8d2e1dd1df5ce743100f3a4a67 (cherry picked from commit d30d6d0610916421c44290986d2c60f6cff6bbfa) --- .../systemui/ForegroundServiceController.java | 18 +++++++++++++----- .../ForegroundServiceControllerTest.java | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java index c2d090e007152..385de4acfea81 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java @@ -16,6 +16,7 @@ package com.android.systemui; import android.annotation.Nullable; import android.app.AppOpsManager; +import android.os.Handler; import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.util.ArraySet; @@ -23,13 +24,13 @@ import android.util.SparseArray; import com.android.internal.messages.nano.SystemMessageProto; import com.android.systemui.appops.AppOpsController; +import com.android.systemui.dagger.qualifiers.MainHandler; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import javax.inject.Inject; import javax.inject.Singleton; - /** * Tracks state of foreground services and notifications related to foreground services per user. */ @@ -44,12 +45,18 @@ public class ForegroundServiceController { private final SparseArray mUserServices = new SparseArray<>(); private final Object mMutex = new Object(); private final NotificationEntryManager mEntryManager; + private final Handler mMainHandler; @Inject public ForegroundServiceController(NotificationEntryManager entryManager, - AppOpsController appOpsController) { + AppOpsController appOpsController, @MainHandler Handler mainHandler) { mEntryManager = entryManager; - appOpsController.addCallback(APP_OPS, this::onAppOpChanged); + mMainHandler = mainHandler; + appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> { + mMainHandler.post(() -> { + onAppOpChanged(code, uid, packageName, active); + }); + }); } /** @@ -113,7 +120,7 @@ public class ForegroundServiceController { * @param packageName package that created the notification * @param active whether the appOpCode is active or not */ - public void onAppOpChanged(int appOpCode, int uid, String packageName, boolean active) { + void onAppOpChanged(int appOpCode, int uid, String packageName, boolean active) { int userId = UserHandle.getUserId(uid); // Record active app ops synchronized (mMutex) { @@ -132,7 +139,8 @@ public class ForegroundServiceController { // Update appOp if there's an associated pending or visible notification: final String foregroundKey = getStandardLayoutKey(userId, packageName); if (foregroundKey != null) { - final NotificationEntry entry = mEntryManager.getPendingOrCurrentNotif(foregroundKey); + final NotificationEntry entry = mEntryManager.getPendingOrCurrentNotif( + foregroundKey); if (entry != null && uid == entry.getSbn().getUid() && packageName.equals(entry.getSbn().getPackageName())) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index bb4387eb4a2df..e63b6d6670fd0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -33,6 +33,7 @@ import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationManager; import android.os.Bundle; +import android.os.Handler; import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.widget.RemoteViews; @@ -64,11 +65,12 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { private NotificationEntryListener mEntryListener; @Mock private NotificationEntryManager mEntryManager; @Mock private AppOpsController mAppOpsController; + @Mock private Handler mMainHandler; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController); + mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController, mMainHandler); mListener = new ForegroundServiceNotificationListener( mContext, mFsc, mEntryManager); ArgumentCaptor entryListenerCaptor = From c0f7c425f19b9710a5330828d6eaf35e2418a5c3 Mon Sep 17 00:00:00 2001 From: Issei Suzuki Date: Thu, 14 Nov 2019 15:59:15 +0100 Subject: [PATCH 042/182] Revert "Clean up visibility related flags in ActivityRecord" This reverts commit c0edbbb521d354d4a93f9dec863c903706f0a5c4. Reason for revert: broke dev test (com.roidapp.photogrid) Fixes: 144403961 Change-Id: I71ef435cfbdab46d2e57f2ed68af3eff04958a99 (cherry picked from commit e63eac7a99f239fc396b0c9b04019a9fcbdf868d) --- .../android/server/windowmanagerservice.proto | 2 +- data/etc/services.core.protolog.json | 12 +++--- .../com/android/server/wm/ActivityRecord.java | 39 +++++++++---------- .../com/android/server/wm/DisplayContent.java | 2 +- .../core/java/com/android/server/wm/Task.java | 9 +++-- .../server/wm/WindowManagerService.java | 4 +- .../com/android/server/wm/WindowState.java | 12 +++--- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 23566a6df8475..553fc73380df6 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -236,7 +236,7 @@ message AppWindowTokenProto { optional bool fills_parent = 7; optional bool app_stopped = 8; optional bool visible_requested = 9; - optional bool client_visible = 10; + optional bool client_hidden = 10; optional bool defer_hiding_client = 11; optional bool reported_drawn = 12; optional bool reported_visible = 13; diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 3c89bfd43f178..b9a1346b7227b 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -55,12 +55,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-2006946193": { - "message": "setClientVisible: %s clientVisible=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "-2002500255": { "message": "Defer removing snapshot surface in %dms", "level": "VERBOSE", @@ -313,6 +307,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "-1456549051": { + "message": "setClientHidden: %s clientHidden=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-1455600136": { "message": "Attempted to add Dream window with unknown token %s. Aborting.", "level": "WARN", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2162bdeead056..5b5ea216a0a7d 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -173,7 +173,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_W import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked; import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN; import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED; -import static com.android.server.wm.AppWindowTokenProto.CLIENT_VISIBLE; +import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN; import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT; import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT; import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS; @@ -465,13 +465,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean mVisible; // Should this token's windows be visible? boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard // might hide this activity? - // True if the visible state of this token was forced to true due to a transferred starting + // True if the hidden state of this token was forced to false due to a transferred starting // window. private boolean mVisibleSetFromTransferredStartingWindow; // TODO: figure out how to consolidate with the same variable in ActivityRecord. private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client // process that it is hidden. - private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false + private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true // and reporting to the client that it is hidden. boolean sleeping; // have we told the activity to sleep? boolean nowVisible; // is this activity's window visible? @@ -536,8 +536,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private Task mLastParent; - // Have we told the window clients to show themselves? - private boolean mClientVisible; + // Have we told the window clients to hide themselves? + private boolean mClientHidden; boolean firstWindowDrawn; // Last drawn state we reported to the app token. @@ -861,7 +861,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent); pw.print(" mOrientation="); pw.println(mOrientation); pw.println(prefix + "mVisibleRequested=" + mVisibleRequested - + " mClientVisible=" + mClientVisible + + " mClientHidden=" + mClientHidden + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "") + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible); if (paused) { @@ -1520,7 +1520,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A inHistory = false; nowVisible = false; mDrawn = false; - mClientVisible = true; idle = false; hasBeenLaunched = false; mStackSupervisor = supervisor; @@ -3231,7 +3230,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mVisibleRequested = true; mVisibleSetFromTransferredStartingWindow = true; } - setClientVisible(fromActivity.mClientVisible); + setClientHidden(fromActivity.mClientHidden); transferAnimation(fromActivity); @@ -3886,7 +3885,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // We previously deferred telling the client to hide itself when visibility was // initially set to false. Now we would like it to hide, so go ahead and set it. mLastDeferHidingClient = deferHidingClient; - setClientVisible(false); + setClientHidden(true); } return; } @@ -3931,7 +3930,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A waitingToShow = true; // If the client isn't hidden, we don't need to reset the drawing state. - if (!isClientVisible()) { + if (isClientHidden()) { // Let's reset the draw state in order to prevent the starting window to be // immediately dismissed when the app still has the surface. forAllWindows(w -> { @@ -3951,7 +3950,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // we still need to tell the client to make its windows visible so they get drawn. // Otherwise, we will wait on performing the transition until all windows have been // drawn, they never will be, and we are sad. - setClientVisible(true); + setClientHidden(false); requestUpdateWallpaperIfNeeded(); @@ -4099,7 +4098,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // If we're becoming invisible, update the client visibility if we are not running an // animation. Otherwise, we'll update client visibility in onAnimationFinished. if (visible || !isAnimating()) { - setClientVisible(visible); + setClientHidden(!visible); } if (!displayContent.mClosingApps.contains(this) @@ -5131,18 +5130,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - boolean isClientVisible() { - return mClientVisible; + boolean isClientHidden() { + return mClientHidden; } - void setClientVisible(boolean clientVisible) { - if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) { + void setClientHidden(boolean hideClient) { + if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) { return; } ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, - "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible, + "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient, Debug.getCallers(5)); - mClientVisible = clientVisible; + mClientHidden = hideClient; sendAppVisibilityToClients(); } @@ -5925,7 +5924,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A "AppWindowToken"); clearThumbnail(); - setClientVisible(isVisible() || mVisibleRequested); + setClientHidden(!isVisible() && !mVisibleRequested); getDisplayContent().computeImeTargetIfNeeded(this); @@ -7347,7 +7346,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A proto.write(FILLS_PARENT, mOccludesParent); proto.write(APP_STOPPED, mAppStopped); proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested); - proto.write(CLIENT_VISIBLE, mClientVisible); + proto.write(CLIENT_HIDDEN, mClientHidden); proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient); proto.write(REPORTED_DRAWN, reportedDrawn); proto.write(REPORTED_VISIBLE, reportedVisible); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 6eb9dba254d8e..e78e30248131f 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3061,7 +3061,7 @@ class DisplayContent extends WindowContainer Date: Thu, 14 Nov 2019 16:19:54 +0100 Subject: [PATCH 043/182] Revert "Clean up visibility related flags in WindowToken" This reverts commit cf0d2ae88dddc97b4873a2df787a5e962395bfe1. Reason for revert: broke dev test (com.roidapp.photogrid) Fixes: 144403961 Change-Id: I77920d16062190b4565d4c95687b06fc587f9817 (cherry picked from commit 7b9e257908deb8eb544b88384dfc1a8af4323272) --- .../server/activitymanagerservice.proto | 3 +- .../android/server/windowmanagerservice.proto | 4 +- data/etc/services.core.protolog.json | 56 +++++------ .../com/android/server/wm/ActivityRecord.java | 97 +++++++++---------- .../server/wm/AppTransitionController.java | 7 +- .../com/android/server/wm/DisplayContent.java | 4 +- .../server/wm/WallpaperController.java | 10 +- .../server/wm/WallpaperWindowToken.java | 10 +- .../com/android/server/wm/WindowState.java | 10 +- .../com/android/server/wm/WindowToken.java | 25 +++-- .../android/server/wm/ActivityTestsBase.java | 2 +- .../wm/AppTransitionControllerTest.java | 4 +- .../server/wm/AppWindowTokenTests.java | 6 +- .../wm/RecentsAnimationControllerTest.java | 2 +- .../android/server/wm/WindowStateTests.java | 8 +- .../android/server/wm/WindowTestUtils.java | 2 +- 16 files changed, 129 insertions(+), 121 deletions(-) diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index ce2717bb27795..8f084abe71a76 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -126,12 +126,11 @@ message ActivityRecordProto { optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true]; optional .com.android.server.wm.IdentifierProto identifier = 2; optional string state = 3; - optional bool visible_requested = 4; + optional bool visible = 4; optional bool front_of_task = 5; optional int32 proc_id = 6; optional bool translucent = 7; optional .com.android.server.wm.AppWindowTokenProto app_window_token = 8; - optional bool visible = 9; } message KeyguardControllerProto { diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 553fc73380df6..3db24778a2c9a 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -248,9 +248,8 @@ message AppWindowTokenProto { optional IdentifierProto starting_window = 19; optional bool starting_displayed = 20; optional bool starting_moved = 21; - optional bool visible_set_from_transferred_starting_window = 22; + optional bool hidden_set_from_transferred_starting_window = 22; repeated .android.graphics.RectProto frozen_bounds = 23; - optional bool visible = 24; } /* represents WindowToken */ @@ -260,6 +259,7 @@ message WindowTokenProto { optional WindowContainerProto window_container = 1; optional int32 hash_code = 2; repeated WindowStateProto windows = 3; + optional bool hidden = 4; optional bool waiting_to_show = 5; optional bool paused = 6; } diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index b9a1346b7227b..9b3198073e610 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -73,10 +73,10 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "-1976550065": { - "message": "commitVisibility: %s: visible=%b visibleRequested=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", + "-1972506791": { + "message": "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-1963461591": { @@ -85,6 +85,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-1958209312": { + "message": "Clear freezing of %s: hidden=%b freezing=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-1953668890": { "message": "Can't start recents animation, nextAppTransition=%s", "level": "DEBUG", @@ -547,6 +553,12 @@ "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/WindowState.java" }, + "-931184679": { + "message": "Changing app %s hidden=%b performLayout=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-928291778": { "message": "applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s", "level": "VERBOSE", @@ -835,12 +847,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "-374767836": { - "message": "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "-371630969": { "message": "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s", "level": "VERBOSE", @@ -883,6 +889,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "-229838822": { + "message": "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-198463978": { "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b", "level": "VERBOSE", @@ -1267,12 +1279,6 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "466506262": { - "message": "Clear freezing of %s: visible=%b freezing=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "474000473": { "message": "No stack above target stack=%s", "level": "DEBUG", @@ -1489,12 +1495,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "841702299": { - "message": "Changing app %s visible=%b performLayout=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_APP_TRANSITIONS", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "845234215": { "message": "App is requesting an orientation, return %d for display id=%d", "level": "VERBOSE", @@ -1903,12 +1903,6 @@ "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "1746778201": { - "message": "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s", - "level": "INFO", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/ActivityRecord.java" - }, "1747941491": { "message": "SURFACE controller=%s alpha=%f matrix=[%f*%f,%f*%f][%f*%f,%f*%f]: %s", "level": "INFO", @@ -1999,6 +1993,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, + "1965198071": { + "message": "commitVisibility: %s: hidden=%b visibleRequested=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "1984470582": { "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d", "level": "DEBUG", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 5b5ea216a0a7d..431d8c4139f84 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -121,7 +121,6 @@ import static com.android.server.am.ActivityRecordProto.PROC_ID; import static com.android.server.am.ActivityRecordProto.STATE; import static com.android.server.am.ActivityRecordProto.TRANSLUCENT; import static com.android.server.am.ActivityRecordProto.VISIBLE; -import static com.android.server.am.ActivityRecordProto.VISIBLE_REQUESTED; import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY; import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; @@ -177,6 +176,7 @@ import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN; import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT; import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT; import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS; +import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW; import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING; import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START; import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN; @@ -191,7 +191,7 @@ import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED; import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED; import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW; import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL; -import static com.android.server.wm.AppWindowTokenProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW; +import static com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED; import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN; import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; @@ -462,13 +462,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean keysPaused; // has key dispatching been paused for it? int launchMode; // the launch mode activity attribute. int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override - private boolean mVisible; // Should this token's windows be visible? boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard // might hide this activity? // True if the hidden state of this token was forced to false due to a transferred starting // window. - private boolean mVisibleSetFromTransferredStartingWindow; - // TODO: figure out how to consolidate with the same variable in ActivityRecord. + private boolean mHiddenSetFromTransferredStartingWindow; + // TODO: figureout how to consolidate with the same variable in ActivityRecord. private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client // process that it is hidden. private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true @@ -854,7 +853,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.println(requestedVrComponent); } super.dump(pw, prefix, dumpAll); - pw.print(" visible="); pw.print(mVisible); if (appToken != null) { pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction); } @@ -886,13 +884,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(" mIsExiting="); pw.println(mIsExiting); } if (startingWindow != null || startingSurface != null - || startingDisplayed || startingMoved || mVisibleSetFromTransferredStartingWindow) { + || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) { pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); pw.print(" startingSurface="); pw.print(startingSurface); pw.print(" startingDisplayed="); pw.print(startingDisplayed); pw.print(" startingMoved="); pw.print(startingMoved); pw.println(" mHiddenSetFromTransferredStartingWindow=" - + mVisibleSetFromTransferredStartingWindow); + + mHiddenSetFromTransferredStartingWindow); } if (!mFrozenBounds.isEmpty()) { pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds); @@ -1488,7 +1486,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Application tokens start out hidden. - setVisible(false); + setHidden(true); mVisibleRequested = false; ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService( @@ -3212,7 +3210,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A "Removing starting %s from %s", tStartingWindow, fromActivity); fromActivity.removeChild(tStartingWindow); fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow); - fromActivity.mVisibleSetFromTransferredStartingWindow = false; + fromActivity.mHiddenSetFromTransferredStartingWindow = false; addWindow(tStartingWindow); // Propagate other interesting state between the tokens. If the old token is displayed, @@ -3225,10 +3223,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (fromActivity.firstWindowDrawn) { firstWindowDrawn = true; } - if (fromActivity.isVisible()) { - setVisible(true); + if (!fromActivity.isHidden()) { + setHidden(false); mVisibleRequested = true; - mVisibleSetFromTransferredStartingWindow = true; + mHiddenSetFromTransferredStartingWindow = true; } setClientHidden(fromActivity.mClientHidden); @@ -3842,14 +3840,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean isVisible() { // If the activity isn't hidden then it is considered visible and there is no need to check // its children windows to see if they are visible. - return mVisible; - } - - void setVisible(boolean visible) { - if (visible != mVisible) { - mVisible = visible; - scheduleAnimation(); - } + return !isHidden(); } void setVisibility(boolean visible) { @@ -3891,8 +3882,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, - "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s", - appToken, visible, appTransition, isVisible(), mVisibleRequested, + "setAppVisibility(%s, visible=%b): %s hidden=%b mVisibleRequested=%b Callers=%s", + appToken, visible, appTransition, isHidden(), mVisibleRequested, Debug.getCallers(6)); final DisplayContent displayContent = getDisplayContent(); @@ -3922,11 +3913,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A startingMoved = false; // If the token is currently hidden (should be the common case), or has been // stopped, then we need to set up to wait for its windows to be ready. - if (!isVisible() || mAppStopped) { + if (isHidden() || mAppStopped) { clearAllDrawn(); // If the app was already visible, don't reset the waitingToShow state. - if (!isVisible()) { + if (isHidden()) { waitingToShow = true; // If the client isn't hidden, we don't need to reset the drawing state. @@ -3996,9 +3987,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { boolean delayed = false; - // Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually + // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually // been set by the app now. - mVisibleSetFromTransferredStartingWindow = false; + mHiddenSetFromTransferredStartingWindow = false; // Allow for state changes and animation to be applied if: // * token is transitioning visibility state @@ -4008,7 +3999,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // * or the token is the opening app and visible while opening task behind existing one. final DisplayContent displayContent = getDisplayContent(); boolean visibilityChanged = false; - if (isVisible() != visible || (!isVisible() && mIsExiting) + if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement()) || (visible && displayContent.mOpeningApps.contains(this) && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) { @@ -4016,7 +4007,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mWmService.mAccessibilityController; boolean changed = false; ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, - "Changing app %s visible=%b performLayout=%b", this, isVisible(), + "Changing app %s hidden=%b performLayout=%b", this, isHidden(), performLayout); boolean runningAppAnimation = false; @@ -4041,7 +4032,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A changed |= win.onAppVisibilityChanged(visible, runningAppAnimation); } - setVisible(visible); + setHidden(!visible); mVisibleRequested = visible; visibilityChanged = true; if (!visible) { @@ -4060,8 +4051,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, - "commitVisibility: %s: visible=%b visibleRequested=%b", this, - isVisible(), mVisibleRequested); + "commitVisibility: %s: hidden=%b visibleRequested=%b", this, + isHidden(), mVisibleRequested); if (changed) { displayContent.getInputMonitor().setUpdateInputWindowsNeededLw(); @@ -4125,7 +4116,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // no animation but there will still be a transition set. // We still need to delay hiding the surface such that it // can be synchronized with showing the next surface in the transition. - if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) { + if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) { SurfaceControl.openTransaction(); for (int i = mChildren.size() - 1; i >= 0; i--) { mChildren.get(i).mWinAnimator.hide("immediately hidden"); @@ -4137,6 +4128,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return delayed; } + @Override + void setHidden(boolean hidden) { + super.setHidden(hidden); + scheduleAnimation(); + } + @Override void onAppTransitionDone() { sendingToBottom = false; @@ -4902,8 +4899,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void startFreezingScreen() { ProtoLog.i(WM_DEBUG_ORIENTATION, - "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s", - appToken, isVisible(), mFreezingScreen, mVisibleRequested, + "Set freezing of %s: hidden=%b freezing=%b visibleRequested=%b. %s", + appToken, isHidden(), mFreezingScreen, mVisibleRequested, new RuntimeException().fillInStackTrace()); if (mVisibleRequested) { if (!mFreezingScreen) { @@ -4941,8 +4938,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } ProtoLog.v(WM_DEBUG_ORIENTATION, - "Clear freezing of %s: visible=%b freezing=%b", appToken, - isVisible(), isFreezingScreen()); + "Clear freezing of %s: hidden=%b freezing=%b", appToken, + isHidden(), isFreezingScreen()); stopFreezingScreen(true, force); } } @@ -5102,7 +5099,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean nowGone = mReportedVisibilityResults.nowGone; boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting; - boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && isVisible(); + boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden(); if (!nowGone) { // If the app is not yet gone, then it can only become visible/drawn. if (!nowDrawn) { @@ -5463,11 +5460,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // well there is no point now. ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData"); mStartingData = null; - if (mVisibleSetFromTransferredStartingWindow) { - // We set the visible state to true for the token from a transferred starting - // window. We now reset it back to false since the starting window was the last - // window in the token. - setVisible(false); + if (mHiddenSetFromTransferredStartingWindow) { + // We set the hidden state to false for the token from a transferred starting window. + // We now reset it back to true since the starting window was the last window in the + // token. + setHidden(true); } } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) { // If this is the last window except for a starting transition window, @@ -5805,7 +5802,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void prepareSurfaces() { - final boolean show = isVisible() || isAnimating(); + final boolean show = !isHidden() || isAnimating(); if (mSurfaceControl != null) { if (show && !mLastSurfaceShowing) { @@ -5924,7 +5921,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A "AppWindowToken"); clearThumbnail(); - setClientHidden(!isVisible() && !mVisibleRequested); + setClientHidden(isHidden() && !mVisibleRequested); getDisplayContent().computeImeTargetIfNeeded(this); @@ -7308,13 +7305,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL); writeIdentifierToProto(proto, IDENTIFIER); proto.write(STATE, mState.toString()); - proto.write(VISIBLE_REQUESTED, mVisibleRequested); + proto.write(VISIBLE, mVisibleRequested); proto.write(FRONT_OF_TASK, isRootOfTask()); if (hasProcess()) { proto.write(PROC_ID, app.getPid()); } proto.write(TRANSLUCENT, !occludesParent()); - proto.write(VISIBLE, mVisible); } public void writeToProto(ProtoOutputStream proto, long fieldId) { @@ -7345,7 +7341,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } proto.write(FILLS_PARENT, mOccludesParent); proto.write(APP_STOPPED, mAppStopped); - proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested); + proto.write(VISIBLE_REQUESTED, mVisibleRequested); proto.write(CLIENT_HIDDEN, mClientHidden); proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient); proto.write(REPORTED_DRAWN, reportedDrawn); @@ -7360,12 +7356,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } proto.write(STARTING_DISPLAYED, startingDisplayed); proto.write(STARTING_MOVED, startingMoved); - proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW, - mVisibleSetFromTransferredStartingWindow); + proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW, + mHiddenSetFromTransferredStartingWindow); for (Rect bounds : mFrozenBounds) { bounds.writeToProto(proto, FROZEN_BOUNDS); } - proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE, mVisible); proto.end(token); } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index ff1b42377f5fa..bef6af350269d 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -688,16 +688,15 @@ public class AppTransitionController { * compare z-order. * * @param apps The list of apps to search. - * @param ignoreInvisible If set to true, ignores apps that are not - * {@link ActivityRecord#isVisible}. + * @param ignoreHidden If set to true, ignores apps that are {@link ActivityRecord#isHidden}. * @return The top {@link ActivityRecord}. */ - private ActivityRecord getTopApp(ArraySet apps, boolean ignoreInvisible) { + private ActivityRecord getTopApp(ArraySet apps, boolean ignoreHidden) { int topPrefixOrderIndex = Integer.MIN_VALUE; ActivityRecord topApp = null; for (int i = apps.size() - 1; i >= 0; i--) { final ActivityRecord app = apps.valueAt(i); - if (ignoreInvisible && !app.isVisible()) { + if (ignoreHidden && app.isHidden()) { continue; } final int prefixOrderIndex = app.getPrefixOrderIndex(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e78e30248131f..ce49c91c0e1f3 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -652,11 +652,11 @@ class DisplayContent extends WindowContainer

To be supported, the service must also require the - * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so - * that other applications can not abuse it. - */ - public static final String SERVICE_INTERFACE = - "android.service.autofill.InlineSuggestionRenderService"; - - private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true); - - private void handleRenderSuggestion(IInlineSuggestionUiCallback callback, - InlinePresentation presentation, int width, int height) { - //TODO(b/146453086): implementation in ExtService - } - - @Override - @Nullable - public final IBinder onBind(@NonNull Intent intent) { - if (SERVICE_INTERFACE.equals(intent.getAction())) { - return new IInlineSuggestionRenderService.Stub() { - @Override - public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback, - @NonNull InlinePresentation presentation, int width, int height) { - mHandler.sendMessage(obtainMessage( - InlineSuggestionRenderService::handleRenderSuggestion, - InlineSuggestionRenderService.this, callback, presentation, - width, height)); - } - }.asBinder(); - } - - Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent); - return null; - } - - /** - * Renders the slice into a view. - */ - @Nullable - public View onRenderSuggestion(@NonNull InlinePresentation presentation, - int width, int height) { - Log.e(TAG, "service implementation (" + getClass() + " does not implement " - + "onRenderSuggestion()"); - return null; - } -} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4d319dfbe5252..f5c45e877ff41 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3339,13 +3339,6 @@ - - - - - - - - - diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 4d5af9ac5d5ce..bb8b12e86e168 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,11 +16,6 @@ package com.android.server.compat; -import static android.Manifest.permission.LOG_COMPAT_CHANGE; -import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; -import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; - import android.app.ActivityManager; import android.app.IActivityManager; import android.content.Context; @@ -73,14 +68,12 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChange(long changeId, ApplicationInfo appInfo) { - checkCompatChangeLogPermission(); reportChange(changeId, appInfo.uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED); } @Override public void reportChangeByPackageName(long changeId, String packageName, int userId) { - checkCompatChangeLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return; @@ -90,13 +83,11 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChangeByUid(long changeId, int uid) { - checkCompatChangeLogPermission(); reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED); } @Override public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { - checkCompatChangeReadPermission(); if (mCompatConfig.isChangeEnabled(changeId, appInfo)) { reportChange(changeId, appInfo.uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED); @@ -109,7 +100,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) { - checkCompatChangeReadPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return true; @@ -119,7 +109,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByUid(long changeId, int uid) { - checkCompatChangeReadPermission(); String[] packages = mContext.getPackageManager().getPackagesForUid(uid); if (packages == null || packages.length == 0) { return true; @@ -152,7 +141,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); killPackage(packageName); } @@ -160,13 +148,11 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); } @Override public void clearOverrides(String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); killPackage(packageName); } @@ -174,14 +160,12 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void clearOverridesForTest(String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); } @Override public boolean clearOverride(long changeId, String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); boolean existed = mCompatConfig.removeOverride(changeId, packageName); killPackage(packageName); return existed; @@ -189,13 +173,11 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { - checkCompatChangeReadPermission(); return mCompatConfig.getAppConfig(appInfo); } @Override public CompatibilityChangeInfo[] listAllChanges() { - checkCompatChangeReadPermission(); return mCompatConfig.dumpChanges(); } @@ -234,7 +216,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - checkCompatChangeReadPermission(); if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; mCompatConfig.dumpConfig(pw); } @@ -292,25 +273,4 @@ public class PlatformCompat extends IPlatformCompat.Stub { Binder.restoreCallingIdentity(identity); } } - - private void checkCompatChangeLogPermission() throws SecurityException { - if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot log compat change usage"); - } - } - - private void checkCompatChangeReadPermission() throws SecurityException { - if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot read compat change"); - } - } - - private void checkCompatChangeOverridePermission() throws SecurityException { - if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot override compat change"); - } - } } diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index b7c900130e397..d2ddff3627b9b 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -66,8 +66,6 @@ - - diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp index 609896ea9e959..5e9ef8efc4029 100644 --- a/tests/PlatformCompatGating/Android.bp +++ b/tests/PlatformCompatGating/Android.bp @@ -18,6 +18,7 @@ android_test { name: "PlatformCompatGating", // Only compile source java files in this apk. srcs: ["src/**/*.java"], + certificate: "platform", libs: [ "android.test.runner", "android.test.base", diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java index c00aa2ac25b3b..932ec643d4785 100644 --- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java +++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java @@ -16,9 +16,7 @@ package android.compat.testing; -import android.Manifest; import android.app.Instrumentation; -import android.app.UiAutomation; import android.compat.Compatibility; import android.compat.Compatibility.ChangeConfig; import android.content.Context; @@ -85,16 +83,12 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { @Override public void evaluate() throws Throwable { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - UiAutomation uiAutomation = instrumentation.getUiAutomation(); String packageName = instrumentation.getTargetContext().getPackageName(); IPlatformCompat platformCompat = IPlatformCompat.Stub .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); if (platformCompat == null) { throw new IllegalStateException("Could not get IPlatformCompat service!"); } - uiAutomation.adoptShellPermissionIdentity( - Manifest.permission.READ_COMPAT_CHANGE_CONFIG, - Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG); Compatibility.setOverrides(mConfig); try { platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig), @@ -107,7 +101,6 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { } catch (RemoteException e) { throw new RuntimeException("Could not call IPlatformCompat binder method!", e); } finally { - uiAutomation.dropShellPermissionIdentity(); Compatibility.clearOverrides(); } } From e25bd379ec282373c7f5c0b3ccdd7bf0da729a8e Mon Sep 17 00:00:00 2001 From: lumark Date: Fri, 31 Jan 2020 21:21:30 +0800 Subject: [PATCH 066/182] Fix Keyboard won't display when RemoteInput active Commit 970d9d2 instroduced IME focus controller which added a new method View#hasImeFocus to restrict the IME keyboard is focusble only when the focused window won't have either FLAG_NOT_FOCUSABLE or FLAG_ALT_FOCUSABLE_IM flags. Since NotificationShadeWindowController will unset both flags when RemoteInput active. But, in ImeFocusControler#onTraversal won't keep update View'ss mHasImeFocus state, it will affect IME focus handle correctness. Hense, it needs to fix View#hasImeFocus state update issue. Fix: 148489857 Bug: 141738570 Test: manual as following steps: 0) make EditTextVariations 1) adb install -r EditTextVariations.apk 2). adb shell am start -n com.android.inputmethod.tools.edittextvariations/.EditTextVariations 3). Tap the 3-dot menu on the EditTextVariations 4). Tap `Direct Reply` on the menu 5). Open notification drawers 6) Try to direct-reply on the notification, expect soft-keyboard should come up after step 6) Change-Id: I8d4fff94ba9313b773bc27fcbd019cc88580d3e9 (cherry picked from commit 655c367badbeb6c9d46e59fb117fe1d01928cf6d) --- core/java/android/view/ImeFocusController.java | 2 ++ core/java/android/view/inputmethod/InputMethodManager.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index 8d58ee83cd679..008abbf42a205 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -76,6 +76,8 @@ public final class ImeFocusController { return; } mHasImeFocus = hasImeFocus; + // Keep View#hasImeFocus up-to-dated when performing layout traversal. + mViewRootImpl.mAttachInfo.mHasImeFocus = mHasImeFocus; if (mHasImeFocus) { onPreWindowFocus(true /* hasWindowFocus */, windowAttribute); onPostWindowFocus(mViewRootImpl.mView.findFocus(), true /* hasWindowFocus */, diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 307abd2f5f65a..f0c16aadf12fe 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -671,6 +671,11 @@ public final class InputMethodManager { mWindowFocusGainFuture = null; } synchronized (mH) { + if (mCurRootView != null) { + // Reset the last served view and restart window focus state of the root view. + mCurRootView.getImeFocusController().setServedView(null); + mRestartOnNextWindowFocus = true; + } mCurRootView = rootView; } } From 5371be44a21e6525f9674ff4f2c6e9ae55485508 Mon Sep 17 00:00:00 2001 From: Danning Chen Date: Wed, 5 Feb 2020 11:52:46 -0800 Subject: [PATCH 067/182] Fix the NPE when reading the call log or SMS if a device has multiple user profiles Change-Id: Iec6485653367f2f005c2b7e17f23ab611e39e13b Bug: 148918224 Test: atest com.android.server.people.data.DataManagerTest (cherry picked from commit b3f852127efb8fb5e8db92179c7c64b08dfa9948) --- .../java/com/android/server/people/data/DataManager.java | 3 ++- .../src/com/android/server/people/data/DataManagerTest.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java index 79503f797318e..fb13b36bd084c 100644 --- a/services/people/java/com/android/server/people/data/DataManager.java +++ b/services/people/java/com/android/server/people/data/DataManager.java @@ -299,7 +299,8 @@ public class DataManager { private void forAllUnlockedUsers(Consumer consumer) { for (int i = 0; i < mUserDataArray.size(); i++) { - UserData userData = mUserDataArray.get(i); + int userId = mUserDataArray.keyAt(i); + UserData userData = mUserDataArray.get(userId); if (userData.isUnlocked()) { consumer.accept(userData); } diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java index 62ea425a54a72..db0afae4fc198 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java @@ -263,6 +263,7 @@ public final class DataManagerTest { @Test public void testContactsChanged() { mDataManager.onUserUnlocked(USER_ID_PRIMARY); + mDataManager.onUserUnlocked(USER_ID_SECONDARY); ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, buildPerson()); @@ -289,6 +290,7 @@ public final class DataManagerTest { @Test public void testNotificationListener() { mDataManager.onUserUnlocked(USER_ID_PRIMARY); + mDataManager.onUserUnlocked(USER_ID_SECONDARY); ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, buildPerson()); @@ -341,6 +343,7 @@ public final class DataManagerTest { @Test public void testCallLogContentObserver() { mDataManager.onUserUnlocked(USER_ID_PRIMARY); + mDataManager.onUserUnlocked(USER_ID_SECONDARY); ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, buildPerson()); @@ -368,6 +371,7 @@ public final class DataManagerTest { @Test public void testMmsSmsContentObserver() { mDataManager.onUserUnlocked(USER_ID_PRIMARY); + mDataManager.onUserUnlocked(USER_ID_SECONDARY); ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, buildPerson()); From 8677b515accd56feae7252272471ff3a577b8135 Mon Sep 17 00:00:00 2001 From: Kevin Han Date: Thu, 6 Feb 2020 16:54:50 -0800 Subject: [PATCH 068/182] Fix content views not updating Content views weren't getting marked dirty inherently on notification updates from the app, so the inflater wouldn't bother binding the content view again, even if the layout actually changed. This fixes that by providing the ability to mark all the active content views as dirty and needing to be rebound and calling it on add/update. Bug: 149002542 Test: repro from bug Test: atest RowContentBindStageTest Change-Id: I59d7f86e43763c3c03329a60a052e6c51cdc845a (cherry picked from commit 2745336f8f8d0a10451c9da4c4ce2cfe9795c358) --- .../inflation/NotificationRowBinderImpl.java | 1 + .../row/RowContentBindParams.java | 8 ++++++ .../row/RowContentBindStageTest.java | 26 +++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index 59d82a1bc5cf3..ecf62db4680bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -295,6 +295,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { } //TODO: Replace this API with RowContentBindParams directly row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry)); + params.rebindAllContentViews(); mRowContentBindStage.requestRebind(entry, en -> { row.setUsesIncreasedCollapsedHeight(useIncreasedCollapsedHeight); row.setUsesIncreasedHeadsUpHeight(useIncreasedHeadsUp); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java index 8280a63dedd9e..5170d0b85b17e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java @@ -122,6 +122,14 @@ public final class RowContentBindParams { return mContentViews; } + /** + * Request that all content views be rebound. This may happen if, for example, the underlying + * layout has changed. + */ + public void rebindAllContentViews() { + mDirtyContentViews = mContentViews; + } + /** * Clears all dirty content views so that they no longer need to be rebound. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java index 66aa5e18d0c93..775f722b13f9f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java @@ -67,7 +67,7 @@ public class RowContentBindStageTest extends SysuiTestCase { } @Test - public void testSetShouldContentViewsBeBound_bindsContent() { + public void testRequireContentViews() { // WHEN inflation flags are set and pipeline is invalidated. final int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry); @@ -85,7 +85,7 @@ public class RowContentBindStageTest extends SysuiTestCase { } @Test - public void testSetShouldContentViewsBeBound_unbindsContent() { + public void testFreeContentViews() { // GIVEN a view with all content bound. RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry); params.requireContentViews(FLAG_CONTENT_VIEW_ALL); @@ -99,6 +99,28 @@ public class RowContentBindStageTest extends SysuiTestCase { verify(mBinder).unbindContent(eq(mEntry), any(), eq(flags)); } + @Test + public void testRebindAllContentViews() { + // GIVEN a view with content bound. + RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry); + final int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; + params.requireContentViews(flags); + params.clearDirtyContentViews(); + + // WHEN we request rebind and stage executed. + params.rebindAllContentViews(); + mRowContentBindStage.executeStage(mEntry, mRow, (en) -> { }); + + // THEN binder binds inflation flags. + verify(mBinder).bindContent( + eq(mEntry), + any(), + eq(flags), + any(), + anyBoolean(), + any()); + } + @Test public void testSetUseLowPriority() { // GIVEN a view with all content bound. From 3f0d02858be32d52fb5351e61ca4e6e4fd33bfe9 Mon Sep 17 00:00:00 2001 From: Kevin Han Date: Thu, 6 Feb 2020 16:54:50 -0800 Subject: [PATCH 069/182] Fix content views not updating Content views weren't getting marked dirty inherently on notification updates from the app, so the inflater wouldn't bother binding the content view again, even if the layout actually changed. This fixes that by providing the ability to mark all the active content views as dirty and needing to be rebound and calling it on add/update. Bug: 149002542 Test: repro from bug Test: atest RowContentBindStageTest Change-Id: I59d7f86e43763c3c03329a60a052e6c51cdc845a (cherry picked from commit 2745336f8f8d0a10451c9da4c4ce2cfe9795c358) --- .../inflation/NotificationRowBinderImpl.java | 1 + .../row/RowContentBindParams.java | 8 ++++++ .../row/RowContentBindStageTest.java | 26 +++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index 59d82a1bc5cf3..ecf62db4680bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -295,6 +295,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { } //TODO: Replace this API with RowContentBindParams directly row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry)); + params.rebindAllContentViews(); mRowContentBindStage.requestRebind(entry, en -> { row.setUsesIncreasedCollapsedHeight(useIncreasedCollapsedHeight); row.setUsesIncreasedHeadsUpHeight(useIncreasedHeadsUp); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java index 8280a63dedd9e..5170d0b85b17e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java @@ -122,6 +122,14 @@ public final class RowContentBindParams { return mContentViews; } + /** + * Request that all content views be rebound. This may happen if, for example, the underlying + * layout has changed. + */ + public void rebindAllContentViews() { + mDirtyContentViews = mContentViews; + } + /** * Clears all dirty content views so that they no longer need to be rebound. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java index 66aa5e18d0c93..775f722b13f9f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java @@ -67,7 +67,7 @@ public class RowContentBindStageTest extends SysuiTestCase { } @Test - public void testSetShouldContentViewsBeBound_bindsContent() { + public void testRequireContentViews() { // WHEN inflation flags are set and pipeline is invalidated. final int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry); @@ -85,7 +85,7 @@ public class RowContentBindStageTest extends SysuiTestCase { } @Test - public void testSetShouldContentViewsBeBound_unbindsContent() { + public void testFreeContentViews() { // GIVEN a view with all content bound. RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry); params.requireContentViews(FLAG_CONTENT_VIEW_ALL); @@ -99,6 +99,28 @@ public class RowContentBindStageTest extends SysuiTestCase { verify(mBinder).unbindContent(eq(mEntry), any(), eq(flags)); } + @Test + public void testRebindAllContentViews() { + // GIVEN a view with content bound. + RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry); + final int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED; + params.requireContentViews(flags); + params.clearDirtyContentViews(); + + // WHEN we request rebind and stage executed. + params.rebindAllContentViews(); + mRowContentBindStage.executeStage(mEntry, mRow, (en) -> { }); + + // THEN binder binds inflation flags. + verify(mBinder).bindContent( + eq(mEntry), + any(), + eq(flags), + any(), + anyBoolean(), + any()); + } + @Test public void testSetUseLowPriority() { // GIVEN a view with all content bound. From 5709d34037154160623672d60c563c1a79a693ff Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Mon, 10 Feb 2020 22:12:44 +0000 Subject: [PATCH 070/182] Revert "Prevents an NPE when content provider is slow to start" This reverts commit 140fc2e9c9382d5326b72ff28e8782e7bffc493d. Reason for revert: b/149176266 Change-Id: I4015fcc1624ee116c4a013c99816d43ce7b24834 (cherry picked from commit 3a54effffdb361ccd60169dcce93cf4e87fc6dac) --- .../java/android/content/ContentResolver.java | 23 +------ core/tests/coretests/AndroidManifest.xml | 6 -- .../android/content/ContentResolverTest.java | 9 --- .../src/android/content/SlowProvider.java | 65 ------------------- .../server/am/ActivityManagerService.java | 27 ++++---- 5 files changed, 18 insertions(+), 112 deletions(-) delete mode 100644 core/tests/coretests/src/android/content/SlowProvider.java diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 0e0161ff4e9f6..f32a4ab433575 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -700,27 +700,6 @@ public abstract class ContentResolver implements ContentInterface { /** @hide */ public static final String REMOTE_CALLBACK_RESULT = "result"; - /** - * How long we wait for an attached process to publish its content providers - * before we decide it must be hung. - * @hide - */ - public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000; - - /** - * How long we wait for an provider to be published. Should be longer than - * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}. - * @hide - */ - public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS = - CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000; - - // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how - // long ActivityManagerService is giving a content provider to get published if a new process - // needs to be started for that. - private static final int GET_TYPE_TIMEOUT_MILLIS = - CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS + 5 * 1000; - public ContentResolver(@Nullable Context context) { this(context, null); } @@ -870,6 +849,8 @@ public abstract class ContentResolver implements ContentInterface { } } + private static final int GET_TYPE_TIMEOUT_MILLIS = 3000; + private static class GetTypeResultListener implements RemoteCallback.OnResultListener { @GuardedBy("this") public boolean done; diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 718ca46a4f18d..59335a5953347 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -1330,12 +1330,6 @@ android:process=":FakeProvider"> - - - Date: Mon, 10 Feb 2020 13:59:42 +0000 Subject: [PATCH 071/182] Fail silently on MediaScannerConnection#onScanCompleted MediaScannerConnection#onScanCompleted callback runs on background thread. Exception on the callback kills the process. To avoid this, ignore exceptions from callback for apps targeting Q or lower. This change fixes change in behavior from refactoring Ie959daa7576214024150faf84b44cdba00119257 where errors on the callback was handled on a binder thread that doesn't cause process crash. Test: atest frameworks/base/media/ directory Test: "in.mohalla.sharechat" app doesn't crash while sharing video. Test: "com.vkontakte.android" app doesn't crash while sending a photo. Bug: 147998630 Bug: 148925602 Change-Id: I5bd5f9fc22ac274da4d09c55dd639a6cca08be9b (cherry picked from commit 364d250fb72595fa3b927350cb38da6cac824624) --- .../android/media/MediaScannerConnection.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java index 05fa511fc81a8..2bffe8ac0649f 100644 --- a/media/java/android/media/MediaScannerConnection.java +++ b/media/java/android/media/MediaScannerConnection.java @@ -156,9 +156,7 @@ public class MediaScannerConnection implements ServiceConnection { } BackgroundThread.getExecutor().execute(() -> { final Uri uri = scanFileQuietly(mProvider, new File(path)); - if (mClient != null) { - mClient.onScanCompleted(path, uri); - } + runCallBack(mContext, mClient, path, uri); }); } } @@ -187,9 +185,7 @@ public class MediaScannerConnection implements ServiceConnection { .acquireContentProviderClient(MediaStore.AUTHORITY)) { for (String path : paths) { final Uri uri = scanFileQuietly(client, new File(path)); - if (callback != null) { - callback.onScanCompleted(path, uri); - } + runCallBack(context, callback, path, uri); } } }); @@ -206,6 +202,23 @@ public class MediaScannerConnection implements ServiceConnection { return uri; } + private static void runCallBack(Context context, OnScanCompletedListener callback, + String path, Uri uri) { + if (callback != null) { + // Ignore exceptions from callback to avoid calling app from crashing. + // Don't ignore exceptions for apps targeting 'R' or higher. + try { + callback.onScanCompleted(path, uri); + } catch (Throwable e) { + if (context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) { + throw e; + } else { + Log.w(TAG, "Ignoring exception from callback for backward compatibility", e); + } + } + } + } + @Deprecated static class ClientProxy implements MediaScannerConnectionClient { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O) From e7c0d667fc57afd12160ddff581943160467e06d Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Wed, 12 Feb 2020 17:16:10 +0000 Subject: [PATCH 072/182] Revert "Require user pass in a non-null BluetoothDevice to all B..." Revert "Pass in active device to all BluetoothA2dp APIs in packa..." Revert "Pass in active device to all BluetoothA2dp APIs in packa..." Revert submission 10253996-bt-a2dp-no-null Reason for revert: b/149361880 Reverted Changes: If43934374: Pass in active device to all BluetoothA2dp APIs in... I22dd1ca36: Make sure calls to BluetoothA2dp APIs pass non-nul... If6475af6f: Require user pass in a non-null BluetoothDevice to... I9d0e2c89c: Pass in active device to all BluetoothA2dp APIs in... I1faa6174d: Need to now pass in active device instead of null ... I69a941a7e: Pass in active device to all BluetoothA2dp APIs in... Change-Id: I297bda68da5023fd832201c485554d6bff05fa78 (cherry picked from commit 45fefe0f65b3ef28fe63372900fa9ea65d9326c0) --- api/system-current.txt | 14 ++++---- .../java/android/bluetooth/BluetoothA2dp.java | 34 +++++-------------- .../settingslib/bluetooth/A2dpProfile.java | 4 +-- .../bluetooth/A2dpProfileTest.java | 20 +++++------ 4 files changed, 27 insertions(+), 45 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 92307ba80e7fc..5cac2758ce6b2 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1452,16 +1452,16 @@ package android.app.usage { package android.bluetooth { public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice); method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothDevice getActiveDevice(); - method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@NonNull android.bluetooth.BluetoothDevice); + method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@Nullable android.bluetooth.BluetoothDevice); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int isOptionalCodecsEnabled(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int isOptionalCodecsSupported(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothCodecConfig); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int getOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothCodecConfig); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@NonNull android.bluetooth.BluetoothDevice, int); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice, int); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int supportsOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice); field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0 field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0 field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1 diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index b672a0857cca2..d8c653c6d0d50 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -643,9 +643,8 @@ public final class BluetoothA2dp implements BluetoothProfile { @SystemApi @Nullable @RequiresPermission(Manifest.permission.BLUETOOTH) - public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) { + public BluetoothCodecStatus getCodecStatus(@Nullable BluetoothDevice device) { if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")"); - verifyDeviceNotNull(device, "getCodecStatus"); try { final IBluetoothA2dp service = getService(); if (service != null && isEnabled()) { @@ -671,14 +670,9 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public void setCodecConfigPreference(@NonNull BluetoothDevice device, - @NonNull BluetoothCodecConfig codecConfig) { + public void setCodecConfigPreference(@Nullable BluetoothDevice device, + @Nullable BluetoothCodecConfig codecConfig) { if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")"); - verifyDeviceNotNull(device, "setCodecConfigPreference"); - if (codecConfig == null) { - Log.e(TAG, "setCodecConfigPreference: Codec config can't be null"); - throw new IllegalArgumentException("codecConfig cannot be null"); - } try { final IBluetoothA2dp service = getService(); if (service != null && isEnabled()) { @@ -701,9 +695,8 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public void enableOptionalCodecs(@NonNull BluetoothDevice device) { + public void enableOptionalCodecs(@Nullable BluetoothDevice device) { if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")"); - verifyDeviceNotNull(device, "enableOptionalCodecs"); enableDisableOptionalCodecs(device, true); } @@ -716,9 +709,8 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public void disableOptionalCodecs(@NonNull BluetoothDevice device) { + public void disableOptionalCodecs(@Nullable BluetoothDevice device) { if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")"); - verifyDeviceNotNull(device, "disableOptionalCodecs"); enableDisableOptionalCodecs(device, false); } @@ -758,8 +750,7 @@ public final class BluetoothA2dp implements BluetoothProfile { @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) @OptionalCodecsSupportStatus - public int isOptionalCodecsSupported(@NonNull BluetoothDevice device) { - verifyDeviceNotNull(device, "isOptionalCodecsSupported"); + public int supportsOptionalCodecs(@Nullable BluetoothDevice device) { try { final IBluetoothA2dp service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -784,8 +775,7 @@ public final class BluetoothA2dp implements BluetoothProfile { @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) @OptionalCodecsPreferenceStatus - public int isOptionalCodecsEnabled(@NonNull BluetoothDevice device) { - verifyDeviceNotNull(device, "isOptionalCodecsEnabled"); + public int getOptionalCodecsEnabled(@Nullable BluetoothDevice device) { try { final IBluetoothA2dp service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -810,9 +800,8 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public void setOptionalCodecsEnabled(@NonNull BluetoothDevice device, + public void setOptionalCodecsEnabled(@Nullable BluetoothDevice device, @OptionalCodecsPreferenceStatus int value) { - verifyDeviceNotNull(device, "setOptionalCodecsEnabled"); try { if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED @@ -865,13 +854,6 @@ public final class BluetoothA2dp implements BluetoothProfile { return false; } - private void verifyDeviceNotNull(BluetoothDevice device, String methodName) { - if (device == null) { - Log.e(TAG, methodName + ": device param is null"); - throw new IllegalArgumentException("Device cannot be null"); - } - } - private boolean isValidDevice(BluetoothDevice device) { if (device == null) return false; diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index d03a747b743c8..1ebe91736ba17 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -216,12 +216,12 @@ public class A2dpProfile implements LocalBluetoothProfile { } public boolean supportsHighQualityAudio(BluetoothDevice device) { - int support = mService.isOptionalCodecsSupported(device); + int support = mService.supportsOptionalCodecs(device); return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED; } public boolean isHighQualityAudioEnabled(BluetoothDevice device) { - int enabled = mService.isOptionalCodecsEnabled(device); + int enabled = mService.getOptionalCodecsEnabled(device); if (enabled != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN) { return enabled == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED; } else if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED && diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java index cb9092eba4414..c555cbec4bab9 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java @@ -73,26 +73,26 @@ public class A2dpProfileTest { @Test public void supportsHighQualityAudio() { - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED); assertThat(mProfile.supportsHighQualityAudio(mDevice)).isTrue(); - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED); assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse(); - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN); assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse(); } @Test public void isHighQualityAudioEnabled() { - when(mBluetoothA2dp.isOptionalCodecsEnabled(any())).thenReturn( + when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED); assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue(); - when(mBluetoothA2dp.isOptionalCodecsEnabled(any())).thenReturn( + when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED); assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse(); @@ -100,16 +100,16 @@ public class A2dpProfileTest { // then isHighQualityAudioEnabled() should return true or false based on whether optional // codecs are supported. If the device is connected then we should ask it directly, but if // the device isn't connected then rely on the stored pref about such support. - when(mBluetoothA2dp.isOptionalCodecsEnabled(any())).thenReturn( + when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); when(mBluetoothA2dp.getConnectionState(any())).thenReturn( BluetoothProfile.STATE_DISCONNECTED); - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED); assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse(); - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED); assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue(); @@ -151,14 +151,14 @@ public class A2dpProfileTest { // Most tests want to simulate optional codecs being supported by the device, so do that // by default here. - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED); } @Test public void getLableCodecsNotSupported() { setupLabelTest(); - when(mBluetoothA2dp.isOptionalCodecsSupported(any())).thenReturn( + when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED); assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL); } From d47fc70e417bfdd5d9b1ebc6cf57fa901f3a972c Mon Sep 17 00:00:00 2001 From: Wonsik Kim Date: Fri, 14 Feb 2020 11:13:22 -0800 Subject: [PATCH 073/182] Revert "Move libstatspull to the apex" This reverts commit 36f0eeaf103f269ce3568eaa2ec793ef54bb1902. Reason for revert: major functional regression Bug: 149538115 Change-Id: I7cc3c1a62e9d2d0bac7fc77848eeacbf8dc7dbe2 (cherry picked from commit dba4dfa1277c66ec23c2ce5ab895a2b744dc2478) --- apex/statsd/Android.bp | 2 -- apex/statsd/aidl/Android.bp | 6 +----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp index c0f84a0ba0702..1f9f18cd051a5 100644 --- a/apex/statsd/Android.bp +++ b/apex/statsd/Android.bp @@ -20,7 +20,6 @@ apex { apex_defaults { native_shared_libs: [ - "libstatspull", "libstats_jni", ], // binaries: ["vold"], @@ -29,7 +28,6 @@ apex_defaults { "service-statsd", ], // prebuilts: ["my_prebuilt"], - compile_multilib: "both", name: "com.android.os.statsd-defaults", key: "com.android.os.statsd.key", certificate: ":com.android.os.statsd.certificate", diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp index 4ccdd7e734dbf..7c93bc73e45db 100644 --- a/apex/statsd/aidl/Android.bp +++ b/apex/statsd/aidl/Android.bp @@ -38,10 +38,6 @@ aidl_interface { }, ndk: { enabled: true, - apex_available: [ - "com.android.os.statsd", - ], } - - }, + } } From adfcc2a11f3555668789648208943920808bfd87 Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Tue, 18 Feb 2020 19:07:02 +0000 Subject: [PATCH 074/182] Revert "Remove libstats_jni from the platform" Revert "Add com.android.os.statsd to linkerconfig" Revert submission 10302138-tej_jni Reason for revert: b/149720256 Reverted Changes: I1fe277bce: Limit metricslogger call into statsdw for events Id516e79e1: Add com.android.os.statsd to linkerconfig I22c2816c8: Remove libstats_jni from the platform Change-Id: I70857ef140b13aac073afee1936b49b7a96ccee5 (cherry picked from commit cbbaaae4402ba0ebd5d8fd1ad3a19b26898359e0) --- apex/statsd/Android.bp | 2 ++ apex/statsd/framework/java/android/util/StatsLog.java | 5 ----- core/jni/Android.bp | 1 + core/jni/AndroidRuntime.cpp | 2 ++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp index c8aa526254b8f..1f9f18cd051a5 100644 --- a/apex/statsd/Android.bp +++ b/apex/statsd/Android.bp @@ -71,5 +71,7 @@ cc_library_shared { apex_available: [ "com.android.os.statsd", "test_com.android.os.statsd", + //TODO (b/148620413): remove platform. + "//apex_available:platform", ], } \ No newline at end of file diff --git a/apex/statsd/framework/java/android/util/StatsLog.java b/apex/statsd/framework/java/android/util/StatsLog.java index 536b71a0e6252..511bc01f521eb 100644 --- a/apex/statsd/framework/java/android/util/StatsLog.java +++ b/apex/statsd/framework/java/android/util/StatsLog.java @@ -36,11 +36,6 @@ import com.android.internal.util.StatsdStatsLog; * define custom metrics inside statsd. */ public final class StatsLog { - - // Load JNI library - static { - System.loadLibrary("stats_jni"); - } private static final String TAG = "StatsLog"; private static final boolean DEBUG = false; private static final int EXPERIMENT_IDS_FIELD_ID = 1; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 900445c9835a7..653cbc90d88d7 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -272,6 +272,7 @@ cc_library_shared { "libnativewindow", "libdl", "libdl_android", + "libstats_jni", "libstatslog", "server_configurable_flags", "libstatspull", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index d790ada8083df..bbc23fec87ea2 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -108,6 +108,7 @@ namespace android { extern int register_android_app_admin_SecurityLog(JNIEnv* env); extern int register_android_content_AssetManager(JNIEnv* env); extern int register_android_util_EventLog(JNIEnv* env); +extern int register_android_util_StatsLog(JNIEnv* env); extern int register_android_util_StatsLogInternal(JNIEnv* env); extern int register_android_util_Log(JNIEnv* env); extern int register_android_util_MemoryIntArray(JNIEnv* env); @@ -1431,6 +1432,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_MemoryIntArray), + REG_JNI(register_android_util_StatsLog), REG_JNI(register_android_util_StatsLogInternal), REG_JNI(register_android_app_admin_SecurityLog), REG_JNI(register_android_content_AssetManager), From 146b8781c7f3a20792f5e10a94e5edbc0e6c91a8 Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Tue, 18 Feb 2020 19:07:02 +0000 Subject: [PATCH 075/182] Revert "Limit metricslogger call into statsdw for events" Revert "Add com.android.os.statsd to linkerconfig" Revert submission 10302138-tej_jni Reason for revert: b/149720256 Reverted Changes: I1fe277bce: Limit metricslogger call into statsdw for events Id516e79e1: Add com.android.os.statsd to linkerconfig I22c2816c8: Remove libstats_jni from the platform Change-Id: Ife857662618f5f5a40b00af79f688713c82a3a9c (cherry picked from commit 63c5613269516c9f33335eec946d45d9a4876801) --- core/java/com/android/internal/logging/MetricsLogger.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java index 75eb4aa052b00..140c410e8de6e 100644 --- a/core/java/com/android/internal/logging/MetricsLogger.java +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -55,11 +55,8 @@ public class MetricsLogger { protected void saveLog(LogMaker log) { // TODO(b/116684537): Flag guard logging to event log and statsd socket. EventLogTags.writeSysuiMultiAction(log.serialize()); - if (log.getCategory() != MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER - && log.getCategory() != MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM) { - FrameworkStatsLog.write(FrameworkStatsLog.KEY_VALUE_PAIRS_ATOM, - /* UID is retrieved from statsd side */ 0, log.getEntries()); - } + FrameworkStatsLog.write(FrameworkStatsLog.KEY_VALUE_PAIRS_ATOM, + /* UID is retrieved from statsd side */ 0, log.getEntries()); } public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN; From 1a5e6c75d8bcdc71b55fbab21964c186ef8ec9a7 Mon Sep 17 00:00:00 2001 From: Muhammad Qureshi Date: Tue, 18 Feb 2020 11:30:17 -0800 Subject: [PATCH 076/182] Re-add compile_multilib to statsd apex An earlier revert removed compile_multilib: both line which caused only 64-bit variant of libstats_jni to be added to the apex when 32-bit is also required. This change adds both 32-bit and 64-bit variants to the apex. Bug: 149720256 Test: m Test: fastboot flashall Test: launch Play Store Change-Id: I594b290e60052e28139cd954a54ada1067d43e09 (cherry picked from commit 6f83764ce50ef635a68daffbe705e27411dacab0) --- apex/statsd/Android.bp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp index c8aa526254b8f..0e9311034ee07 100644 --- a/apex/statsd/Android.bp +++ b/apex/statsd/Android.bp @@ -27,6 +27,7 @@ apex_defaults { "framework-statsd", "service-statsd", ], + compile_multilib: "both", // prebuilts: ["my_prebuilt"], name: "com.android.os.statsd-defaults", key: "com.android.os.statsd.key", @@ -72,4 +73,4 @@ cc_library_shared { "com.android.os.statsd", "test_com.android.os.statsd", ], -} \ No newline at end of file +} From 009bee3aeb1f1a995d6ad877805795bdf2da72da Mon Sep 17 00:00:00 2001 From: Ned Burns Date: Thu, 20 Feb 2020 20:16:29 -0500 Subject: [PATCH 077/182] Fix crash during SysUI dumpsys Sneaky-sneaky operator precedence. Null check was not actually preventing us from executing the right side of the &&. Test: manual Change-Id: I86686c5b06ef9fd5441255792a1574d9ecd94166 (cherry picked from commit 017b1bba894a28d0c4048e1ab93ed3008739b1ca) --- .../android/keyguard/KeyguardUpdateMonitor.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 52ea3009fd279..f57571d8d4b4c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2734,9 +2734,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId); BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId); pw.println(" Fingerprint state (user=" + userId + ")"); - pw.println(" allowed=" + fingerprint != null - && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric)); - pw.println(" auth'd=" + fingerprint != null && fingerprint.mAuthenticated); + pw.println(" allowed=" + + (fingerprint != null + && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric))); + pw.println(" auth'd=" + (fingerprint != null && fingerprint.mAuthenticated)); pw.println(" authSinceBoot=" + getStrongAuthTracker().hasUserAuthenticatedSinceBoot()); pw.println(" disabled(DPM)=" + isFingerprintDisabled(userId)); @@ -2751,9 +2752,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId); BiometricAuthenticated face = mUserFaceAuthenticated.get(userId); pw.println(" Face authentication state (user=" + userId + ")"); - pw.println(" allowed=" + face != null - && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric)); - pw.println(" auth'd=" + face != null && face.mAuthenticated); + pw.println(" allowed=" + + (face != null && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric))); + pw.println(" auth'd=" + + (face != null && face.mAuthenticated)); pw.println(" authSinceBoot=" + getStrongAuthTracker().hasUserAuthenticatedSinceBoot()); pw.println(" disabled(DPM)=" + isFaceDisabled(userId)); From d3b9baff62c82ccc34ee0573c2994cb7d51c9b8c Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Fri, 21 Feb 2020 15:21:41 -0500 Subject: [PATCH 078/182] Do not attempt to special case uncompressed font assets. The logic to attempt to directly mmap uncompressed font assets has resulted in breakages for some applications and utilities. This CL disables this speculative optimzation until we can determine the problem with this approach and if such an optimization is required. Bug: 149780695 Test: CtsTextTestCases and androidx.appcompat.widget.AppCompatTextViewTest Change-Id: I3b10a801a5600aefe8573fab1b28cd79c848c892 (cherry picked from commit dd03a8ef81064241943ae1788cf1c63ed3df35b7) --- .../java/android/graphics/fonts/Font.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java index 4899fbe431ccf..853165d4cf3f8 100644 --- a/graphics/java/android/graphics/fonts/Font.java +++ b/graphics/java/android/graphics/fonts/Font.java @@ -19,7 +19,6 @@ package android.graphics.fonts; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; -import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.content.res.Resources; import android.os.LocaleList; @@ -220,25 +219,6 @@ public final class Font { Preconditions.checkNotNull(am, "assetManager can not be null"); Preconditions.checkNotNull(path, "path can not be null"); - if (!isAsset) { - // Attempt to open as FD, which should work unless the asset is compressed - AssetFileDescriptor assetFD; - try { - if (cookie > 0) { - assetFD = am.openNonAssetFd(cookie, path); - } else { - assetFD = am.openNonAssetFd(path); - } - - try (FileInputStream fis = assetFD.createInputStream()) { - final FileChannel fc = fis.getChannel(); - return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); - } - } catch (IOException e) { - // failed to open as FD so now we will attempt to open as an input stream - } - } - try (InputStream assetStream = isAsset ? am.open(path, AssetManager.ACCESS_BUFFER) : am.openNonAsset(cookie, path, AssetManager.ACCESS_BUFFER)) { From 916f901137080d51a46c6971f7d9cc6670a54463 Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Sat, 22 Feb 2020 00:12:50 +0000 Subject: [PATCH 079/182] Revert "Avoid creating new instance on top when started for resu..." Revert "Add tests for start singleTop/singleInstance activity fo..." Revert submission 10112771-single-for-result Reason for revert: b/149877125 Reverted Changes: I923a0d9aa:Avoid creating new instance on top when started fo... I7d47580f8:Add tests for start singleTop/singleInstance activ... Change-Id: Ice262d1b8cada3b6c6fe0a5e8000bb59e0536596 (cherry picked from commit e0012bda2adf8f00c6f159a5210b43c0bc692272) --- .../core/java/com/android/server/wm/ActivityStarter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 600a125cdf43a..8878dee6b47ba 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1813,12 +1813,12 @@ class ActivityStarter { */ private int deliverToCurrentTopIfNeeded(ActivityStack topStack) { final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); - final boolean dontStart = top != null + final boolean dontStart = top != null && mStartActivity.resultTo == null && top.mActivityComponent.equals(mStartActivity.mActivityComponent) && top.mUserId == mStartActivity.mUserId && top.attachedToProcess() && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 - || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) + || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) // This allows home activity to automatically launch on secondary display when // display added, if home was the top activity on default display, instead of // sending new intent to the home activity on default display. @@ -2049,6 +2049,8 @@ class ActivityStarter { && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE) && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0; + sendNewTaskResultRequestIfNeeded(); + if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } @@ -2230,8 +2232,6 @@ class ActivityStarter { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } } - - sendNewTaskResultRequestIfNeeded(); } private void computeSourceStack() { From 275839894c14760e3f88bc4baad2b11498365189 Mon Sep 17 00:00:00 2001 From: Winson Date: Fri, 21 Feb 2020 17:32:14 -0800 Subject: [PATCH 080/182] Fix PackageSetting isUpdatedSystemApp and SYSTEM_EXT rescan When updating a PackageSetting, the existing one was not being considered, causing them to be assigned incorrectly on re-scan/re-install. The updatedSystemApp state was also being toggled incorrectly, as the previous code relied on the fact that a new Package object was created, implicitly resetting the fields as it was a new Java object with re-initialized fields. This disables the field explicitly when re-enabling a system app, as this action re-uses the existing PackageSetting that was previously associated with the /data copy. Also fixes scanning as SYSTEM_EXT when the disabled system package was also SYSTEM_EXT. Bug: 135203078 Bug: 149994952 Test: atest NexusLauncherTests:com.android.quickstep.StartLauncherViaGestureTests Merged-In: I81d126efc144725cac8af6810d33952295b375e1 Change-Id: I81d126efc144725cac8af6810d33952295b375e1 (cherry picked from commit 8359e40c9277005d93b9f9b6bcb09374d6ae7a8f) --- .../android/server/pm/PackageManagerService.java | 15 +++++++++------ .../core/java/com/android/server/pm/Settings.java | 3 +++ .../pm/permission/PermissionManagerService.java | 2 +- .../server/pm/pkg/PackageStateUnserialized.java | 3 +++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 077fc6f014295..2d8808052864d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -10969,10 +10969,10 @@ public class PackageManagerService extends IPackageManager.Stub // to null here, only to reset them at a later point. Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting, destCodeFile, destResourceFile, parsedPackage.getNativeLibraryDir(), - AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage), - AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage), - PackageInfoWithoutStateUtils.appInfoFlags(parsedPackage), - PackageInfoWithoutStateUtils.appInfoPrivateFlags(parsedPackage), + AndroidPackageUtils.getPrimaryCpuAbi(parsedPackage, pkgSetting), + AndroidPackageUtils.getSecondaryCpuAbi(parsedPackage, pkgSetting), + PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting), + PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting), UserManagerService.getInstance(), usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups()); @@ -11164,6 +11164,8 @@ public class PackageManagerService extends IPackageManager.Stub // TODO(b/135203078): Remove, move to constructor pkgSetting.pkg = parsedPackage; pkgSetting.pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting); + pkgSetting.pkgPrivateFlags = + PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting); if (parsedPackage.getLongVersionCode() != pkgSetting.versionCode) { pkgSetting.versionCode = parsedPackage.getLongVersionCode(); } @@ -16954,6 +16956,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean vendor = oldPackage.isVendor(); final boolean product = oldPackage.isProduct(); final boolean odm = oldPackage.isOdm(); + final boolean systemExt = oldPackage.isSystemExt(); final @ParseFlags int systemParseFlags = parseFlags; final @ScanFlags int systemScanFlags = scanFlags | SCAN_AS_SYSTEM @@ -16961,14 +16964,14 @@ public class PackageManagerService extends IPackageManager.Stub | (oem ? SCAN_AS_OEM : 0) | (vendor ? SCAN_AS_VENDOR : 0) | (product ? SCAN_AS_PRODUCT : 0) - | (odm ? SCAN_AS_ODM : 0); + | (odm ? SCAN_AS_ODM : 0) + | (systemExt ? SCAN_AS_SYSTEM_EXT : 0); if (DEBUG_INSTALL) { Slog.d(TAG, "replaceSystemPackageLI: new=" + parsedPackage + ", old=" + oldPackage); } res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); - ps.getPkgState().setUpdatedSystemApp(true); targetParseFlags = systemParseFlags; targetScanFlags = systemScanFlags; } else { // non system replace diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index af5c53606f9fc..24533184f5bf6 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -521,6 +521,9 @@ public final class Settings { p.secondaryCpuAbiString, p.cpuAbiOverrideString, p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags, p.usesStaticLibraries, p.usesStaticLibrariesVersions, p.mimeGroups); + if (ret != null) { + ret.getPkgState().setUpdatedSystemApp(false); + } mDisabledSysPackages.remove(name); return ret; } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 840c865d4732f..f647b6a94bf6b 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2794,7 +2794,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() && - !ps.isSystem() || !ps.getPkgState().isUpdatedSystemApp()) { + !ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) { // This is the first that we have heard about this package, so the // permissions we have now selected are fixed until explicitly // changed. diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java index c008d93ca91a3..e27bf48b6b61f 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java @@ -35,6 +35,9 @@ import java.util.List; * * It is assumed that anything inside the package was not cached or written to disk, so none of * these fields are either. They must be set on every boot from other state on the device. + * + * These fields are also not copied into any cloned PackageSetting, to preserve the old behavior + * where they would be lost implicitly by re-generating the package object. */ @DataClass(genSetters = true, genConstructor = false, genBuilder = false) public class PackageStateUnserialized { From c540e799f40f504438e73c892e4ff28c3e59d0d5 Mon Sep 17 00:00:00 2001 From: Ned Burns Date: Tue, 7 Jan 2020 20:34:23 -0500 Subject: [PATCH 081/182] Don't crash if NSSL gets incomplete gesture In *theory*, a View should always receive an ACTION_DOWN before receiving any other touch events, but this isn't always the case in practice. Whenever we see one of these "partial" gestures, we should ignore it until a real one starts. Test: manual Bug: 146323887 Change-Id: Ic75e4873993f0a8ec3e7210fc173d1fb0bd7b71f (cherry picked from commit d80ded29fbe1e876748ccc66579a5e82c921be65) --- .../stack/NotificationStackScrollLayout.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 1bd9bbecc26e1..3d41ef0adcce8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -3841,9 +3841,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); - final int action = ev.getAction(); + final int action = ev.getActionMasked(); - switch (action & MotionEvent.ACTION_MASK) { + if (ev.findPointerIndex(mActivePointerId) == -1 && action != MotionEvent.ACTION_DOWN) { + // Incomplete gesture, possibly due to window swap mid-gesture. Ignore until a new + // one starts. + Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent " + + MotionEvent.actionToString(ev.getActionMasked())); + return true; + } + + switch (action) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0 || !isInContentBounds(ev)) { return false; @@ -3866,10 +3874,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } case MotionEvent.ACTION_MOVE: final int activePointerIndex = ev.findPointerIndex(mActivePointerId); - if (activePointerIndex == -1) { - Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent"); - break; - } final int y = (int) ev.getY(activePointerIndex); final int x = (int) ev.getX(activePointerIndex); From 8c2212c7a3604daf6df4803416bd2cf5f574920e Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Sat, 22 Feb 2020 00:12:50 +0000 Subject: [PATCH 082/182] Revert "Avoid creating new instance on top when started for resu..." Revert "Add tests for start singleTop/singleInstance activity fo..." Revert submission 10112771-single-for-result Reason for revert: b/149877125 Reverted Changes: I923a0d9aa:Avoid creating new instance on top when started fo... I7d47580f8:Add tests for start singleTop/singleInstance activ... Change-Id: Ice262d1b8cada3b6c6fe0a5e8000bb59e0536596 (cherry picked from commit e0012bda2adf8f00c6f159a5210b43c0bc692272) It appears that the original reverts missed the master cutover to rvc-dev for rvc-release builds. b/150138994 tracks this issue (cherry picked from commit 8d250a622f845008be5b876d3785d293f7589dbc) Change-Id: Ie8238c19210c739715053d82a35d856d40b558f9 --- .../core/java/com/android/server/wm/ActivityStarter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 600a125cdf43a..8878dee6b47ba 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1813,12 +1813,12 @@ class ActivityStarter { */ private int deliverToCurrentTopIfNeeded(ActivityStack topStack) { final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); - final boolean dontStart = top != null + final boolean dontStart = top != null && mStartActivity.resultTo == null && top.mActivityComponent.equals(mStartActivity.mActivityComponent) && top.mUserId == mStartActivity.mUserId && top.attachedToProcess() && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 - || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) + || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) // This allows home activity to automatically launch on secondary display when // display added, if home was the top activity on default display, instead of // sending new intent to the home activity on default display. @@ -2049,6 +2049,8 @@ class ActivityStarter { && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE) && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0; + sendNewTaskResultRequestIfNeeded(); + if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } @@ -2230,8 +2232,6 @@ class ActivityStarter { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } } - - sendNewTaskResultRequestIfNeeded(); } private void computeSourceStack() { From 92a5ff054a98053a4ccca382cd7f0c7ba6399162 Mon Sep 17 00:00:00 2001 From: Ned Burns Date: Tue, 7 Jan 2020 20:34:23 -0500 Subject: [PATCH 083/182] Don't crash if NSSL gets incomplete gesture In *theory*, a View should always receive an ACTION_DOWN before receiving any other touch events, but this isn't always the case in practice. Whenever we see one of these "partial" gestures, we should ignore it until a real one starts. Test: manual Bug: 146323887 Change-Id: Ic75e4873993f0a8ec3e7210fc173d1fb0bd7b71f (cherry picked from commit d80ded29fbe1e876748ccc66579a5e82c921be65) --- .../stack/NotificationStackScrollLayout.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 1bd9bbecc26e1..3d41ef0adcce8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -3841,9 +3841,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); - final int action = ev.getAction(); + final int action = ev.getActionMasked(); - switch (action & MotionEvent.ACTION_MASK) { + if (ev.findPointerIndex(mActivePointerId) == -1 && action != MotionEvent.ACTION_DOWN) { + // Incomplete gesture, possibly due to window swap mid-gesture. Ignore until a new + // one starts. + Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent " + + MotionEvent.actionToString(ev.getActionMasked())); + return true; + } + + switch (action) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0 || !isInContentBounds(ev)) { return false; @@ -3866,10 +3874,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } case MotionEvent.ACTION_MOVE: final int activePointerIndex = ev.findPointerIndex(mActivePointerId); - if (activePointerIndex == -1) { - Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent"); - break; - } final int y = (int) ev.getY(activePointerIndex); final int x = (int) ev.getX(activePointerIndex); From 2102af060062833b151b4b01f975350b8a7a3a49 Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Sat, 22 Feb 2020 00:12:50 +0000 Subject: [PATCH 084/182] Revert "Avoid creating new instance on top when started for resu..." Revert "Add tests for start singleTop/singleInstance activity fo..." Revert submission 10112771-single-for-result Reason for revert: b/149877125 Reverted Changes: I923a0d9aa:Avoid creating new instance on top when started fo... I7d47580f8:Add tests for start singleTop/singleInstance activ... Change-Id: Ice262d1b8cada3b6c6fe0a5e8000bb59e0536596 (cherry picked from commit e0012bda2adf8f00c6f159a5210b43c0bc692272) It appears that the original reverts missed the master cutover to rvc-dev for rvc-release builds. b/150138994 tracks this issue Bug: 149877125 Bug: 150138994 (cherry picked from commit de8fadecbb520c6b2a9fb8faa9bd4de7e2dea9c4) Change-Id: I1336fb5040e7d9ddc4f49dc8ff4bca62ca9922eb --- .../core/java/com/android/server/wm/ActivityStarter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 600a125cdf43a..8878dee6b47ba 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1813,12 +1813,12 @@ class ActivityStarter { */ private int deliverToCurrentTopIfNeeded(ActivityStack topStack) { final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); - final boolean dontStart = top != null + final boolean dontStart = top != null && mStartActivity.resultTo == null && top.mActivityComponent.equals(mStartActivity.mActivityComponent) && top.mUserId == mStartActivity.mUserId && top.attachedToProcess() && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 - || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) + || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) // This allows home activity to automatically launch on secondary display when // display added, if home was the top activity on default display, instead of // sending new intent to the home activity on default display. @@ -2049,6 +2049,8 @@ class ActivityStarter { && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE) && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0; + sendNewTaskResultRequestIfNeeded(); + if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } @@ -2230,8 +2232,6 @@ class ActivityStarter { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } } - - sendNewTaskResultRequestIfNeeded(); } private void computeSourceStack() { From d160de80b6ccdfd08625a37a4567cf6ac41b8faa Mon Sep 17 00:00:00 2001 From: Tarandeep Singh Date: Mon, 24 Feb 2020 18:35:43 -0800 Subject: [PATCH 085/182] DO NOT MERGE: Fix FLAG_NOT_FOCUSABLE ime target Windows with FLAG_NOT_FOCUSABLE can not be IME target unless alpha is zero (i.e. app is using transparent window to detect IME for legacy reasons). Going forward we can improve this with the todo already mentioned in the code block. Bug: 145812508 Fix: 149899590 Test: Manually verified using steps in bug. Change-Id: I0e7db484dd4f9b584998b9f922fd46030fb6fb72 (cherry picked from commit f3a2b52e16a6a4e91ade996a713cbb1d2b51172b) (cherry picked from commit b17e22cd7676c0cb820bd91969e492044e1822f4) --- services/core/java/com/android/server/wm/WindowState.java | 6 +++--- .../wmtests/src/com/android/server/wm/WindowStateTests.java | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b25008373a7bd..8613e2887f712 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2275,9 +2275,9 @@ class WindowState extends WindowContainer implements WindowManagerP return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format)) { - // Support legacy use cases where transparent windows can still be ime target with - // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { + // Support legacy use cases where completely transparent windows can still be ime target + // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 2c68cc7a19bfd..b35d38bf17e5b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,9 +251,11 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; + appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; + appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; From e18d331d7079c78c9ce0409da211b2e315d5aca6 Mon Sep 17 00:00:00 2001 From: Ned Burns Date: Tue, 7 Jan 2020 20:34:23 -0500 Subject: [PATCH 086/182] Don't crash if NSSL gets incomplete gesture In *theory*, a View should always receive an ACTION_DOWN before receiving any other touch events, but this isn't always the case in practice. Whenever we see one of these "partial" gestures, we should ignore it until a real one starts. Test: manual Bug: 146323887 Change-Id: Ic75e4873993f0a8ec3e7210fc173d1fb0bd7b71f (cherry picked from commit d80ded29fbe1e876748ccc66579a5e82c921be65) --- .../stack/NotificationStackScrollLayout.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 1bd9bbecc26e1..3d41ef0adcce8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -3841,9 +3841,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); - final int action = ev.getAction(); + final int action = ev.getActionMasked(); - switch (action & MotionEvent.ACTION_MASK) { + if (ev.findPointerIndex(mActivePointerId) == -1 && action != MotionEvent.ACTION_DOWN) { + // Incomplete gesture, possibly due to window swap mid-gesture. Ignore until a new + // one starts. + Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent " + + MotionEvent.actionToString(ev.getActionMasked())); + return true; + } + + switch (action) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0 || !isInContentBounds(ev)) { return false; @@ -3866,10 +3874,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } case MotionEvent.ACTION_MOVE: final int activePointerIndex = ev.findPointerIndex(mActivePointerId); - if (activePointerIndex == -1) { - Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent"); - break; - } final int y = (int) ev.getY(activePointerIndex); final int x = (int) ev.getX(activePointerIndex); From 27571ce202fa6286a2527302eb09ebe5b31a540a Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Sat, 22 Feb 2020 00:12:50 +0000 Subject: [PATCH 087/182] Revert "Avoid creating new instance on top when started for resu..." Revert "Add tests for start singleTop/singleInstance activity fo..." Revert submission 10112771-single-for-result Reason for revert: b/149877125 Reverted Changes: I923a0d9aa:Avoid creating new instance on top when started fo... I7d47580f8:Add tests for start singleTop/singleInstance activ... Change-Id: Ice262d1b8cada3b6c6fe0a5e8000bb59e0536596 (cherry picked from commit e0012bda2adf8f00c6f159a5210b43c0bc692272) It appears that the original reverts missed the master cutover to rvc-dev for rvc-release builds. b/150138994 tracks this issue Bug: 149877125 Bug: 150138994 (cherry picked from commit de8fadecbb520c6b2a9fb8faa9bd4de7e2dea9c4) Change-Id: Ia2c5fd7da63119aac54fc4607fdba2929f8a9d3f --- .../core/java/com/android/server/wm/ActivityStarter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index f52c7f29ac8a0..32103048469f5 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1819,12 +1819,12 @@ class ActivityStarter { */ private int deliverToCurrentTopIfNeeded(ActivityStack topStack) { final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); - final boolean dontStart = top != null + final boolean dontStart = top != null && mStartActivity.resultTo == null && top.mActivityComponent.equals(mStartActivity.mActivityComponent) && top.mUserId == mStartActivity.mUserId && top.attachedToProcess() && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 - || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) + || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) // This allows home activity to automatically launch on secondary display when // display added, if home was the top activity on default display, instead of // sending new intent to the home activity on default display. @@ -2055,6 +2055,8 @@ class ActivityStarter { && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE) && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0; + sendNewTaskResultRequestIfNeeded(); + if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } @@ -2236,8 +2238,6 @@ class ActivityStarter { mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } } - - sendNewTaskResultRequestIfNeeded(); } private void computeSourceStack() { From 458fde54a158fbc88fdc67782479f6a66b9888bc Mon Sep 17 00:00:00 2001 From: Tarandeep Singh Date: Mon, 24 Feb 2020 18:35:43 -0800 Subject: [PATCH 088/182] DO NOT MERGE: Fix FLAG_NOT_FOCUSABLE ime target Windows with FLAG_NOT_FOCUSABLE can not be IME target unless alpha is zero (i.e. app is using transparent window to detect IME for legacy reasons). Going forward we can improve this with the todo already mentioned in the code block. Bug: 145812508 Fix: 149899590 Test: Manually verified using steps in bug. Change-Id: I0e7db484dd4f9b584998b9f922fd46030fb6fb72 (cherry picked from commit f3a2b52e16a6a4e91ade996a713cbb1d2b51172b) (cherry picked from commit b17e22cd7676c0cb820bd91969e492044e1822f4) --- services/core/java/com/android/server/wm/WindowState.java | 6 +++--- .../wmtests/src/com/android/server/wm/WindowStateTests.java | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 37597fbc7c457..bc8c2c951e6ac 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2256,9 +2256,9 @@ class WindowState extends WindowContainer implements WindowManagerP return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format)) { - // Support legacy use cases where transparent windows can still be ime target with - // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { + // Support legacy use cases where completely transparent windows can still be ime target + // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 2c68cc7a19bfd..b35d38bf17e5b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,9 +251,11 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; + appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; + appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; From 7964d61e4aadd4fd50c61fe2ad2fce35c652237d Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Wed, 26 Feb 2020 12:11:53 -0800 Subject: [PATCH 089/182] Ensures display rotation triggers PiP re-position Fixed in this CL, upon rotation change - Updates display bounds in PipTaskOrganizer - Issues PiP offset from PipTouchHandler (-> PipMotionHelper) Bug: 150300422 Bug: 150275283 Test: manually rotating screen Change-Id: I4262df6ddc306732693150f27ca0da6e294df5ab (cherry picked from commit bede2c10498cae5a810f4185c10b19c39e8ae669) --- .../src/com/android/systemui/pip/phone/PipManager.java | 5 ++++- .../src/com/android/systemui/pip/phone/PipMotionHelper.java | 4 +--- .../src/com/android/systemui/pip/phone/PipTouchHandler.java | 6 +++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index e98dec0835bfd..767064deec63f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -339,7 +339,10 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio private void updateMovementBounds(Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment) { - // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler first. + mPipTaskOrganizer.onDisplayInfoChanged(mTmpDisplayInfo); + // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler before + // passing to mTouchHandler, mTouchHandler would rely on the bounds calculated by + // mPipBoundsHandler with up-to-dated information mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, animatingBounds, mTmpDisplayInfo); mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index 91f539c3a13d9..980d18b6a7e0f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -411,11 +411,9 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call } private void adjustAndAnimatePipOffset(Rect originalBounds, int offset, int duration) { - if (offset == 0) { - return; - } SomeArgs args = SomeArgs.obtain(); args.arg1 = originalBounds; + // offset would be zero if triggered from screen rotation. args.argi1 = offset; args.argi2 = duration; mHandler.sendMessage(mHandler.obtainMessage(MSG_OFFSET_ANIMATE, args)); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 3b855db6e3280..57b90c0288494 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -266,6 +266,10 @@ public class PipTouchHandler { public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect curBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) { final int bottomOffset = mIsImeShowing ? mImeHeight : 0; + final boolean fromDisplayRotationChanged = (mDisplayRotation != displayRotation); + if (fromDisplayRotationChanged) { + mTouchState.reset(); + } // Re-calculate the expanded bounds mNormalBounds = normalBounds; @@ -293,7 +297,7 @@ public class PipTouchHandler { // If this is from an IME or shelf adjustment, then we should move the PiP so that it is not // occluded by the IME or shelf. - if (fromImeAdjustment || fromShelfAdjustment) { + if (fromImeAdjustment || fromShelfAdjustment || fromDisplayRotationChanged) { if (mTouchState.isUserInteracting()) { // Defer the update of the current movement bounds until after the user finishes // touching the screen From 113e98e2450c35dcebd4df9b0250ca1cf2e87f60 Mon Sep 17 00:00:00 2001 From: Winson Date: Wed, 26 Feb 2020 14:57:20 -0800 Subject: [PATCH 090/182] Initialize PackageManagerService ApplicationInfo instances to system user The data directory for components using AppInfo objects created during PackageSetting commit is not specific per-user, so the ApplicationInfo object must be initialized in PMS, as callers don't expect to do so themselves. Bug: 150109595 Change-Id: If0b8af43ca449700bb192a272b4e64b0ec92b7f8 (cherry picked from commit ac3db53dca4ce0d2da57efcb80b72971a616ebb2) --- .../server/pm/PackageManagerService.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f714af03336f7..74cb93d7a101d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -11780,14 +11780,22 @@ public class PackageManagerService extends IPackageManager.Stub final String pkgName = pkg.getPackageName(); if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.getPackageName())) { - setUpCustomResolverActivity(pkg); + setUpCustomResolverActivity(pkg, pkgSetting); } if (pkg.getPackageName().equals("android")) { synchronized (mLock) { // Set up information for our fall-back user intent resolution activity. mPlatformPackage = pkg; + + // The instance stored in PackageManagerService is special cased to be non-user + // specific, so initialize all the needed fields here. mAndroidApplication = pkg.toAppInfoWithoutState(); + mAndroidApplication.flags = PackageInfoUtils.appInfoFlags(pkg, pkgSetting); + mAndroidApplication.privateFlags = + PackageInfoUtils.appInfoPrivateFlags(pkg, pkgSetting); + mAndroidApplication.initForUser(UserHandle.USER_SYSTEM); + if (!mResolverReplaced) { mResolveActivity.applicationInfo = mAndroidApplication; mResolveActivity.name = ResolverActivity.class.getName(); @@ -11949,11 +11957,20 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } - private void setUpCustomResolverActivity(AndroidPackage pkg) { + private void setUpCustomResolverActivity(AndroidPackage pkg, PackageSetting pkgSetting) { synchronized (mLock) { mResolverReplaced = true; + + // The instance created in PackageManagerService is special cased to be non-user + // specific, so initialize all the needed fields here. + ApplicationInfo appInfo = pkg.toAppInfoWithoutState(); + appInfo.flags = PackageInfoUtils.appInfoFlags(pkg, pkgSetting); + appInfo.privateFlags = + PackageInfoUtils.appInfoPrivateFlags(pkg, pkgSetting); + appInfo.initForUser(UserHandle.USER_SYSTEM); + // Set up information for custom user intent resolution activity. - mResolveActivity.applicationInfo = pkg.toAppInfoWithoutState(); + mResolveActivity.applicationInfo = appInfo; mResolveActivity.name = mCustomResolverComponentName.getClassName(); mResolveActivity.packageName = pkg.getPackageName(); mResolveActivity.processName = pkg.getProcessName(); From 10b6086a4569dc0d47d988c0bf29c8cf81416748 Mon Sep 17 00:00:00 2001 From: Tarandeep Singh Date: Mon, 2 Mar 2020 10:41:14 -0800 Subject: [PATCH 091/182] Ignore unchecked IME show/hide when no root Both showSoftInputUnchecked() and closeCurrenInput() rely on rootView to obtain window token. If view root is null, window has already gone away and IME control had been revoked. Trying to show or hide at this time would be a no-op. Bug: 149900693 Test: Manually using the steps mentioned in bug and verify that there is no NPE. Change-Id: I294bb2ec5395d7502a855bafbac672af069e9b4a (cherry picked from commit ba9b716a7092f97997fa4c2389d393e605d1c8ab) --- .../view/inputmethod/InputMethodManager.java | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index aca265b1f59a8..482d5b25e9da1 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -1634,14 +1634,20 @@ public final class InputMethodManager { @Deprecated @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499) public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) { - try { - Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed " - + "soon. If you are using android.support.v7.widget.SearchView, please update " - + "to version 26.0 or newer version."); - mService.showSoftInput( - mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + synchronized (mH) { + try { + Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be" + + " removed soon. If you are using android.support.v7.widget.SearchView," + + " please update to version 26.0 or newer version."); + if (mCurRootView == null || mCurRootView.getView() == null) { + Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()"); + return; + } + mService.showSoftInput( + mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } } @@ -1986,11 +1992,17 @@ public final class InputMethodManager { @UnsupportedAppUsage void closeCurrentInput() { - try { - mService.hideSoftInput( - mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + synchronized (mH) { + if (mCurRootView == null || mCurRootView.getView() == null) { + Log.w(TAG, "No current root view, ignoring closeCurrentInput()"); + return; + } + try { + mService.hideSoftInput( + mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } } From 0b7c682cab98e1e26cae82a0c9986223f229613b Mon Sep 17 00:00:00 2001 From: Amit Mahajan Date: Tue, 3 Mar 2020 19:18:23 +0000 Subject: [PATCH 092/182] Revert "Fix permission check for get/setSmscAddress." This reverts commit 05e97205523d6ca0f941b0707539f9be6e54ba54. Reason for revert: b/150666039 Bug: 150666039 Change-Id: I67a4ffe94e3caabd04a5b9305de3e476867bfbd1 (cherry picked from commit dec964ceb6eba0de5fa999075ddafdcbc0a41392) --- .../internal/telephony/SmsApplication.java | 17 +---------------- .../java/android/telephony/SmsManager.java | 7 +++---- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java index d54c054e2f825..bb6f154335a92 100644 --- a/telephony/common/com/android/internal/telephony/SmsApplication.java +++ b/telephony/common/com/android/internal/telephony/SmsApplication.java @@ -1057,8 +1057,7 @@ public final class SmsApplication { } /** - * Check if a package is default sms app (or equivalent, like bluetooth), and verify that - * packageName belongs to the caller. + * Check if a package is default sms app (or equivalent, like bluetooth) * * @param context context from the calling app * @param packageName the name of the package to be checked @@ -1067,22 +1066,8 @@ public final class SmsApplication { @UnsupportedAppUsage public static boolean isDefaultSmsApplication(Context context, String packageName) { if (packageName == null) { - Log.e(LOG_TAG, "isDefaultSmsApplication: packageName is null"); return false; } - try { - if (Binder.getCallingUid() - == context.getPackageManager().getPackageUid(packageName, 0)) { - Log.e(LOG_TAG, "isDefaultSmsApplication: " + packageName + " calling uid " - + context.getPackageManager().getPackageUid(packageName, 0) - + " does not match calling uid " + Binder.getCallingUid()); - return false; - } - } catch (NameNotFoundException ex) { - Log.e(LOG_TAG, "isDefaultSmsApplication: packageName " + packageName + " not found"); - return false; - } - final String defaultSmsPackage = getDefaultSmsApplicationPackageName(context); if ((defaultSmsPackage != null && defaultSmsPackage.equals(packageName)) || BLUETOOTH_PACKAGE_NAME.equals(packageName)) { diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 87d0c7f9edfc7..8479db64799c7 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -2898,7 +2898,7 @@ public final class SmsManager { getSubscriptionId(), null); } } catch (RemoteException ex) { - throw new RuntimeException(ex); + // ignore it } return smsc; } @@ -2920,8 +2920,7 @@ public final class SmsManager { *

* * @param smsc the SMSC address string. - * @return true for success, false otherwise. Failure can be due to caller not having the - * appropriate permission, or modem returning an error. + * @return true for success, false otherwise. */ @SuppressAutoDoc // for carrier privileges and default SMS application. @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @@ -2933,7 +2932,7 @@ public final class SmsManager { smsc, getSubscriptionId(), null); } } catch (RemoteException ex) { - throw new RuntimeException(ex); + // ignore it } return false; } From fa87d1989da3ab960bf5090f452aab952f6bbf16 Mon Sep 17 00:00:00 2001 From: Jay Aliomer Date: Mon, 2 Mar 2020 15:32:23 -0500 Subject: [PATCH 093/182] Dark theme not working bug When switching dark mode, the dark mode override should only apply when the dark theme is in auto or custom mode. The solution is to set the override to the same value as night mode Test: UiModeManagerTest Fixes: 150567159 Change-Id: Ib10b73e747a53669de0babc9b44d373b47bfc0fb (cherry picked from commit d483f72ee37c7933b3cccf50ad4102fed27f8062) --- core/java/android/provider/Settings.java | 12 ++- .../android/server/UiModeManagerService.java | 86 +++++++++++-------- .../server/UiModeManagerServiceTest.java | 9 ++ 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fa2b0148b4b5b..4216cf387380a 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7836,12 +7836,20 @@ public final class Settings { public static final String UI_NIGHT_MODE = "ui_night_mode"; /** - * The current night mode that has been overrided by the system. Owned + * The current night mode that has been overridden to turn on by the system. Owned * and controlled by UiModeManagerService. Constants are as per * UiModeManager. * @hide */ - public static final String UI_NIGHT_MODE_OVERRIDE = "ui_night_mode_override"; + public static final String UI_NIGHT_MODE_OVERRIDE_ON = "ui_night_mode_override_on"; + + /** + * The current night mode that has been overridden to turn off by the system. Owned + * and controlled by UiModeManagerService. Constants are as per + * UiModeManager. + * @hide + */ + public static final String UI_NIGHT_MODE_OVERRIDE_OFF = "ui_night_mode_override_off"; /** * Whether screensavers are enabled. diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index f619d6927fdb9..88b517c597c48 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -97,17 +97,11 @@ final class UiModeManagerService extends SystemService { private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; private int mNightMode = UiModeManager.MODE_NIGHT_NO; - // we use the override auto mode - // for example: force night mode off in the night time - // while in auto mode - private int mNightModeOverride = mNightMode; private final LocalTime DEFAULT_CUSTOM_NIGHT_START_TIME = LocalTime.of(22, 0); private final LocalTime DEFAULT_CUSTOM_NIGHT_END_TIME = LocalTime.of(6, 0); private LocalTime mCustomAutoNightModeStartMilliseconds = DEFAULT_CUSTOM_NIGHT_START_TIME; private LocalTime mCustomAutoNightModeEndMilliseconds = DEFAULT_CUSTOM_NIGHT_END_TIME; - protected static final String OVERRIDE_NIGHT_MODE = Secure.UI_NIGHT_MODE_OVERRIDE; - private Map mCarModePackagePriority = new HashMap<>(); private boolean mCarModeEnabled = false; private boolean mCharging = false; @@ -150,6 +144,12 @@ final class UiModeManagerService extends SystemService { private AlarmManager mAlarmManager; private PowerManager mPowerManager; + // In automatic scheduling, the user is able + // to override the computed night mode until the two match + // Example: Activate dark mode in the day time until sunrise the next day + private boolean mOverrideNightModeOn; + private boolean mOverrideNightModeOff; + private PowerManager.WakeLock mWakeLock; private final LocalService mLocalService = new LocalService(); @@ -291,15 +291,18 @@ final class UiModeManagerService extends SystemService { private final ContentObserver mSetupWizardObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri) { - // setup wizard is done now so we can unblock - if (setupWizardCompleteForCurrentUser()) { - mSetupWizardComplete = true; - getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver); - // update night mode - Context context = getContext(); - updateNightModeFromSettings(context, context.getResources(), - UserHandle.getCallingUserId()); - updateLocked(0, 0); + synchronized (mLock) { + // setup wizard is done now so we can unblock + if (setupWizardCompleteForCurrentUser()) { + mSetupWizardComplete = true; + getContext().getContentResolver() + .unregisterContentObserver(mSetupWizardObserver); + // update night mode + Context context = getContext(); + updateNightModeFromSettingsLocked(context, context.getResources(), + UserHandle.getCallingUserId()); + updateLocked(0, 0); + } } } }; @@ -371,11 +374,10 @@ final class UiModeManagerService extends SystemService { mCar = pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH); - updateNightModeFromSettings(context, res, UserHandle.getCallingUserId()); - // Update the initial, static configurations. SystemServerInitThreadPool.submit(() -> { synchronized (mLock) { + updateNightModeFromSettingsLocked(context, res, UserHandle.getCallingUserId()); updateConfigurationLocked(); applyConfigurationExternallyLocked(); } @@ -457,15 +459,17 @@ final class UiModeManagerService extends SystemService { * @param userId The user to update the setting for * @return True if the new value is different from the old value. False otherwise. */ - private boolean updateNightModeFromSettings(Context context, Resources res, int userId) { + private boolean updateNightModeFromSettingsLocked(Context context, Resources res, int userId) { final int defaultNightMode = res.getInteger( com.android.internal.R.integer.config_defaultNightMode); int oldNightMode = mNightMode; if (mSetupWizardComplete) { mNightMode = Secure.getIntForUser(context.getContentResolver(), Secure.UI_NIGHT_MODE, defaultNightMode, userId); - mNightModeOverride = Secure.getIntForUser(context.getContentResolver(), - OVERRIDE_NIGHT_MODE, defaultNightMode, userId); + mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(), + Secure.UI_NIGHT_MODE_OVERRIDE_ON, defaultNightMode, userId) != 0; + mOverrideNightModeOff = Secure.getIntForUser(context.getContentResolver(), + Secure.UI_NIGHT_MODE_OVERRIDE_OFF, defaultNightMode, userId) != 0; mCustomAutoNightModeStartMilliseconds = LocalTime.ofNanoOfDay( Secure.getLongForUser(context.getContentResolver(), Secure.DARK_THEME_CUSTOM_START_TIME, @@ -476,9 +480,10 @@ final class UiModeManagerService extends SystemService { DEFAULT_CUSTOM_NIGHT_END_TIME.toNanoOfDay() / 1000L, userId) * 1000); } else { mNightMode = defaultNightMode; - mNightModeOverride = defaultNightMode; mCustomAutoNightModeEndMilliseconds = DEFAULT_CUSTOM_NIGHT_END_TIME; mCustomAutoNightModeStartMilliseconds = DEFAULT_CUSTOM_NIGHT_START_TIME; + mOverrideNightModeOn = false; + mOverrideNightModeOff = false; } return oldNightMode != mNightMode; @@ -647,7 +652,7 @@ final class UiModeManagerService extends SystemService { } mNightMode = mode; - mNightModeOverride = mode; + resetNightModeOverrideLocked(); // Only persist setting if not in car mode if (!mCarModeEnabled) { persistNightMode(user); @@ -708,8 +713,8 @@ final class UiModeManagerService extends SystemService { try { if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) { unregisterScreenOffEventLocked(); - mNightModeOverride = active - ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; + mOverrideNightModeOff = !active; + mOverrideNightModeOn = active; } else if (mNightMode == UiModeManager.MODE_NIGHT_NO && active) { mNightMode = UiModeManager.MODE_NIGHT_YES; @@ -800,9 +805,11 @@ final class UiModeManagerService extends SystemService { pw.print(" mDockState="); pw.print(mDockState); pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); - pw.print(" mNightModeOverride="); pw.print(mNightModeOverride); pw.print(" mNightMode="); pw.print(mNightMode); pw.print(" ("); pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") "); + pw.print(" mOverrideOn/Off="); pw.print(mOverrideNightModeOn); + pw.print("/"); pw.print(mOverrideNightModeOff); + pw.print(" mNightModeLocked="); pw.println(mNightModeLocked); pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); @@ -874,7 +881,7 @@ final class UiModeManagerService extends SystemService { // When exiting car mode, restore night mode from settings if (!isCarModeNowEnabled) { Context context = getContext(); - updateNightModeFromSettings(context, + updateNightModeFromSettingsLocked(context, context.getResources(), UserHandle.getCallingUserId()); } @@ -1000,7 +1007,9 @@ final class UiModeManagerService extends SystemService { Secure.putIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mNightMode, user); Secure.putIntForUser(getContext().getContentResolver(), - OVERRIDE_NIGHT_MODE, mNightModeOverride, user); + Secure.UI_NIGHT_MODE_OVERRIDE_ON, mOverrideNightModeOn ? 1 : 0, user); + Secure.putIntForUser(getContext().getContentResolver(), + Secure.UI_NIGHT_MODE_OVERRIDE_OFF, mOverrideNightModeOff ? 1 : 0, user); Secure.putLongForUser(getContext().getContentResolver(), Secure.DARK_THEME_CUSTOM_START_TIME, mCustomAutoNightModeStartMilliseconds.toNanoOfDay() / 1000, user); @@ -1130,6 +1139,7 @@ final class UiModeManagerService extends SystemService { void updateLocked(int enableFlags, int disableFlags) { String action = null; String oldAction = null; + boolean originalComputedNightMode = mComputedNightMode; if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) { adjustStatusBarCarModeLocked(); oldAction = UiModeManager.ACTION_EXIT_CAR_MODE; @@ -1210,6 +1220,11 @@ final class UiModeManagerService extends SystemService { sendConfigurationAndStartDreamOrDockAppLocked(category); } + // reset overrides if mComputedNightMode changes + if (originalComputedNightMode != mComputedNightMode) { + resetNightModeOverrideLocked(); + } + // keep screen on when charging and in car mode boolean keepScreenOn = mCharging && ((mCarModeEnabled && mCarModeKeepsScreenOn && @@ -1360,19 +1375,22 @@ final class UiModeManagerService extends SystemService { private void updateComputedNightModeLocked(boolean activate) { mComputedNightMode = activate; - if (mNightModeOverride == UiModeManager.MODE_NIGHT_YES && !mComputedNightMode) { + if (mOverrideNightModeOn && !mComputedNightMode) { mComputedNightMode = true; return; } - if (mNightModeOverride == UiModeManager.MODE_NIGHT_NO && mComputedNightMode) { + if (mOverrideNightModeOff && mComputedNightMode) { mComputedNightMode = false; return; } + } - mNightModeOverride = mNightMode; - final int user = UserHandle.getCallingUserId(); - Secure.putIntForUser(getContext().getContentResolver(), - OVERRIDE_NIGHT_MODE, mNightModeOverride, user); + private void resetNightModeOverrideLocked() { + if (mOverrideNightModeOff || mOverrideNightModeOn) { + mOverrideNightModeOff = false; + mOverrideNightModeOn = false; + persistNightMode(UserHandle.getCallingUserId()); + } } private void registerVrStateListener() { @@ -1515,7 +1533,7 @@ final class UiModeManagerService extends SystemService { final int currentId = intent.getIntExtra( Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM); // only update if the value is actually changed - if (updateNightModeFromSettings(context, context.getResources(), currentId)) { + if (updateNightModeFromSettingsLocked(context, context.getResources(), currentId)) { updateLocked(0, 0); } } diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java index 6a707eb361603..93ca34ad1a45e 100644 --- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java @@ -166,6 +166,15 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { verify(mContext, atLeastOnce()).unregisterReceiver(any(BroadcastReceiver.class)); } + @Test + public void setNightModeActivated_fromNoToYesAndBAck() throws RemoteException { + mService.setNightMode(MODE_NIGHT_NO); + mService.setNightModeActivated(true); + assertTrue(isNightModeActivated()); + mService.setNightModeActivated(false); + assertFalse(isNightModeActivated()); + } + @Test public void autoNightModeSwitch_batterySaverOn() throws RemoteException { mService.setNightMode(MODE_NIGHT_NO); From e6068144bb1db933fb5f519100143f2ec55d39ac Mon Sep 17 00:00:00 2001 From: Jay Aliomer Date: Mon, 2 Mar 2020 15:32:23 -0500 Subject: [PATCH 094/182] Dark theme not working bug When switching dark mode, the dark mode override should only apply when the dark theme is in auto or custom mode. The solution is to set the override to the same value as night mode Test: UiModeManagerTest Fixes: 150567159 Change-Id: Ib10b73e747a53669de0babc9b44d373b47bfc0fb (cherry picked from commit d483f72ee37c7933b3cccf50ad4102fed27f8062) --- core/java/android/provider/Settings.java | 12 ++- .../android/server/UiModeManagerService.java | 86 +++++++++++-------- .../server/UiModeManagerServiceTest.java | 9 ++ 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fa2b0148b4b5b..4216cf387380a 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7836,12 +7836,20 @@ public final class Settings { public static final String UI_NIGHT_MODE = "ui_night_mode"; /** - * The current night mode that has been overrided by the system. Owned + * The current night mode that has been overridden to turn on by the system. Owned * and controlled by UiModeManagerService. Constants are as per * UiModeManager. * @hide */ - public static final String UI_NIGHT_MODE_OVERRIDE = "ui_night_mode_override"; + public static final String UI_NIGHT_MODE_OVERRIDE_ON = "ui_night_mode_override_on"; + + /** + * The current night mode that has been overridden to turn off by the system. Owned + * and controlled by UiModeManagerService. Constants are as per + * UiModeManager. + * @hide + */ + public static final String UI_NIGHT_MODE_OVERRIDE_OFF = "ui_night_mode_override_off"; /** * Whether screensavers are enabled. diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index f619d6927fdb9..88b517c597c48 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -97,17 +97,11 @@ final class UiModeManagerService extends SystemService { private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; private int mNightMode = UiModeManager.MODE_NIGHT_NO; - // we use the override auto mode - // for example: force night mode off in the night time - // while in auto mode - private int mNightModeOverride = mNightMode; private final LocalTime DEFAULT_CUSTOM_NIGHT_START_TIME = LocalTime.of(22, 0); private final LocalTime DEFAULT_CUSTOM_NIGHT_END_TIME = LocalTime.of(6, 0); private LocalTime mCustomAutoNightModeStartMilliseconds = DEFAULT_CUSTOM_NIGHT_START_TIME; private LocalTime mCustomAutoNightModeEndMilliseconds = DEFAULT_CUSTOM_NIGHT_END_TIME; - protected static final String OVERRIDE_NIGHT_MODE = Secure.UI_NIGHT_MODE_OVERRIDE; - private Map mCarModePackagePriority = new HashMap<>(); private boolean mCarModeEnabled = false; private boolean mCharging = false; @@ -150,6 +144,12 @@ final class UiModeManagerService extends SystemService { private AlarmManager mAlarmManager; private PowerManager mPowerManager; + // In automatic scheduling, the user is able + // to override the computed night mode until the two match + // Example: Activate dark mode in the day time until sunrise the next day + private boolean mOverrideNightModeOn; + private boolean mOverrideNightModeOff; + private PowerManager.WakeLock mWakeLock; private final LocalService mLocalService = new LocalService(); @@ -291,15 +291,18 @@ final class UiModeManagerService extends SystemService { private final ContentObserver mSetupWizardObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri) { - // setup wizard is done now so we can unblock - if (setupWizardCompleteForCurrentUser()) { - mSetupWizardComplete = true; - getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver); - // update night mode - Context context = getContext(); - updateNightModeFromSettings(context, context.getResources(), - UserHandle.getCallingUserId()); - updateLocked(0, 0); + synchronized (mLock) { + // setup wizard is done now so we can unblock + if (setupWizardCompleteForCurrentUser()) { + mSetupWizardComplete = true; + getContext().getContentResolver() + .unregisterContentObserver(mSetupWizardObserver); + // update night mode + Context context = getContext(); + updateNightModeFromSettingsLocked(context, context.getResources(), + UserHandle.getCallingUserId()); + updateLocked(0, 0); + } } } }; @@ -371,11 +374,10 @@ final class UiModeManagerService extends SystemService { mCar = pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH); - updateNightModeFromSettings(context, res, UserHandle.getCallingUserId()); - // Update the initial, static configurations. SystemServerInitThreadPool.submit(() -> { synchronized (mLock) { + updateNightModeFromSettingsLocked(context, res, UserHandle.getCallingUserId()); updateConfigurationLocked(); applyConfigurationExternallyLocked(); } @@ -457,15 +459,17 @@ final class UiModeManagerService extends SystemService { * @param userId The user to update the setting for * @return True if the new value is different from the old value. False otherwise. */ - private boolean updateNightModeFromSettings(Context context, Resources res, int userId) { + private boolean updateNightModeFromSettingsLocked(Context context, Resources res, int userId) { final int defaultNightMode = res.getInteger( com.android.internal.R.integer.config_defaultNightMode); int oldNightMode = mNightMode; if (mSetupWizardComplete) { mNightMode = Secure.getIntForUser(context.getContentResolver(), Secure.UI_NIGHT_MODE, defaultNightMode, userId); - mNightModeOverride = Secure.getIntForUser(context.getContentResolver(), - OVERRIDE_NIGHT_MODE, defaultNightMode, userId); + mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(), + Secure.UI_NIGHT_MODE_OVERRIDE_ON, defaultNightMode, userId) != 0; + mOverrideNightModeOff = Secure.getIntForUser(context.getContentResolver(), + Secure.UI_NIGHT_MODE_OVERRIDE_OFF, defaultNightMode, userId) != 0; mCustomAutoNightModeStartMilliseconds = LocalTime.ofNanoOfDay( Secure.getLongForUser(context.getContentResolver(), Secure.DARK_THEME_CUSTOM_START_TIME, @@ -476,9 +480,10 @@ final class UiModeManagerService extends SystemService { DEFAULT_CUSTOM_NIGHT_END_TIME.toNanoOfDay() / 1000L, userId) * 1000); } else { mNightMode = defaultNightMode; - mNightModeOverride = defaultNightMode; mCustomAutoNightModeEndMilliseconds = DEFAULT_CUSTOM_NIGHT_END_TIME; mCustomAutoNightModeStartMilliseconds = DEFAULT_CUSTOM_NIGHT_START_TIME; + mOverrideNightModeOn = false; + mOverrideNightModeOff = false; } return oldNightMode != mNightMode; @@ -647,7 +652,7 @@ final class UiModeManagerService extends SystemService { } mNightMode = mode; - mNightModeOverride = mode; + resetNightModeOverrideLocked(); // Only persist setting if not in car mode if (!mCarModeEnabled) { persistNightMode(user); @@ -708,8 +713,8 @@ final class UiModeManagerService extends SystemService { try { if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) { unregisterScreenOffEventLocked(); - mNightModeOverride = active - ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO; + mOverrideNightModeOff = !active; + mOverrideNightModeOn = active; } else if (mNightMode == UiModeManager.MODE_NIGHT_NO && active) { mNightMode = UiModeManager.MODE_NIGHT_YES; @@ -800,9 +805,11 @@ final class UiModeManagerService extends SystemService { pw.print(" mDockState="); pw.print(mDockState); pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); - pw.print(" mNightModeOverride="); pw.print(mNightModeOverride); pw.print(" mNightMode="); pw.print(mNightMode); pw.print(" ("); pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") "); + pw.print(" mOverrideOn/Off="); pw.print(mOverrideNightModeOn); + pw.print("/"); pw.print(mOverrideNightModeOff); + pw.print(" mNightModeLocked="); pw.println(mNightModeLocked); pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); @@ -874,7 +881,7 @@ final class UiModeManagerService extends SystemService { // When exiting car mode, restore night mode from settings if (!isCarModeNowEnabled) { Context context = getContext(); - updateNightModeFromSettings(context, + updateNightModeFromSettingsLocked(context, context.getResources(), UserHandle.getCallingUserId()); } @@ -1000,7 +1007,9 @@ final class UiModeManagerService extends SystemService { Secure.putIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mNightMode, user); Secure.putIntForUser(getContext().getContentResolver(), - OVERRIDE_NIGHT_MODE, mNightModeOverride, user); + Secure.UI_NIGHT_MODE_OVERRIDE_ON, mOverrideNightModeOn ? 1 : 0, user); + Secure.putIntForUser(getContext().getContentResolver(), + Secure.UI_NIGHT_MODE_OVERRIDE_OFF, mOverrideNightModeOff ? 1 : 0, user); Secure.putLongForUser(getContext().getContentResolver(), Secure.DARK_THEME_CUSTOM_START_TIME, mCustomAutoNightModeStartMilliseconds.toNanoOfDay() / 1000, user); @@ -1130,6 +1139,7 @@ final class UiModeManagerService extends SystemService { void updateLocked(int enableFlags, int disableFlags) { String action = null; String oldAction = null; + boolean originalComputedNightMode = mComputedNightMode; if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) { adjustStatusBarCarModeLocked(); oldAction = UiModeManager.ACTION_EXIT_CAR_MODE; @@ -1210,6 +1220,11 @@ final class UiModeManagerService extends SystemService { sendConfigurationAndStartDreamOrDockAppLocked(category); } + // reset overrides if mComputedNightMode changes + if (originalComputedNightMode != mComputedNightMode) { + resetNightModeOverrideLocked(); + } + // keep screen on when charging and in car mode boolean keepScreenOn = mCharging && ((mCarModeEnabled && mCarModeKeepsScreenOn && @@ -1360,19 +1375,22 @@ final class UiModeManagerService extends SystemService { private void updateComputedNightModeLocked(boolean activate) { mComputedNightMode = activate; - if (mNightModeOverride == UiModeManager.MODE_NIGHT_YES && !mComputedNightMode) { + if (mOverrideNightModeOn && !mComputedNightMode) { mComputedNightMode = true; return; } - if (mNightModeOverride == UiModeManager.MODE_NIGHT_NO && mComputedNightMode) { + if (mOverrideNightModeOff && mComputedNightMode) { mComputedNightMode = false; return; } + } - mNightModeOverride = mNightMode; - final int user = UserHandle.getCallingUserId(); - Secure.putIntForUser(getContext().getContentResolver(), - OVERRIDE_NIGHT_MODE, mNightModeOverride, user); + private void resetNightModeOverrideLocked() { + if (mOverrideNightModeOff || mOverrideNightModeOn) { + mOverrideNightModeOff = false; + mOverrideNightModeOn = false; + persistNightMode(UserHandle.getCallingUserId()); + } } private void registerVrStateListener() { @@ -1515,7 +1533,7 @@ final class UiModeManagerService extends SystemService { final int currentId = intent.getIntExtra( Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM); // only update if the value is actually changed - if (updateNightModeFromSettings(context, context.getResources(), currentId)) { + if (updateNightModeFromSettingsLocked(context, context.getResources(), currentId)) { updateLocked(0, 0); } } diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java index 6a707eb361603..93ca34ad1a45e 100644 --- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java @@ -166,6 +166,15 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { verify(mContext, atLeastOnce()).unregisterReceiver(any(BroadcastReceiver.class)); } + @Test + public void setNightModeActivated_fromNoToYesAndBAck() throws RemoteException { + mService.setNightMode(MODE_NIGHT_NO); + mService.setNightModeActivated(true); + assertTrue(isNightModeActivated()); + mService.setNightModeActivated(false); + assertFalse(isNightModeActivated()); + } + @Test public void autoNightModeSwitch_batterySaverOn() throws RemoteException { mService.setNightMode(MODE_NIGHT_NO); From 6f264696e43c55df4a4f221eedad4a4a21b729ad Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Wed, 4 Mar 2020 21:18:27 +0000 Subject: [PATCH 095/182] Revert "Turn on QS media player by default" This reverts commit 679609721c4a7422ac3612dde69c9e2639ea6883. Reason for revert: b/150437753. IM'ed with Beth, going to revert but not merge this CL. Beth is working on a fix with an eta of a day or 2. Ill CP this into a RP1A.200303.002+ builds. Change-Id: Id42659d33bbd5ccc188d977f6af320cc8b3b6478 (cherry picked from commit f1563675e81b0b079b90fa3d7c9628c16aab9359) --- packages/SystemUI/src/com/android/systemui/util/Utils.java | 3 +-- .../row/wrapper/NotificationMediaTemplateViewWrapperTest.java | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java index 5f821187e30ce..cfa2947eb8627 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Utils.java +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -126,10 +126,9 @@ public class Utils { /** * Allow the media player to be shown in the QS area, controlled by 2 flags. - * On by default, but can be disabled by setting to 0 */ public static boolean useQsMediaPlayer(Context context) { - int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 1); + int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0); return flag > 0; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java index 18ea774e56f08..69e4f2205c35e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java @@ -25,7 +25,6 @@ import android.app.Notification; import android.media.MediaMetadata; import android.media.session.MediaSession; import android.media.session.PlaybackState; -import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.View; @@ -67,9 +66,6 @@ public class NotificationMediaTemplateViewWrapperTest extends SysuiTestCase { allowTestableLooperAsMainThread(); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); - - // These tests are for regular media style notifications, not controls in quick settings - Settings.System.putInt(mContext.getContentResolver(), "qs_media_player", 0); } private void makeTestNotification(long duration, boolean allowSeeking) throws Exception { From 3853c649047990acb2e85a56c8908a430bf983a3 Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Wed, 4 Mar 2020 17:42:53 -0800 Subject: [PATCH 096/182] Relax permission checks in sound trigger middleware This is a temporary measure to address a bug preventing Now Playing from working. Bug: 150750187 Test: Manual Change-Id: I55f1224ab7301e5cfaff510705d8c7bf21ecfad3 (cherry picked from commit 194969aa5f107440745ada5370df3ff72cc5386e) --- .../SoundTriggerMiddlewareValidation.java | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java index c45f37dfdbd89..49a2901d4f9f2 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java @@ -249,21 +249,8 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware * @param permission The permission to check. */ void enforcePermission(String permission) { - final int status = PermissionChecker.checkCallingOrSelfPermissionForPreflight(mContext, - permission); - switch (status) { - case PermissionChecker.PERMISSION_GRANTED: - return; - case PermissionChecker.PERMISSION_HARD_DENIED: - throw new SecurityException( - String.format("Caller must have the %s permission.", permission)); - case PermissionChecker.PERMISSION_SOFT_DENIED: - throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED, - String.format("Caller must have the %s permission.", permission)); - default: - throw new InternalServerError( - new RuntimeException("Unexpected perimission check result.")); - } + mContext.enforceCallingOrSelfPermission(permission, + String.format("Caller must have the %s permission.", permission)); } @Override From 6342d34a75d01d635af38cbd1a56da900af7545d Mon Sep 17 00:00:00 2001 From: Beth Thibodeau Date: Thu, 5 Mar 2020 11:43:51 -0500 Subject: [PATCH 097/182] Reset controls when playback state is NONE If a notification is cleared it won't always send an update first and call onSessionDestroyed. NotificationMediaManager already checks if the current media notification is being removed and sends an event, so we can listen for that. This fixes the bug with cast notifications. It can also be tested by playing media, pausing, and then clearing all notifications - the controls will now switch to the resumption state. Also removed the long-press menu in QSMediaPlayer (which was just for testing) since I was refactoring that block anyways. Fixes: 150437753 Fixes: 150742919 Test: manual Change-Id: I0ecada16967a6d21b82dc86d05544cf78027bcd9 (cherry picked from commit 3316d251d322f80a8e24f0b1b2d0747f928ae6de) --- .../android/systemui/qs/QSMediaPlayer.java | 182 +++++++++--------- .../src/com/android/systemui/qs/QSPanel.java | 8 +- .../systemui/qs/QuickQSMediaPlayer.java | 133 +++++++------ .../com/android/systemui/qs/QuickQSPanel.java | 9 +- 4 files changed, 180 insertions(+), 152 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java index 011893d657237..fd63390c71c58 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java @@ -56,15 +56,17 @@ import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.NotificationMediaManager; import java.util.List; /** * Single media player for carousel in QSPanel */ -public class QSMediaPlayer { +public class QSMediaPlayer implements NotificationMediaManager.MediaListener { private static final String TAG = "QSMediaPlayer"; + private final NotificationMediaManager mMediaManager; private Context mContext; private LinearLayout mMediaNotifView; @@ -76,78 +78,30 @@ public class QSMediaPlayer { private ComponentName mRecvComponent; private QSPanel mParent; + // Button IDs for QS controls + private static final int[] QS_ACTION_IDS = { + R.id.action0, + R.id.action1, + R.id.action2, + R.id.action3, + R.id.action4 + }; + + // Button IDs used in notifications + private static final int[] NOTIF_ACTION_IDS = { + com.android.internal.R.id.action0, + com.android.internal.R.id.action1, + com.android.internal.R.id.action2, + com.android.internal.R.id.action3, + com.android.internal.R.id.action4 + }; + private MediaController.Callback mSessionCallback = new MediaController.Callback() { @Override public void onSessionDestroyed() { Log.d(TAG, "session destroyed"); mController.unregisterCallback(mSessionCallback); - - // Hide all the old buttons - final int[] actionIds = { - R.id.action0, - R.id.action1, - R.id.action2, - R.id.action3, - R.id.action4 - }; - for (int i = 0; i < actionIds.length; i++) { - ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); - if (thisBtn != null) { - thisBtn.setVisibility(View.GONE); - } - } - - // Add a restart button - ImageButton btn = mMediaNotifView.findViewById(actionIds[0]); - btn.setOnClickListener(v -> { - Log.d(TAG, "Attempting to restart session"); - // Send a media button event to previously found receiver - if (mRecvComponent != null) { - Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); - intent.setComponent(mRecvComponent); - int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; - intent.putExtra( - Intent.EXTRA_KEY_EVENT, - new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); - mContext.sendBroadcast(intent); - } else { - Log.d(TAG, "No receiver to restart"); - // If we don't have a receiver, try relaunching the activity instead - try { - mController.getSessionActivity().send(); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Pending intent was canceled"); - e.printStackTrace(); - } - } - }); - btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play)); - btn.setImageTintList(ColorStateList.valueOf(mForegroundColor)); - btn.setVisibility(View.VISIBLE); - - // Add long-click option to remove the player - ViewGroup mMediaCarousel = (ViewGroup) mMediaNotifView.getParent(); - mMediaNotifView.setOnLongClickListener(v -> { - // Replace player view with delete/cancel view - v.setVisibility(View.GONE); - - View options = LayoutInflater.from(mContext).inflate( - R.layout.qs_media_panel_options, null, false); - ImageButton btnDelete = options.findViewById(R.id.remove); - btnDelete.setOnClickListener(b -> { - mMediaCarousel.removeView(options); - mParent.removeMediaPlayer(QSMediaPlayer.this); - }); - ImageButton btnCancel = options.findViewById(R.id.cancel); - btnCancel.setOnClickListener(b -> { - mMediaCarousel.removeView(options); - v.setVisibility(View.VISIBLE); - }); - - int pos = mMediaCarousel.indexOfChild(v); - mMediaCarousel.addView(options, pos, v.getLayoutParams()); - return true; // consumed click - }); + clearControls(); } }; @@ -156,10 +110,11 @@ public class QSMediaPlayer { * @param context * @param parent */ - public QSMediaPlayer(Context context, ViewGroup parent) { + public QSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager) { mContext = context; LayoutInflater inflater = LayoutInflater.from(mContext); mMediaNotifView = (LinearLayout) inflater.inflate(R.layout.qs_media_panel, parent, false); + mMediaManager = manager; } public View getView() { @@ -232,8 +187,7 @@ public class QSMediaPlayer { // Also close shade mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Pending intent was canceled"); - e.printStackTrace(); + Log.e(TAG, "Pending intent was canceled", e); } }); @@ -266,25 +220,10 @@ public class QSMediaPlayer { // Media controls LinearLayout parentActionsLayout = (LinearLayout) actionsContainer; - final int[] actionIds = { - R.id.action0, - R.id.action1, - R.id.action2, - R.id.action3, - R.id.action4 - }; - final int[] notifActionIds = { - com.android.internal.R.id.action0, - com.android.internal.R.id.action1, - com.android.internal.R.id.action2, - com.android.internal.R.id.action3, - com.android.internal.R.id.action4 - }; - int i = 0; - for (; i < parentActionsLayout.getChildCount() && i < actionIds.length; i++) { - ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); - ImageButton thatBtn = parentActionsLayout.findViewById(notifActionIds[i]); + for (; i < parentActionsLayout.getChildCount() && i < QS_ACTION_IDS.length; i++) { + ImageButton thisBtn = mMediaNotifView.findViewById(QS_ACTION_IDS[i]); + ImageButton thatBtn = parentActionsLayout.findViewById(NOTIF_ACTION_IDS[i]); if (thatBtn == null || thatBtn.getDrawable() == null || thatBtn.getVisibility() != View.VISIBLE) { thisBtn.setVisibility(View.GONE); @@ -301,10 +240,14 @@ public class QSMediaPlayer { } // Hide any unused buttons - for (; i < actionIds.length; i++) { - ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); + for (; i < QS_ACTION_IDS.length; i++) { + ImageButton thisBtn = mMediaNotifView.findViewById(QS_ACTION_IDS[i]); thisBtn.setVisibility(View.GONE); } + + // Ensure is only added once + mMediaManager.removeCallback(this); + mMediaManager.addCallback(this); } public MediaSession.Token getMediaSessionToken() { @@ -413,4 +356,61 @@ public class QSMediaPlayer { deviceName.setText(com.android.internal.R.string.ext_media_seamless_action); } } + + /** + * Put controls into a resumption state + */ + private void clearControls() { + // Hide all the old buttons + final int[] actionIds = { + R.id.action0, + R.id.action1, + R.id.action2, + R.id.action3, + R.id.action4 + }; + + for (int i = 0; i < actionIds.length; i++) { + ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); + if (thisBtn != null) { + thisBtn.setVisibility(View.GONE); + } + } + + // Add a restart button + ImageButton btn = mMediaNotifView.findViewById(actionIds[0]); + btn.setOnClickListener(v -> { + Log.d(TAG, "Attempting to restart session"); + // Send a media button event to previously found receiver + if (mRecvComponent != null) { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); + intent.setComponent(mRecvComponent); + int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; + intent.putExtra( + Intent.EXTRA_KEY_EVENT, + new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); + mContext.sendBroadcast(intent); + } else { + Log.d(TAG, "No receiver to restart"); + // If we don't have a receiver, try relaunching the activity instead + try { + mController.getSessionActivity().send(); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Pending intent was canceled"); + e.printStackTrace(); + } + } + }); + btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play)); + btn.setImageTintList(ColorStateList.valueOf(mForegroundColor)); + btn.setVisibility(View.VISIBLE); + } + + @Override + public void onMetadataOrStateChanged(MediaMetadata metadata, int state) { + if (state == PlaybackState.STATE_NONE) { + clearControls(); + mMediaManager.removeCallback(this); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index d2d90925cbe22..73edb7215c2f4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -60,6 +60,7 @@ import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.settings.BrightnessController; import com.android.systemui.settings.ToggleSliderView; +import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener; import com.android.systemui.tuner.TunerService; @@ -94,6 +95,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne private final LinearLayout mMediaCarousel; private final ArrayList mMediaPlayers = new ArrayList<>(); + private final NotificationMediaManager mNotificationMediaManager; private LocalMediaManager mLocalMediaManager; private MediaDevice mDevice; private boolean mUpdateCarousel = false; @@ -150,12 +152,14 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne AttributeSet attrs, DumpManager dumpManager, BroadcastDispatcher broadcastDispatcher, - QSLogger qsLogger + QSLogger qsLogger, + NotificationMediaManager notificationMediaManager ) { super(context, attrs); mContext = context; mQSLogger = qsLogger; mDumpManager = dumpManager; + mNotificationMediaManager = notificationMediaManager; setOrientation(VERTICAL); @@ -255,7 +259,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne if (player == null) { Log.d(TAG, "creating new player"); - player = new QSMediaPlayer(mContext, this); + player = new QSMediaPlayer(mContext, this, mNotificationMediaManager); if (player.isPlaying()) { mMediaCarousel.addView(player.getView(), 0, lp); // add in front diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java index 9018a375c365a..eee28db90f1db 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java @@ -40,15 +40,17 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.systemui.R; +import com.android.systemui.statusbar.NotificationMediaManager; import java.util.List; /** * QQS mini media player */ -public class QuickQSMediaPlayer { +public class QuickQSMediaPlayer implements NotificationMediaManager.MediaListener { private static final String TAG = "QQSMediaPlayer"; + private final NotificationMediaManager mMediaManager; private Context mContext; private LinearLayout mMediaNotifView; @@ -57,48 +59,24 @@ public class QuickQSMediaPlayer { private int mForegroundColor; private ComponentName mRecvComponent; + // Button IDs for QS controls + private static final int[] QQS_ACTION_IDS = {R.id.action0, R.id.action1, R.id.action2}; + + // Button IDs used in notifications + private static final int[] NOTIF_ACTION_IDS = { + com.android.internal.R.id.action0, + com.android.internal.R.id.action1, + com.android.internal.R.id.action2, + com.android.internal.R.id.action3, + com.android.internal.R.id.action4 + }; + private MediaController.Callback mSessionCallback = new MediaController.Callback() { @Override public void onSessionDestroyed() { Log.d(TAG, "session destroyed"); mController.unregisterCallback(mSessionCallback); - - // Hide all the old buttons - final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2}; - for (int i = 0; i < actionIds.length; i++) { - ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); - if (thisBtn != null) { - thisBtn.setVisibility(View.GONE); - } - } - - // Add a restart button - ImageButton btn = mMediaNotifView.findViewById(actionIds[0]); - btn.setOnClickListener(v -> { - Log.d(TAG, "Attempting to restart session"); - // Send a media button event to previously found receiver - if (mRecvComponent != null) { - Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); - intent.setComponent(mRecvComponent); - int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; - intent.putExtra( - Intent.EXTRA_KEY_EVENT, - new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); - mContext.sendBroadcast(intent); - } else { - Log.d(TAG, "No receiver to restart"); - // If we don't have a receiver, try relaunching the activity instead - try { - mController.getSessionActivity().send(); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Pending intent was canceled"); - e.printStackTrace(); - } - } - }); - btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play)); - btn.setImageTintList(ColorStateList.valueOf(mForegroundColor)); - btn.setVisibility(View.VISIBLE); + clearControls(); } }; @@ -107,10 +85,11 @@ public class QuickQSMediaPlayer { * @param context * @param parent */ - public QuickQSMediaPlayer(Context context, ViewGroup parent) { + public QuickQSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager) { mContext = context; LayoutInflater inflater = LayoutInflater.from(mContext); mMediaNotifView = (LinearLayout) inflater.inflate(R.layout.qqs_media_panel, parent, false); + mMediaManager = manager; } public View getView() { @@ -188,26 +167,14 @@ public class QuickQSMediaPlayer { titleText.setText(songName); titleText.setTextColor(mForegroundColor); - // Buttons we can display - final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2}; - - // Existing buttons in the notification LinearLayout parentActionsLayout = (LinearLayout) actionsContainer; - final int[] notifActionIds = { - com.android.internal.R.id.action0, - com.android.internal.R.id.action1, - com.android.internal.R.id.action2, - com.android.internal.R.id.action3, - com.android.internal.R.id.action4 - }; - int i = 0; if (actionsToShow != null) { int maxButtons = Math.min(actionsToShow.length, parentActionsLayout.getChildCount()); - maxButtons = Math.min(maxButtons, actionIds.length); + maxButtons = Math.min(maxButtons, QQS_ACTION_IDS.length); for (; i < maxButtons; i++) { - ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); - int thatId = notifActionIds[actionsToShow[i]]; + ImageButton thisBtn = mMediaNotifView.findViewById(QQS_ACTION_IDS[i]); + int thatId = NOTIF_ACTION_IDS[actionsToShow[i]]; ImageButton thatBtn = parentActionsLayout.findViewById(thatId); if (thatBtn == null || thatBtn.getDrawable() == null || thatBtn.getVisibility() != View.VISIBLE) { @@ -225,10 +192,14 @@ public class QuickQSMediaPlayer { } // Hide any unused buttons - for (; i < actionIds.length; i++) { - ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); + for (; i < QQS_ACTION_IDS.length; i++) { + ImageButton thisBtn = mMediaNotifView.findViewById(QQS_ACTION_IDS[i]); thisBtn.setVisibility(View.GONE); } + + // Ensure is only added once + mMediaManager.removeCallback(this); + mMediaManager.addCallback(this); } public MediaSession.Token getMediaSessionToken() { @@ -259,4 +230,54 @@ public class QuickQSMediaPlayer { public boolean hasMediaSession() { return mController != null && mController.getPlaybackState() != null; } + + /** + * Put controls into a resumption state + */ + public void clearControls() { + // Hide all the old buttons + final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2}; + for (int i = 0; i < actionIds.length; i++) { + ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]); + if (thisBtn != null) { + thisBtn.setVisibility(View.GONE); + } + } + + // Add a restart button + ImageButton btn = mMediaNotifView.findViewById(actionIds[0]); + btn.setOnClickListener(v -> { + Log.d(TAG, "Attempting to restart session"); + // Send a media button event to previously found receiver + if (mRecvComponent != null) { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); + intent.setComponent(mRecvComponent); + int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY; + intent.putExtra( + Intent.EXTRA_KEY_EVENT, + new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); + mContext.sendBroadcast(intent); + } else { + Log.d(TAG, "No receiver to restart"); + // If we don't have a receiver, try relaunching the activity instead + try { + mController.getSessionActivity().send(); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Pending intent was canceled", e); + } + } + }); + btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play)); + btn.setImageTintList(ColorStateList.valueOf(mForegroundColor)); + btn.setVisibility(View.VISIBLE); + } + + @Override + public void onMetadataOrStateChanged(MediaMetadata metadata, int state) { + if (state == PlaybackState.STATE_NONE) { + Log.d(TAG, "clearing controls because state none"); + clearControls(); + mMediaManager.removeCallback(this); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 20efbcb3cc425..2e1dd8f11d647 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -35,6 +35,7 @@ import com.android.systemui.plugins.qs.QSTile.SignalState; import com.android.systemui.plugins.qs.QSTile.State; import com.android.systemui.qs.customize.QSCustomizer; import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; import com.android.systemui.util.Utils; @@ -72,9 +73,10 @@ public class QuickQSPanel extends QSPanel { AttributeSet attrs, DumpManager dumpManager, BroadcastDispatcher broadcastDispatcher, - QSLogger qsLogger + QSLogger qsLogger, + NotificationMediaManager notificationMediaManager ) { - super(context, attrs, dumpManager, broadcastDispatcher, qsLogger); + super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, notificationMediaManager); if (mFooter != null) { removeView(mFooter.getView()); } @@ -93,7 +95,8 @@ public class QuickQSPanel extends QSPanel { mHorizontalLinearLayout.setClipToPadding(false); int marginSize = (int) mContext.getResources().getDimension(R.dimen.qqs_media_spacing); - mMediaPlayer = new QuickQSMediaPlayer(mContext, mHorizontalLinearLayout); + mMediaPlayer = new QuickQSMediaPlayer(mContext, mHorizontalLinearLayout, + notificationMediaManager); LayoutParams lp2 = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1); lp2.setMarginEnd(marginSize); lp2.setMarginStart(0); From da58015335c85c45dba5e20f082af4b66af2647f Mon Sep 17 00:00:00 2001 From: Jay Aliomer Date: Thu, 5 Mar 2020 12:12:16 -0500 Subject: [PATCH 098/182] Dark theme upgrade broken When upgrading release, night mode overrides evaluate to true for unknown reasons. a check for manual toggle is added in order to not apply overrides Fixes: 150567159 Test: manual since it involves integration Change-Id: I09af78fd16662185d01aea427188f79527d47a9e (cherry picked from commit 1b174b0d31bcc28b73b0afe106a125ac365a7479) --- .../java/com/android/server/UiModeManagerService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 88b517c597c48..7c833faee1bd6 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -467,9 +467,9 @@ final class UiModeManagerService extends SystemService { mNightMode = Secure.getIntForUser(context.getContentResolver(), Secure.UI_NIGHT_MODE, defaultNightMode, userId); mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(), - Secure.UI_NIGHT_MODE_OVERRIDE_ON, defaultNightMode, userId) != 0; + Secure.UI_NIGHT_MODE_OVERRIDE_ON, 0, userId) != 0; mOverrideNightModeOff = Secure.getIntForUser(context.getContentResolver(), - Secure.UI_NIGHT_MODE_OVERRIDE_OFF, defaultNightMode, userId) != 0; + Secure.UI_NIGHT_MODE_OVERRIDE_OFF, 0, userId) != 0; mCustomAutoNightModeStartMilliseconds = LocalTime.ofNanoOfDay( Secure.getLongForUser(context.getContentResolver(), Secure.DARK_THEME_CUSTOM_START_TIME, @@ -1045,7 +1045,6 @@ final class UiModeManagerService extends SystemService { final TwilightState lastState = mTwilightManager.getLastTwilightState(); activateNightMode = lastState == null ? mComputedNightMode : lastState.isNight(); } - updateComputedNightModeLocked(activateNightMode); } else { if (mTwilightManager != null) { @@ -1375,6 +1374,9 @@ final class UiModeManagerService extends SystemService { private void updateComputedNightModeLocked(boolean activate) { mComputedNightMode = activate; + if (mNightMode == MODE_NIGHT_YES || mNightMode == UiModeManager.MODE_NIGHT_NO) { + return; + } if (mOverrideNightModeOn && !mComputedNightMode) { mComputedNightMode = true; return; From c649d9d8ca574885f87e34f277af53567787b3ac Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 5 Mar 2020 14:40:27 -0800 Subject: [PATCH 099/182] Change animation-leash to be a container layer Temporary revert to fix flicker issues. Bug: b/149792636, b/150829791 Test: go/wm-smoke Change-Id: I016dfd937ea844f0687195d1670471dfdcbd8cdd (cherry picked from commit 10a09f5eaff9f7e75879e8be952b1fc80635ce57) --- services/core/java/com/android/server/wm/SurfaceAnimator.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 3b3234a4bec0a..19f8ca912449c 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -379,10 +379,8 @@ class SurfaceAnimator { final SurfaceControl.Builder builder = animatable.makeAnimationLeash() .setParent(animatable.getAnimationLeashParent()) .setHidden(hidden) - .setName(surface + " - animation-leash") - .setColorLayer(); + .setName(surface + " - animation-leash"); final SurfaceControl leash = builder.build(); - t.unsetColor(leash); t.setWindowCrop(leash, width, height); t.setPosition(leash, x, y); t.show(leash); From e36d21c94e2e94bad40db7c22f2cf41ff4af96bc Mon Sep 17 00:00:00 2001 From: Jay Aliomer Date: Thu, 5 Mar 2020 12:12:16 -0500 Subject: [PATCH 100/182] Dark theme upgrade broken When upgrading release, night mode overrides evaluate to true for unknown reasons. a check for manual toggle is added in order to not apply overrides Fixes: 150567159 Test: manual since it involves integration Change-Id: I09af78fd16662185d01aea427188f79527d47a9e (cherry picked from commit 1b174b0d31bcc28b73b0afe106a125ac365a7479) --- .../java/com/android/server/UiModeManagerService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 88b517c597c48..7c833faee1bd6 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -467,9 +467,9 @@ final class UiModeManagerService extends SystemService { mNightMode = Secure.getIntForUser(context.getContentResolver(), Secure.UI_NIGHT_MODE, defaultNightMode, userId); mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(), - Secure.UI_NIGHT_MODE_OVERRIDE_ON, defaultNightMode, userId) != 0; + Secure.UI_NIGHT_MODE_OVERRIDE_ON, 0, userId) != 0; mOverrideNightModeOff = Secure.getIntForUser(context.getContentResolver(), - Secure.UI_NIGHT_MODE_OVERRIDE_OFF, defaultNightMode, userId) != 0; + Secure.UI_NIGHT_MODE_OVERRIDE_OFF, 0, userId) != 0; mCustomAutoNightModeStartMilliseconds = LocalTime.ofNanoOfDay( Secure.getLongForUser(context.getContentResolver(), Secure.DARK_THEME_CUSTOM_START_TIME, @@ -1045,7 +1045,6 @@ final class UiModeManagerService extends SystemService { final TwilightState lastState = mTwilightManager.getLastTwilightState(); activateNightMode = lastState == null ? mComputedNightMode : lastState.isNight(); } - updateComputedNightModeLocked(activateNightMode); } else { if (mTwilightManager != null) { @@ -1375,6 +1374,9 @@ final class UiModeManagerService extends SystemService { private void updateComputedNightModeLocked(boolean activate) { mComputedNightMode = activate; + if (mNightMode == MODE_NIGHT_YES || mNightMode == UiModeManager.MODE_NIGHT_NO) { + return; + } if (mOverrideNightModeOn && !mComputedNightMode) { mComputedNightMode = true; return; From 9b5c2954cb2ec0631634018a4ce22c5287f7b81f Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Wed, 4 Mar 2020 21:18:27 +0000 Subject: [PATCH 101/182] Revert "Turn on QS media player by default" This reverts commit 679609721c4a7422ac3612dde69c9e2639ea6883. Reason for revert: b/150437753. Change-Id: Id42659d33bbd5ccc188d977f6af320cc8b3b6478 (cherry picked from commit 8d5eea4e61597ad66a37588bfa49badeabbd0438) --- packages/SystemUI/src/com/android/systemui/util/Utils.java | 3 +-- .../row/wrapper/NotificationMediaTemplateViewWrapperTest.java | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java index 5f821187e30ce..cfa2947eb8627 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Utils.java +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -126,10 +126,9 @@ public class Utils { /** * Allow the media player to be shown in the QS area, controlled by 2 flags. - * On by default, but can be disabled by setting to 0 */ public static boolean useQsMediaPlayer(Context context) { - int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 1); + int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0); return flag > 0; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java index 18ea774e56f08..69e4f2205c35e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java @@ -25,7 +25,6 @@ import android.app.Notification; import android.media.MediaMetadata; import android.media.session.MediaSession; import android.media.session.PlaybackState; -import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.View; @@ -67,9 +66,6 @@ public class NotificationMediaTemplateViewWrapperTest extends SysuiTestCase { allowTestableLooperAsMainThread(); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); - - // These tests are for regular media style notifications, not controls in quick settings - Settings.System.putInt(mContext.getContentResolver(), "qs_media_player", 0); } private void makeTestNotification(long duration, boolean allowSeeking) throws Exception { From 52f7859a9eb5cf6f9455bcc74bd12aa980aba59d Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 6 Mar 2020 13:35:55 -0700 Subject: [PATCH 102/182] Adjust users of hidden APIs. There's a new method overload that gives them both the "int flags" and "int userId". Bug: 150939131 Test: atest CtsDatabaseTestCases Test: atest CtsContentTestCases:android.content.cts.ContentResolverTest Exempt-From-Owner-Approval: trivial refactoring Change-Id: I7dc3fa1e2c4dfb802fd7919e2c8a559b4e46064d (cherry picked from commit 29246e85473ab9f1ebc88d905d57316eead99ec4) --- .../src/com/android/keyguard/clock/ClockManager.java | 5 +++-- .../server/notification/ValidateNotificationPeople.java | 5 +++-- .../devicepolicy/DevicePolicyManagerServiceTestable.java | 5 +++-- .../src/com/android/server/people/data/DataManagerTest.java | 3 ++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index 03674648d1e47..cb43934dea829 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java @@ -74,8 +74,9 @@ public final class ClockManager { private final ContentObserver mContentObserver = new ContentObserver(mMainHandler) { @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - super.onChange(selfChange, uri, userId); + public void onChange(boolean selfChange, Iterable uris, + int flags, int userId) { + super.onChange(selfChange, uris, userId); if (Objects.equals(userId, mCurrentUserObservable.getCurrentUser().getValue())) { reload(); diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index 90fc59a893a65..d36f202ecc001 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -106,8 +106,9 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { mHandler = new Handler(); mObserver = new ContentObserver(mHandler) { @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - super.onChange(selfChange, uri, userId); + public void onChange(boolean selfChange, Iterable uris, + int flags, int userId) { + super.onChange(selfChange, uris, flags, userId); if (DEBUG || mEvictionCount % 100 == 0) { if (VERBOSE) Slog.i(TAG, "mEvictionCount: " + mEvictionCount); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index 5ad81b2c45068..2aeed24867617 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -56,6 +56,7 @@ import com.android.server.net.NetworkPolicyManagerInternal; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Map; /** @@ -108,13 +109,13 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi public void notifyChangeToContentObserver(Uri uri, int userHandle) { ContentObserver co = mMockInjector.mContentObservers.get(new Pair<>(uri, userHandle)); if (co != null) { - co.onChange(false, uri, userHandle); // notify synchronously + co.onChange(false, Arrays.asList(uri), 0, userHandle); // notify synchronously } // Notify USER_ALL observer too. co = mMockInjector.mContentObservers.get(new Pair<>(uri, UserHandle.USER_ALL)); if (co != null) { - co.onChange(false, uri, userHandle); // notify synchronously + co.onChange(false, Arrays.asList(uri), 0, userHandle); // notify synchronously } } diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java index 624b67ccda853..63dbb0f9d79f0 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java @@ -366,7 +366,8 @@ public final class DataManagerTest { ContentObserver contentObserver = mDataManager.getContactsContentObserverForTesting( USER_ID_PRIMARY); - contentObserver.onChange(false, ContactsContract.Contacts.CONTENT_URI, USER_ID_PRIMARY); + contentObserver.onChange(false, Arrays.asList(ContactsContract.Contacts.CONTENT_URI), 0, + USER_ID_PRIMARY); List conversations = getConversationsInPrimary(); assertEquals(1, conversations.size()); From 5a08e3aa5bd10599b8a78b206581803aff605875 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Fri, 6 Mar 2020 18:07:43 -0500 Subject: [PATCH 103/182] Fix instances of ContentObserver#onChange in SystemUI Fix instances due to change in signature. Test: atest SystemUITests Test: atest TileServiceTest BooleanTileServiceTest Bug: 150939131 Change-Id: Ie5903231eb7dd22553803c6a65994ef3dc957708 (cherry picked from commit caf76d25e3b15d72e26671902aa8bbebeb729339) --- .../systemui/car/CarDeviceProvisionedControllerImpl.java | 3 ++- .../controls/controller/ControlsControllerImpl.kt | 9 +++++++-- .../src/com/android/systemui/doze/DozeSensors.java | 2 +- .../notification/people/PeopleHubViewController.kt | 4 ++-- .../policy/DeviceProvisionedControllerImpl.java | 2 +- .../android/systemui/theme/ThemeOverlayController.java | 4 +++- .../src/com/android/systemui/tuner/TunerServiceImpl.java | 7 +++++-- .../controls/controller/ControlsControllerImplTest.kt | 6 +++--- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java index 38d5211bd0d45..09e62d240a72b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java @@ -44,8 +44,9 @@ public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControl CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS); private final ContentObserver mCarSettingsObserver = new ContentObserver( Dependency.get(Dependency.MAIN_HANDLER)) { + @Override - public void onChange(boolean selfChange, Uri uri, int userId) { + public void onChange(boolean selfChange, Uri uri, int flags) { if (USER_SETUP_IN_PROGRESS_URI.equals(uri)) { notifyUserSetupInProgressChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index dedd341a46beb..c58e790727fa8 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -125,14 +125,19 @@ class ControlsControllerImpl @Inject constructor ( @VisibleForTesting internal val settingObserver = object : ContentObserver(null) { - override fun onChange(selfChange: Boolean, uri: Uri, userId: Int) { + override fun onChange( + selfChange: Boolean, + uris: MutableIterable, + flags: Int, + userId: Int + ) { // Do not listen to changes in the middle of user change, those will be read by the // user-switch receiver. if (userChanging || userId != currentUserId) { return } available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, - DEFAULT_ENABLED, currentUserId) != 0 + DEFAULT_ENABLED, currentUserId) != 0 resetFavorites(available) } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 44e5d3de5ca7e..c28a719b9826f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -261,7 +261,7 @@ public class DozeSensors { private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override - public void onChange(boolean selfChange, Uri uri, int userId) { + public void onChange(boolean selfChange, Iterable uris, int flags, int userId) { if (userId != ActivityManager.getCurrentUser()) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt index 62d3612a483b1..7f42fe0473f3c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt @@ -164,8 +164,8 @@ class PeopleHubSettingChangeDataSourceImpl @Inject constructor( // Immediately report current value of setting updateListener(listener) val observer = object : ContentObserver(handler) { - override fun onChange(selfChange: Boolean, uri: Uri?, userId: Int) { - super.onChange(selfChange, uri, userId) + override fun onChange(selfChange: Boolean, uri: Uri?, flags: Int) { + super.onChange(selfChange, uri, flags) updateListener(listener) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java index a3e2e7619bac7..7280a881655c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java @@ -59,7 +59,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen mUserSetupUri = Secure.getUriFor(Secure.USER_SETUP_COMPLETE); mSettingsObserver = new ContentObserver(mainHandler) { @Override - public void onChange(boolean selfChange, Uri uri, int userId) { + public void onChange(boolean selfChange, Uri uri, int flags) { Log.d(TAG, "Setting change: " + uri); if (mUserSetupUri.equals(uri)) { notifySetupChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index 31b9952afe941..30db37c4f128a 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -99,8 +99,10 @@ public class ThemeOverlayController extends SystemUI { Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), false, new ContentObserver(mBgHandler) { + @Override - public void onChange(boolean selfChange, Uri uri, int userId) { + public void onChange(boolean selfChange, Iterable uris, int flags, + int userId) { if (DEBUG) Log.d(TAG, "Overlay changed for user: " + userId); if (ActivityManager.getCurrentUser() == userId) { updateThemeOverlays(); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java index 142fdc21aff1a..b2a5f5bee5434 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java @@ -262,10 +262,13 @@ public class TunerServiceImpl extends TunerService { } @Override - public void onChange(boolean selfChange, Uri uri, int userId) { + public void onChange(boolean selfChange, Iterable uris, int flags, int userId) { if (userId == ActivityManager.getCurrentUser()) { - reloadSetting(uri); + for (Uri u : uris) { + reloadSetting(u); + } } } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt index 45ea3c96b8195..183dde87bdf78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt @@ -408,7 +408,7 @@ class ControlsControllerImplTest : SysuiTestCase() { fun testDisableFeature_notAvailable() { Settings.Secure.putIntForUser(mContext.contentResolver, ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user) - controller.settingObserver.onChange(false, ControlsControllerImpl.URI, 0) + controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, 0) assertFalse(controller.available) } @@ -421,7 +421,7 @@ class ControlsControllerImplTest : SysuiTestCase() { Settings.Secure.putIntForUser(mContext.contentResolver, ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user) - controller.settingObserver.onChange(false, ControlsControllerImpl.URI, user) + controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, user) assertTrue(controller.getFavorites().isEmpty()) } @@ -432,7 +432,7 @@ class ControlsControllerImplTest : SysuiTestCase() { Settings.Secure.putIntForUser(mContext.contentResolver, ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser) - controller.settingObserver.onChange(false, ControlsControllerImpl.URI, otherUser) + controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, otherUser) assertTrue(controller.available) assertFalse(controller.getFavorites().isEmpty()) From 0eeb8686fa3e3097cc60ab50b61ca58c74e54203 Mon Sep 17 00:00:00 2001 From: Rob Carr Date: Mon, 9 Mar 2020 11:22:30 -0700 Subject: [PATCH 104/182] InsetController: Release leashes from RenderThread We handle changes to the leashes from the UI thread, but use the same SurfaceControl wrapper object from the RenderThread with SyncRtSurfaceTransactionApplier. This means that at the time we release a SurfaceControl from the UI thread we might have already scheduled a SyncRtSurfaceTransactionApplier to use it, and actually that could be in the process of running, leading to racy access and crashes. To fix this we release the SurfaceControl from the RenderThread so that it happens behind all existing operations. Bug: 151086678 Test: Existing tests pass. Change-Id: I2308d1c64f3f368c32587f99ddfb9e05955f821f (cherry picked from commit 521e363a0ff5b90bec8f1fb6d5e10156af713a76) --- core/java/android/view/InsetsController.java | 19 +++++++++++++++++++ .../android/view/InsetsSourceConsumer.java | 2 +- .../android/view/InsetsSourceControl.java | 4 ++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 573d8fc65c84f..f52960c5c3e06 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -992,4 +992,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } return mViewRoot.mWindowAttributes.insetsFlags.behavior; } + + /** + * At the time we receive new leashes (e.g. InsetsSourceConsumer is processing + * setControl) we need to release the old leash. But we may have already scheduled + * a SyncRtSurfaceTransaction applier to use it from the RenderThread. To avoid + * synchronization issues we also release from the RenderThread so this release + * happens after any existing items on the work queue. + */ + public void releaseSurfaceControlFromRt(SurfaceControl sc) { + if (mViewRoot.mView != null && mViewRoot.mView.isHardwareAccelerated()) { + mViewRoot.registerRtFrameCallback(frame -> { + sc.release(); + }); + // Make sure a frame gets scheduled. + mViewRoot.mView.invalidate(); + } else { + sc.release(); + } + } } diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index f07f1ce186fea..252fc0c82cf77 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -117,7 +117,7 @@ public class InsetsSourceConsumer { } } if (lastControl != null) { - lastControl.release(); + lastControl.release(mController); } } diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java index 29ba56a5fbb9d..75f6eab798ce4 100644 --- a/core/java/android/view/InsetsSourceControl.java +++ b/core/java/android/view/InsetsSourceControl.java @@ -94,9 +94,9 @@ public class InsetsSourceControl implements Parcelable { dest.writeParcelable(mSurfacePosition, 0 /* flags*/); } - public void release() { + public void release(InsetsController controller) { if (mLeash != null) { - mLeash.release(); + controller.releaseSurfaceControlFromRt(mLeash); } } From ee23855dd8bbc723b7bba8597d2160195a9d5b54 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Mon, 9 Mar 2020 21:22:44 +0000 Subject: [PATCH 105/182] Revert "media: lazy MediaCodec.release()" Revert submission 10446783-mediacodec-lazy-release Reason for revert: back-to-back video playback jitters Reverted Changes: I119945684:stagefright: MediaCodec::releaseAsync() Ieb4c0b2e1:media: lazy MediaCodec.release() Bug: 150662913 Change-Id: I9388f90ab7befe8415afa82b6b349318c5bdc2f8 (cherry picked from commit 5b610e26eb1be054aa144c39ae3045d5f2c3d29c) --- media/jni/android_media_MediaCodec.cpp | 14 ++------------ media/jni/android_media_MediaCodec.h | 1 - 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 737c95d73e6c4..893e51654b682 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -242,13 +242,6 @@ void JMediaCodec::release() { }); } -void JMediaCodec::releaseAsync() { - if (mCodec != NULL) { - mCodec->releaseAsync(); - } - mInitStatus = NO_INIT; -} - JMediaCodec::~JMediaCodec() { if (mLooper != NULL) { /* MediaCodec and looper should have been released explicitly already @@ -1131,10 +1124,7 @@ static sp getMediaCodec(JNIEnv *env, jobject thiz) { } static void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) { - sp codec = getMediaCodec(env, thiz); - if (codec != NULL) { - codec->releaseAsync(); - } + setMediaCodec(env, thiz, NULL); } static void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) { @@ -2807,7 +2797,7 @@ static void android_media_MediaCodec_native_setup( static void android_media_MediaCodec_native_finalize( JNIEnv *env, jobject thiz) { - setMediaCodec(env, thiz, NULL); + android_media_MediaCodec_release(env, thiz); } // MediaCodec.LinearBlock diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 400ce1bc98e76..8899fee7a73d2 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -61,7 +61,6 @@ struct JMediaCodec : public AHandler { void registerSelf(); void release(); - void releaseAsync(); status_t enableOnFrameRenderedListener(jboolean enable); From 2bc7801cb4950b524bbc5f3f8b07061e4b9cb566 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Fri, 6 Mar 2020 19:35:48 -0800 Subject: [PATCH 106/182] Some clean-up of divider code in preparation for bugfixes Made an actual class for the imecontroller in divider to prepare for some more complicated interactions. Also consolidated the minimize/resizability update logic for the same reason. Bug: 150781668 Test: no change. things should work and tests pass Change-Id: I68f1b47e092ed35311cbcd2878e4c271ac161a8c (cherry picked from commit 877739b3c302d041091e301342867db6df190f1e) --- .../systemui/stackdivider/Divider.java | 491 +++++++++--------- .../stackdivider/DividerWindowManager.java | 3 + .../stackdivider/WindowManagerProxy.java | 21 +- 3 files changed, 242 insertions(+), 273 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index c6eecf260dac1..ce45b03585118 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -129,217 +129,213 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } }; - private DisplayImeController.ImePositionProcessor mImePositionProcessor = - new DisplayImeController.ImePositionProcessor() { - /** - * These are the y positions of the top of the IME surface when it is hidden and - * when it is shown respectively. These are NOT necessarily the top of the visible - * IME itself. - */ - private int mHiddenTop = 0; - private int mShownTop = 0; + private class DividerImeController implements DisplayImeController.ImePositionProcessor { + /** + * These are the y positions of the top of the IME surface when it is hidden and when it is + * shown respectively. These are NOT necessarily the top of the visible IME itself. + */ + private int mHiddenTop = 0; + private int mShownTop = 0; - // The following are target states (what we are curretly animating towards). - /** - * {@code true} if, at the end of the animation, the split task positions should be - * adjusted by height of the IME. This happens when the secondary split is the IME - * target. - */ - private boolean mTargetAdjusted = false; - /** - * {@code true} if, at the end of the animation, the IME should be shown/visible - * regardless of what has focus. - */ - private boolean mTargetShown = false; + // The following are target states (what we are curretly animating towards). + /** + * {@code true} if, at the end of the animation, the split task positions should be + * adjusted by height of the IME. This happens when the secondary split is the IME target. + */ + private boolean mTargetAdjusted = false; + /** + * {@code true} if, at the end of the animation, the IME should be shown/visible + * regardless of what has focus. + */ + private boolean mTargetShown = false; - // The following are the current (most recent) states set during animation - /** - * {@code true} if the secondary split has IME focus. - */ - private boolean mSecondaryHasFocus = false; - /** The dimming currently applied to the primary/secondary splits. */ - private float mLastPrimaryDim = 0.f; - private float mLastSecondaryDim = 0.f; - /** The most recent y position of the top of the IME surface */ - private int mLastAdjustTop = -1; + // The following are the current (most recent) states set during animation + /** {@code true} if the secondary split has IME focus. */ + private boolean mSecondaryHasFocus = false; + /** The dimming currently applied to the primary/secondary splits. */ + private float mLastPrimaryDim = 0.f; + private float mLastSecondaryDim = 0.f; + /** The most recent y position of the top of the IME surface */ + private int mLastAdjustTop = -1; - // The following are states reached last time an animation fully completed. - /** {@code true} if the IME was shown/visible by the last-completed animation. */ - private boolean mImeWasShown = false; - /** - * {@code true} if the split positions were adjusted by the last-completed - * animation. - */ - private boolean mAdjusted = false; + // The following are states reached last time an animation fully completed. + /** {@code true} if the IME was shown/visible by the last-completed animation. */ + private boolean mImeWasShown = false; + /** {@code true} if the split positions were adjusted by the last-completed animation. */ + private boolean mAdjusted = false; - /** - * When some aspect of split-screen needs to animate independent from the IME, - * this will be non-null and control split animation. - */ - @Nullable - private ValueAnimator mAnimation = null; + /** + * When some aspect of split-screen needs to animate independent from the IME, + * this will be non-null and control split animation. + */ + @Nullable + private ValueAnimator mAnimation = null; - private boolean getSecondaryHasFocus(int displayId) { - try { - IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() - .getImeTarget(displayId); - return imeSplit != null - && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to get IME target", e); - } - return false; - } + private boolean getSecondaryHasFocus(int displayId) { + try { + IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() + .getImeTarget(displayId); + return imeSplit != null + && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to get IME target", e); + } + return false; + } + @Override + public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, + boolean imeShouldShow, SurfaceControl.Transaction t) { + mSecondaryHasFocus = getSecondaryHasFocus(displayId); + mTargetAdjusted = imeShouldShow && mSecondaryHasFocus + && !mSplitLayout.mDisplayLayout.isLandscape(); + mHiddenTop = hiddenTop; + mShownTop = shownTop; + mTargetShown = imeShouldShow; + if (mLastAdjustTop < 0) { + mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; + } + if (mAnimation != null || (mImeWasShown && imeShouldShow + && mTargetAdjusted != mAdjusted)) { + // We need to animate adjustment independently of the IME position, so + // start our own animation to drive adjustment. This happens when a + // different split's editor has gained focus while the IME is still visible. + startAsyncAnimation(); + } + updateImeAdjustState(); + } + + private void updateImeAdjustState() { + // Reposition the server's secondary split position so that it evaluates + // insets properly. + WindowContainerTransaction wct = new WindowContainerTransaction(); + if (mTargetAdjusted) { + mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); + wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); + // "Freeze" the configuration size so that the app doesn't get a config + // or relaunch. This is required because normally nav-bar contributes + // to configuration bounds (via nondecorframe). + Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration + .windowConfiguration.getAppBounds()); + adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top + - mSplitLayout.mSecondary.top); + wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); + wct.setScreenSizeDp(mSplits.mSecondary.token, + mSplits.mSecondary.configuration.screenWidthDp, + mSplits.mSecondary.configuration.screenHeightDp); + } else { + wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); + wct.setAppBounds(mSplits.mSecondary.token, null); + wct.setScreenSizeDp(mSplits.mSecondary.token, + SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); + } + try { + ActivityTaskManager.getTaskOrganizerController() + .applyContainerTransaction(wct, null /* organizer */); + } catch (RemoteException e) { + } + + // Update all the adjusted-for-ime states + mView.setAdjustedForIme(mTargetShown, mTargetShown + ? DisplayImeController.ANIMATION_DURATION_SHOW_MS + : DisplayImeController.ANIMATION_DURATION_HIDE_MS); + setAdjustedForIme(mTargetShown); + } + + @Override + public void onImePositionChanged(int displayId, int imeTop, + SurfaceControl.Transaction t) { + if (mAnimation != null) { + // Not synchronized with IME anymore, so return. + return; + } + final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop); + final float progress = mTargetShown ? fraction : 1.f - fraction; + onProgress(progress, t); + } + + @Override + public void onImeEndPositioning(int displayId, boolean cancelled, + SurfaceControl.Transaction t) { + if (mAnimation != null) { + // Not synchronized with IME anymore, so return. + return; + } + onEnd(cancelled, t); + } + + private void onProgress(float progress, SurfaceControl.Transaction t) { + if (mTargetAdjusted != mAdjusted) { + final float fraction = mTargetAdjusted ? progress : 1.f - progress; + mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); + mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); + mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary, + mSplitLayout.mAdjustedSecondary); + } + final float invProg = 1.f - progress; + final float targetPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + final float targetSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mView.setResizeDimLayer(t, true /* primary */, + mLastPrimaryDim * invProg + progress * targetPrimaryDim); + mView.setResizeDimLayer(t, false /* primary */, + mLastSecondaryDim * invProg + progress * targetSecondaryDim); + } + + private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { + if (!cancelled) { + onProgress(1.f, t); + mAdjusted = mTargetAdjusted; + mImeWasShown = mTargetShown; + mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; + mLastPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mLastSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + } + } + + private void startAsyncAnimation() { + if (mAnimation != null) { + mAnimation.cancel(); + } + mAnimation = ValueAnimator.ofFloat(0.f, 1.f); + mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS); + if (mTargetAdjusted != mAdjusted) { + final float fraction = + ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop); + final float progress = mTargetAdjusted ? fraction : 1.f - fraction; + mAnimation.setCurrentFraction(progress); + } + + mAnimation.addUpdateListener(animation -> { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + float value = (float) animation.getAnimatedValue(); + onProgress(value, t); + t.apply(); + mTransactionPool.release(t); + }); + mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR); + mAnimation.addListener(new AnimatorListenerAdapter() { + private boolean mCancel = false; @Override - public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, - boolean imeShouldShow, SurfaceControl.Transaction t) { - mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = imeShouldShow && mSecondaryHasFocus - && !mSplitLayout.mDisplayLayout.isLandscape(); - mHiddenTop = hiddenTop; - mShownTop = shownTop; - mTargetShown = imeShouldShow; - if (mLastAdjustTop < 0) { - mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; - } - if (mAnimation != null || (mImeWasShown && imeShouldShow - && mTargetAdjusted != mAdjusted)) { - // We need to animate adjustment independently of the IME position, so - // start our own animation to drive adjustment. This happens when a - // different split's editor has gained focus while the IME is still visible. - startAsyncAnimation(); - } - // Reposition the server's secondary split position so that it evaluates - // insets properly. - WindowContainerTransaction wct = new WindowContainerTransaction(); - if (mTargetAdjusted) { - mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); - wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); - // "Freeze" the configuration size so that the app doesn't get a config - // or relaunch. This is required because normally nav-bar contributes - // to configuration bounds (via nondecorframe). - Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration - .windowConfiguration.getAppBounds()); - adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top - - mSplitLayout.mSecondary.top); - wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); - wct.setScreenSizeDp(mSplits.mSecondary.token, - mSplits.mSecondary.configuration.screenWidthDp, - mSplits.mSecondary.configuration.screenHeightDp); - } else { - wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); - wct.setAppBounds(mSplits.mSecondary.token, null); - wct.setScreenSizeDp(mSplits.mSecondary.token, - SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); - } - try { - ActivityTaskManager.getTaskOrganizerController() - .applyContainerTransaction(wct, null /* organizer */); - } catch (RemoteException e) { - } - - // Update all the adjusted-for-ime states - mView.setAdjustedForIme(mTargetShown, mTargetShown - ? DisplayImeController.ANIMATION_DURATION_SHOW_MS - : DisplayImeController.ANIMATION_DURATION_HIDE_MS); - setAdjustedForIme(mTargetShown); + public void onAnimationCancel(Animator animation) { + mCancel = true; } - @Override - public void onImePositionChanged(int displayId, int imeTop, - SurfaceControl.Transaction t) { - if (mAnimation != null) { - // Not synchronized with IME anymore, so return. - return; - } - final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop); - final float progress = mTargetShown ? fraction : 1.f - fraction; - onProgress(progress, t); + public void onAnimationEnd(Animator animation) { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + onEnd(mCancel, t); + t.apply(); + mTransactionPool.release(t); + mAnimation = null; } - - @Override - public void onImeEndPositioning(int displayId, boolean cancelled, - SurfaceControl.Transaction t) { - if (mAnimation != null) { - // Not synchronized with IME anymore, so return. - return; - } - onEnd(cancelled, t); - } - - private void onProgress(float progress, SurfaceControl.Transaction t) { - if (mTargetAdjusted != mAdjusted) { - final float fraction = mTargetAdjusted ? progress : 1.f - progress; - mLastAdjustTop = - (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); - mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); - mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary, - mSplitLayout.mAdjustedSecondary); - } - final float invProg = 1.f - progress; - final float targetPrimaryDim = (mSecondaryHasFocus && mTargetShown) - ? ADJUSTED_NONFOCUS_DIM : 0.f; - final float targetSecondaryDim = (!mSecondaryHasFocus && mTargetShown) - ? ADJUSTED_NONFOCUS_DIM : 0.f; - mView.setResizeDimLayer(t, true /* primary */, - mLastPrimaryDim * invProg + progress * targetPrimaryDim); - mView.setResizeDimLayer(t, false /* primary */, - mLastSecondaryDim * invProg + progress * targetSecondaryDim); - } - - private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { - if (!cancelled) { - onProgress(1.f, t); - mAdjusted = mTargetAdjusted; - mImeWasShown = mTargetShown; - mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; - mLastPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - mLastSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - } - } - - private void startAsyncAnimation() { - if (mAnimation != null) { - mAnimation.cancel(); - } - mAnimation = ValueAnimator.ofFloat(0.f, 1.f); - mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS); - if (mTargetAdjusted != mAdjusted) { - final float fraction = - ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop); - final float progress = mTargetAdjusted ? fraction : 1.f - fraction; - mAnimation.setCurrentFraction(progress); - } - - mAnimation.addUpdateListener(animation -> { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - float value = (float) animation.getAnimatedValue(); - onProgress(value, t); - t.apply(); - mTransactionPool.release(t); - }); - mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR); - mAnimation.addListener(new AnimatorListenerAdapter() { - private boolean mCancel = false; - @Override - public void onAnimationCancel(Animator animation) { - mCancel = true; - } - @Override - public void onAnimationEnd(Animator animation) { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - onEnd(mCancel, t); - t.apply(); - mTransactionPool.release(t); - mAnimation = null; - } - }); - mAnimation.start(); - } - }; + }); + mAnimation.start(); + } + } + private final DividerImeController mImePositionProcessor = new DividerImeController(); public Divider(Context context, Optional> recentsOptionalLazy, DisplayController displayController, SystemWindows systemWindows, @@ -513,44 +509,45 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } } - private void setHomeStackResizable(boolean resizable) { - if (mHomeStackResizable == resizable) { - return; - } - mHomeStackResizable = resizable; - if (!inSplitMode()) { - return; - } - WindowManagerProxy.applyHomeTasksMinimized(mSplitLayout, mSplits.mSecondary.token); - } - - private void updateMinimizedDockedStack(final boolean minimized, final long animDuration, - final boolean isHomeStackResizable) { - setHomeStackResizable(isHomeStackResizable); - if (animDuration > 0) { - mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable); - } else { - mView.setMinimizedDockStack(minimized, isHomeStackResizable); - } - updateTouchable(); - } - /** Switch to minimized state if appropriate */ public void setMinimized(final boolean minimized) { mHandler.post(() -> { - if (!inSplitMode()) { - return; + WindowContainerTransaction wct = new WindowContainerTransaction(); + if (setHomeMinimized(minimized, mHomeStackResizable, wct)) { + WindowManagerProxy.applyContainerTransaction(wct); } - if (mMinimized == minimized) { - return; - } - mMinimized = minimized; - WindowManagerProxy.applyPrimaryFocusable(mSplits, !mMinimized); - mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable); - updateTouchable(); }); } + private boolean setHomeMinimized(final boolean minimized, boolean homeStackResizable, + WindowContainerTransaction wct) { + boolean transact = false; + + // Update minimized state + if (mMinimized != minimized) { + mMinimized = minimized; + wct.setFocusable(mSplits.mPrimary.token, !mMinimized); + transact = true; + } + + // Update home-stack resizability + if (mHomeStackResizable != homeStackResizable) { + mHomeStackResizable = homeStackResizable; + if (inSplitMode()) { + WindowManagerProxy.applyHomeTasksMinimized( + mSplitLayout, mSplits.mSecondary.token, wct); + transact = true; + } + } + + // Sync state to DividerView if it exists. + if (mView != null) { + mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable); + } + updateTouchable(); + return transact; + } + void setAdjustedForIme(boolean adjustedForIme) { if (mAdjustedForIme == adjustedForIme) { return; @@ -646,46 +643,30 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } void ensureMinimizedSplit() { - final boolean wasMinimized = mMinimized; - mMinimized = true; - setHomeStackResizable(mSplits.mSecondary.isResizable()); - WindowManagerProxy.applyPrimaryFocusable(mSplits, false /* focusable */); + WindowContainerTransaction wct = new WindowContainerTransaction(); + if (setHomeMinimized(true, mSplits.mSecondary.isResizable(), wct)) { + WindowManagerProxy.applyContainerTransaction(wct); + } if (!inSplitMode()) { // Wasn't in split-mode yet, so enter now. if (DEBUG) { Log.d(TAG, " entering split mode with minimized=true"); } updateVisibility(true /* visible */); - } else if (!wasMinimized) { - if (DEBUG) { - Log.d(TAG, " in split mode, but minimizing "); - } - // Was already in split-mode, update just minimized state. - updateMinimizedDockedStack(mMinimized, getAnimDuration(), - mHomeStackResizable); } } void ensureNormalSplit() { - if (mMinimized) { - WindowManagerProxy.applyPrimaryFocusable(mSplits, true /* focusable */); + WindowContainerTransaction wct = new WindowContainerTransaction(); + if (setHomeMinimized(false /* minimized */, mHomeStackResizable, wct)) { + WindowManagerProxy.applyContainerTransaction(wct); } if (!inSplitMode()) { // Wasn't in split-mode, so enter now. if (DEBUG) { Log.d(TAG, " enter split mode unminimized "); } - mMinimized = false; updateVisibility(true /* visible */); } - if (mMinimized) { - // Was in minimized state, so leave that. - if (DEBUG) { - Log.d(TAG, " in split mode already, but unminimizing "); - } - mMinimized = false; - updateMinimizedDockedStack(mMinimized, getAnimDuration(), - mHomeStackResizable); - } } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java index 3020a25dfa474..729df3887915c 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java @@ -88,6 +88,9 @@ public class DividerWindowManager { } public void setTouchable(boolean touchable) { + if (mView == null) { + return; + } boolean changed = false; if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) { mLp.flags |= FLAG_NOT_TOUCHABLE; diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index 167c33abac6e3..fea57a320d04c 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.graphics.Rect; @@ -137,17 +138,13 @@ public class WindowManagerProxy { return resizable; } - static void applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent) { - applyHomeTasksMinimized(layout, parent, null /* transaction */); - } - /** * Assign a fixed override-bounds to home tasks that reflect their geometry while the primary * split is minimized. This actually "sticks out" of the secondary split area, but when in * minimized mode, the secondary split gets a 'negative' crop to expose it. */ static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent, - WindowContainerTransaction t) { + @NonNull WindowContainerTransaction wct) { // Resize the home/recents stacks to the larger minimized-state size final Rect homeBounds; final ArrayList homeStacks = new ArrayList<>(); @@ -158,19 +155,9 @@ public class WindowManagerProxy { homeBounds = new Rect(0, 0, layout.mDisplayLayout.width(), layout.mDisplayLayout.height()); } - WindowContainerTransaction wct = t != null ? t : new WindowContainerTransaction(); for (int i = homeStacks.size() - 1; i >= 0; --i) { wct.setBounds(homeStacks.get(i), homeBounds); } - if (t != null) { - return isHomeResizable; - } - try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, - null /* organizer */); - } catch (RemoteException e) { - Log.e(TAG, "Failed to resize home stacks ", e); - } return isHomeResizable; } @@ -301,10 +288,8 @@ public class WindowManagerProxy { } } - static void applyPrimaryFocusable(SplitScreenTaskOrganizer splits, boolean focusable) { + static void applyContainerTransaction(WindowContainerTransaction wct) { try { - WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setFocusable(splits.mPrimary.token, focusable); ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, null /* organizer */); } catch (RemoteException e) { From f89e0b93522a67b0f773391622394286339e6e17 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Mon, 9 Mar 2020 10:51:27 -0700 Subject: [PATCH 107/182] Don't apply ime adjustments/dims if split is not active Bug: 151053107 Test: Open IME on lockscreen (password) and see that there is no dim. Change-Id: Ifcac72f0fe5a59b4b1de2a696281ea2c76b3e9b5 (cherry picked from commit ee94e8d98904e746d9d626504b33605cc081e011) --- .../systemui/stackdivider/Divider.java | 36 +++++++++++-------- .../systemui/stackdivider/DividerView.java | 14 +++++++- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index ce45b03585118..04d53627d0c67 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -148,6 +148,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, * regardless of what has focus. */ private boolean mTargetShown = false; + private float mTargetPrimaryDim = 0.f; + private float mTargetSecondaryDim = 0.f; // The following are the current (most recent) states set during animation /** {@code true} if the secondary split has IME focus. */ @@ -186,8 +188,12 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, boolean imeShouldShow, SurfaceControl.Transaction t) { + if (!inSplitMode()) { + return; + } + final boolean splitIsVisible = !mView.isHidden(); mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = imeShouldShow && mSecondaryHasFocus + mTargetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus && !mSplitLayout.mDisplayLayout.isLandscape(); mHiddenTop = hiddenTop; mShownTop = shownTop; @@ -195,6 +201,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (mLastAdjustTop < 0) { mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; } + mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible) + ? ADJUSTED_NONFOCUS_DIM : 0.f; + mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible) + ? ADJUSTED_NONFOCUS_DIM : 0.f; if (mAnimation != null || (mImeWasShown && imeShouldShow && mTargetAdjusted != mAdjusted)) { // We need to animate adjustment independently of the IME position, so @@ -202,7 +212,11 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, // different split's editor has gained focus while the IME is still visible. startAsyncAnimation(); } - updateImeAdjustState(); + if (splitIsVisible) { + // If split is hidden, we don't want to trigger any relayouts that would cause the + // divider to show again. + updateImeAdjustState(); + } } private void updateImeAdjustState() { @@ -245,7 +259,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) { - if (mAnimation != null) { + if (mAnimation != null || !inSplitMode()) { // Not synchronized with IME anymore, so return. return; } @@ -257,7 +271,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeEndPositioning(int displayId, boolean cancelled, SurfaceControl.Transaction t) { - if (mAnimation != null) { + if (mAnimation != null || !inSplitMode()) { // Not synchronized with IME anymore, so return. return; } @@ -273,14 +287,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mSplitLayout.mAdjustedSecondary); } final float invProg = 1.f - progress; - final float targetPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - final float targetSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; mView.setResizeDimLayer(t, true /* primary */, - mLastPrimaryDim * invProg + progress * targetPrimaryDim); + mLastPrimaryDim * invProg + progress * mTargetPrimaryDim); mView.setResizeDimLayer(t, false /* primary */, - mLastSecondaryDim * invProg + progress * targetSecondaryDim); + mLastSecondaryDim * invProg + progress * mTargetSecondaryDim); } private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { @@ -289,10 +299,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mAdjusted = mTargetAdjusted; mImeWasShown = mTargetShown; mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; - mLastPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - mLastSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mLastPrimaryDim = mTargetPrimaryDim; + mLastSecondaryDim = mTargetSecondaryDim; } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 477cbb7c7ad07..4114bb9d055da 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -165,6 +165,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, // The view is removed or in the process of been removed from the system. private boolean mRemoved; + // Whether the surface for this view has been hidden regardless of actual visibility. This is + // used interact with keyguard. + private boolean mSurfaceHidden = false; + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -414,6 +418,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, /** Unlike setVisible, this directly hides the surface without changing view visibility. */ void setHidden(boolean hidden) { + if (mSurfaceHidden == hidden) { + return; + } + mSurfaceHidden = hidden; post(() -> { final SurfaceControl sc = getWindowSurfaceControl(); if (sc == null) { @@ -430,6 +438,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, }); } + boolean isHidden() { + return mSurfaceHidden; + } + public boolean startDragging(boolean animate, boolean touching) { cancelFlingAnimation(); if (touching) { @@ -1071,7 +1083,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, void setResizeDimLayer(Transaction t, boolean primary, float alpha) { SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim; - if (alpha <= 0.f) { + if (alpha <= 0.001f) { t.hide(dim); } else { t.setAlpha(dim, alpha); From 5e2545ffc34c989e616ddb57c8d22c579a1ea68f Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Tue, 10 Mar 2020 13:46:27 +0000 Subject: [PATCH 108/182] Revert "Don't apply ime adjustments/dims if split is not active" Revert submission 10602670 Reason for revert: Breaks WM pre-submit Reverted Changes: I68f1b47e0:Some clean-up of divider code in preparation for b... Ifcac72f0f:Don't apply ime adjustments/dims if split is not a... Bug: 151053107 Change-Id: Ie599188debabc3e58ad37141edaba7fab7f7d8eb (cherry picked from commit fae5d6e315fdfa1bd6aaee4b6d64251cbf1d6a0c) --- .../systemui/stackdivider/Divider.java | 36 ++++++++----------- .../systemui/stackdivider/DividerView.java | 14 +------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 04d53627d0c67..ce45b03585118 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -148,8 +148,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, * regardless of what has focus. */ private boolean mTargetShown = false; - private float mTargetPrimaryDim = 0.f; - private float mTargetSecondaryDim = 0.f; // The following are the current (most recent) states set during animation /** {@code true} if the secondary split has IME focus. */ @@ -188,12 +186,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, boolean imeShouldShow, SurfaceControl.Transaction t) { - if (!inSplitMode()) { - return; - } - final boolean splitIsVisible = !mView.isHidden(); mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus + mTargetAdjusted = imeShouldShow && mSecondaryHasFocus && !mSplitLayout.mDisplayLayout.isLandscape(); mHiddenTop = hiddenTop; mShownTop = shownTop; @@ -201,10 +195,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (mLastAdjustTop < 0) { mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; } - mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible) - ? ADJUSTED_NONFOCUS_DIM : 0.f; - mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible) - ? ADJUSTED_NONFOCUS_DIM : 0.f; if (mAnimation != null || (mImeWasShown && imeShouldShow && mTargetAdjusted != mAdjusted)) { // We need to animate adjustment independently of the IME position, so @@ -212,11 +202,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, // different split's editor has gained focus while the IME is still visible. startAsyncAnimation(); } - if (splitIsVisible) { - // If split is hidden, we don't want to trigger any relayouts that would cause the - // divider to show again. - updateImeAdjustState(); - } + updateImeAdjustState(); } private void updateImeAdjustState() { @@ -259,7 +245,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) { - if (mAnimation != null || !inSplitMode()) { + if (mAnimation != null) { // Not synchronized with IME anymore, so return. return; } @@ -271,7 +257,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeEndPositioning(int displayId, boolean cancelled, SurfaceControl.Transaction t) { - if (mAnimation != null || !inSplitMode()) { + if (mAnimation != null) { // Not synchronized with IME anymore, so return. return; } @@ -287,10 +273,14 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mSplitLayout.mAdjustedSecondary); } final float invProg = 1.f - progress; + final float targetPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + final float targetSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; mView.setResizeDimLayer(t, true /* primary */, - mLastPrimaryDim * invProg + progress * mTargetPrimaryDim); + mLastPrimaryDim * invProg + progress * targetPrimaryDim); mView.setResizeDimLayer(t, false /* primary */, - mLastSecondaryDim * invProg + progress * mTargetSecondaryDim); + mLastSecondaryDim * invProg + progress * targetSecondaryDim); } private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { @@ -299,8 +289,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mAdjusted = mTargetAdjusted; mImeWasShown = mTargetShown; mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; - mLastPrimaryDim = mTargetPrimaryDim; - mLastSecondaryDim = mTargetSecondaryDim; + mLastPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mLastSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 4114bb9d055da..477cbb7c7ad07 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -165,10 +165,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, // The view is removed or in the process of been removed from the system. private boolean mRemoved; - // Whether the surface for this view has been hidden regardless of actual visibility. This is - // used interact with keyguard. - private boolean mSurfaceHidden = false; - private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -418,10 +414,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, /** Unlike setVisible, this directly hides the surface without changing view visibility. */ void setHidden(boolean hidden) { - if (mSurfaceHidden == hidden) { - return; - } - mSurfaceHidden = hidden; post(() -> { final SurfaceControl sc = getWindowSurfaceControl(); if (sc == null) { @@ -438,10 +430,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, }); } - boolean isHidden() { - return mSurfaceHidden; - } - public boolean startDragging(boolean animate, boolean touching) { cancelFlingAnimation(); if (touching) { @@ -1083,7 +1071,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, void setResizeDimLayer(Transaction t, boolean primary, float alpha) { SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim; - if (alpha <= 0.001f) { + if (alpha <= 0.f) { t.hide(dim); } else { t.setAlpha(dim, alpha); From 9b523725642d30cdb6e452791b5c2c1a404cf084 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Tue, 10 Mar 2020 13:46:27 +0000 Subject: [PATCH 109/182] Revert "Some clean-up of divider code in preparation for bugfixes" Revert submission 10602670 Reason for revert: Breaks WM pre-submit Reverted Changes: I68f1b47e0:Some clean-up of divider code in preparation for b... Ifcac72f0f:Don't apply ime adjustments/dims if split is not a... Bug: 150781668 Change-Id: I8a497b395f25865b476590c3c0cb98133b94ac8e (cherry picked from commit 91ac7d79c515fea486e2fbc33383f981363ae118) --- .../systemui/stackdivider/Divider.java | 495 +++++++++--------- .../stackdivider/DividerWindowManager.java | 3 - .../stackdivider/WindowManagerProxy.java | 21 +- 3 files changed, 275 insertions(+), 244 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index ce45b03585118..c6eecf260dac1 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -129,213 +129,217 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } }; - private class DividerImeController implements DisplayImeController.ImePositionProcessor { - /** - * These are the y positions of the top of the IME surface when it is hidden and when it is - * shown respectively. These are NOT necessarily the top of the visible IME itself. - */ - private int mHiddenTop = 0; - private int mShownTop = 0; + private DisplayImeController.ImePositionProcessor mImePositionProcessor = + new DisplayImeController.ImePositionProcessor() { + /** + * These are the y positions of the top of the IME surface when it is hidden and + * when it is shown respectively. These are NOT necessarily the top of the visible + * IME itself. + */ + private int mHiddenTop = 0; + private int mShownTop = 0; - // The following are target states (what we are curretly animating towards). - /** - * {@code true} if, at the end of the animation, the split task positions should be - * adjusted by height of the IME. This happens when the secondary split is the IME target. - */ - private boolean mTargetAdjusted = false; - /** - * {@code true} if, at the end of the animation, the IME should be shown/visible - * regardless of what has focus. - */ - private boolean mTargetShown = false; + // The following are target states (what we are curretly animating towards). + /** + * {@code true} if, at the end of the animation, the split task positions should be + * adjusted by height of the IME. This happens when the secondary split is the IME + * target. + */ + private boolean mTargetAdjusted = false; + /** + * {@code true} if, at the end of the animation, the IME should be shown/visible + * regardless of what has focus. + */ + private boolean mTargetShown = false; - // The following are the current (most recent) states set during animation - /** {@code true} if the secondary split has IME focus. */ - private boolean mSecondaryHasFocus = false; - /** The dimming currently applied to the primary/secondary splits. */ - private float mLastPrimaryDim = 0.f; - private float mLastSecondaryDim = 0.f; - /** The most recent y position of the top of the IME surface */ - private int mLastAdjustTop = -1; + // The following are the current (most recent) states set during animation + /** + * {@code true} if the secondary split has IME focus. + */ + private boolean mSecondaryHasFocus = false; + /** The dimming currently applied to the primary/secondary splits. */ + private float mLastPrimaryDim = 0.f; + private float mLastSecondaryDim = 0.f; + /** The most recent y position of the top of the IME surface */ + private int mLastAdjustTop = -1; - // The following are states reached last time an animation fully completed. - /** {@code true} if the IME was shown/visible by the last-completed animation. */ - private boolean mImeWasShown = false; - /** {@code true} if the split positions were adjusted by the last-completed animation. */ - private boolean mAdjusted = false; + // The following are states reached last time an animation fully completed. + /** {@code true} if the IME was shown/visible by the last-completed animation. */ + private boolean mImeWasShown = false; + /** + * {@code true} if the split positions were adjusted by the last-completed + * animation. + */ + private boolean mAdjusted = false; - /** - * When some aspect of split-screen needs to animate independent from the IME, - * this will be non-null and control split animation. - */ - @Nullable - private ValueAnimator mAnimation = null; + /** + * When some aspect of split-screen needs to animate independent from the IME, + * this will be non-null and control split animation. + */ + @Nullable + private ValueAnimator mAnimation = null; - private boolean getSecondaryHasFocus(int displayId) { - try { - IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() - .getImeTarget(displayId); - return imeSplit != null - && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to get IME target", e); - } - return false; - } - - @Override - public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, - boolean imeShouldShow, SurfaceControl.Transaction t) { - mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = imeShouldShow && mSecondaryHasFocus - && !mSplitLayout.mDisplayLayout.isLandscape(); - mHiddenTop = hiddenTop; - mShownTop = shownTop; - mTargetShown = imeShouldShow; - if (mLastAdjustTop < 0) { - mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; - } - if (mAnimation != null || (mImeWasShown && imeShouldShow - && mTargetAdjusted != mAdjusted)) { - // We need to animate adjustment independently of the IME position, so - // start our own animation to drive adjustment. This happens when a - // different split's editor has gained focus while the IME is still visible. - startAsyncAnimation(); - } - updateImeAdjustState(); - } - - private void updateImeAdjustState() { - // Reposition the server's secondary split position so that it evaluates - // insets properly. - WindowContainerTransaction wct = new WindowContainerTransaction(); - if (mTargetAdjusted) { - mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); - wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); - // "Freeze" the configuration size so that the app doesn't get a config - // or relaunch. This is required because normally nav-bar contributes - // to configuration bounds (via nondecorframe). - Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration - .windowConfiguration.getAppBounds()); - adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top - - mSplitLayout.mSecondary.top); - wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); - wct.setScreenSizeDp(mSplits.mSecondary.token, - mSplits.mSecondary.configuration.screenWidthDp, - mSplits.mSecondary.configuration.screenHeightDp); - } else { - wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); - wct.setAppBounds(mSplits.mSecondary.token, null); - wct.setScreenSizeDp(mSplits.mSecondary.token, - SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); - } - try { - ActivityTaskManager.getTaskOrganizerController() - .applyContainerTransaction(wct, null /* organizer */); - } catch (RemoteException e) { - } - - // Update all the adjusted-for-ime states - mView.setAdjustedForIme(mTargetShown, mTargetShown - ? DisplayImeController.ANIMATION_DURATION_SHOW_MS - : DisplayImeController.ANIMATION_DURATION_HIDE_MS); - setAdjustedForIme(mTargetShown); - } - - @Override - public void onImePositionChanged(int displayId, int imeTop, - SurfaceControl.Transaction t) { - if (mAnimation != null) { - // Not synchronized with IME anymore, so return. - return; - } - final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop); - final float progress = mTargetShown ? fraction : 1.f - fraction; - onProgress(progress, t); - } - - @Override - public void onImeEndPositioning(int displayId, boolean cancelled, - SurfaceControl.Transaction t) { - if (mAnimation != null) { - // Not synchronized with IME anymore, so return. - return; - } - onEnd(cancelled, t); - } - - private void onProgress(float progress, SurfaceControl.Transaction t) { - if (mTargetAdjusted != mAdjusted) { - final float fraction = mTargetAdjusted ? progress : 1.f - progress; - mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); - mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); - mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary, - mSplitLayout.mAdjustedSecondary); - } - final float invProg = 1.f - progress; - final float targetPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - final float targetSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - mView.setResizeDimLayer(t, true /* primary */, - mLastPrimaryDim * invProg + progress * targetPrimaryDim); - mView.setResizeDimLayer(t, false /* primary */, - mLastSecondaryDim * invProg + progress * targetSecondaryDim); - } - - private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { - if (!cancelled) { - onProgress(1.f, t); - mAdjusted = mTargetAdjusted; - mImeWasShown = mTargetShown; - mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; - mLastPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - mLastSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - } - } - - private void startAsyncAnimation() { - if (mAnimation != null) { - mAnimation.cancel(); - } - mAnimation = ValueAnimator.ofFloat(0.f, 1.f); - mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS); - if (mTargetAdjusted != mAdjusted) { - final float fraction = - ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop); - final float progress = mTargetAdjusted ? fraction : 1.f - fraction; - mAnimation.setCurrentFraction(progress); - } - - mAnimation.addUpdateListener(animation -> { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - float value = (float) animation.getAnimatedValue(); - onProgress(value, t); - t.apply(); - mTransactionPool.release(t); - }); - mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR); - mAnimation.addListener(new AnimatorListenerAdapter() { - private boolean mCancel = false; - @Override - public void onAnimationCancel(Animator animation) { - mCancel = true; + private boolean getSecondaryHasFocus(int displayId) { + try { + IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() + .getImeTarget(displayId); + return imeSplit != null + && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to get IME target", e); + } + return false; } + @Override - public void onAnimationEnd(Animator animation) { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - onEnd(mCancel, t); - t.apply(); - mTransactionPool.release(t); - mAnimation = null; + public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, + boolean imeShouldShow, SurfaceControl.Transaction t) { + mSecondaryHasFocus = getSecondaryHasFocus(displayId); + mTargetAdjusted = imeShouldShow && mSecondaryHasFocus + && !mSplitLayout.mDisplayLayout.isLandscape(); + mHiddenTop = hiddenTop; + mShownTop = shownTop; + mTargetShown = imeShouldShow; + if (mLastAdjustTop < 0) { + mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; + } + if (mAnimation != null || (mImeWasShown && imeShouldShow + && mTargetAdjusted != mAdjusted)) { + // We need to animate adjustment independently of the IME position, so + // start our own animation to drive adjustment. This happens when a + // different split's editor has gained focus while the IME is still visible. + startAsyncAnimation(); + } + // Reposition the server's secondary split position so that it evaluates + // insets properly. + WindowContainerTransaction wct = new WindowContainerTransaction(); + if (mTargetAdjusted) { + mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); + wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); + // "Freeze" the configuration size so that the app doesn't get a config + // or relaunch. This is required because normally nav-bar contributes + // to configuration bounds (via nondecorframe). + Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration + .windowConfiguration.getAppBounds()); + adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top + - mSplitLayout.mSecondary.top); + wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); + wct.setScreenSizeDp(mSplits.mSecondary.token, + mSplits.mSecondary.configuration.screenWidthDp, + mSplits.mSecondary.configuration.screenHeightDp); + } else { + wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); + wct.setAppBounds(mSplits.mSecondary.token, null); + wct.setScreenSizeDp(mSplits.mSecondary.token, + SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); + } + try { + ActivityTaskManager.getTaskOrganizerController() + .applyContainerTransaction(wct, null /* organizer */); + } catch (RemoteException e) { + } + + // Update all the adjusted-for-ime states + mView.setAdjustedForIme(mTargetShown, mTargetShown + ? DisplayImeController.ANIMATION_DURATION_SHOW_MS + : DisplayImeController.ANIMATION_DURATION_HIDE_MS); + setAdjustedForIme(mTargetShown); } - }); - mAnimation.start(); - } - } - private final DividerImeController mImePositionProcessor = new DividerImeController(); + + @Override + public void onImePositionChanged(int displayId, int imeTop, + SurfaceControl.Transaction t) { + if (mAnimation != null) { + // Not synchronized with IME anymore, so return. + return; + } + final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop); + final float progress = mTargetShown ? fraction : 1.f - fraction; + onProgress(progress, t); + } + + @Override + public void onImeEndPositioning(int displayId, boolean cancelled, + SurfaceControl.Transaction t) { + if (mAnimation != null) { + // Not synchronized with IME anymore, so return. + return; + } + onEnd(cancelled, t); + } + + private void onProgress(float progress, SurfaceControl.Transaction t) { + if (mTargetAdjusted != mAdjusted) { + final float fraction = mTargetAdjusted ? progress : 1.f - progress; + mLastAdjustTop = + (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); + mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); + mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary, + mSplitLayout.mAdjustedSecondary); + } + final float invProg = 1.f - progress; + final float targetPrimaryDim = (mSecondaryHasFocus && mTargetShown) + ? ADJUSTED_NONFOCUS_DIM : 0.f; + final float targetSecondaryDim = (!mSecondaryHasFocus && mTargetShown) + ? ADJUSTED_NONFOCUS_DIM : 0.f; + mView.setResizeDimLayer(t, true /* primary */, + mLastPrimaryDim * invProg + progress * targetPrimaryDim); + mView.setResizeDimLayer(t, false /* primary */, + mLastSecondaryDim * invProg + progress * targetSecondaryDim); + } + + private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { + if (!cancelled) { + onProgress(1.f, t); + mAdjusted = mTargetAdjusted; + mImeWasShown = mTargetShown; + mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; + mLastPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mLastSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + } + } + + private void startAsyncAnimation() { + if (mAnimation != null) { + mAnimation.cancel(); + } + mAnimation = ValueAnimator.ofFloat(0.f, 1.f); + mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS); + if (mTargetAdjusted != mAdjusted) { + final float fraction = + ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop); + final float progress = mTargetAdjusted ? fraction : 1.f - fraction; + mAnimation.setCurrentFraction(progress); + } + + mAnimation.addUpdateListener(animation -> { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + float value = (float) animation.getAnimatedValue(); + onProgress(value, t); + t.apply(); + mTransactionPool.release(t); + }); + mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR); + mAnimation.addListener(new AnimatorListenerAdapter() { + private boolean mCancel = false; + @Override + public void onAnimationCancel(Animator animation) { + mCancel = true; + } + @Override + public void onAnimationEnd(Animator animation) { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + onEnd(mCancel, t); + t.apply(); + mTransactionPool.release(t); + mAnimation = null; + } + }); + mAnimation.start(); + } + }; public Divider(Context context, Optional> recentsOptionalLazy, DisplayController displayController, SystemWindows systemWindows, @@ -509,43 +513,42 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } } + private void setHomeStackResizable(boolean resizable) { + if (mHomeStackResizable == resizable) { + return; + } + mHomeStackResizable = resizable; + if (!inSplitMode()) { + return; + } + WindowManagerProxy.applyHomeTasksMinimized(mSplitLayout, mSplits.mSecondary.token); + } + + private void updateMinimizedDockedStack(final boolean minimized, final long animDuration, + final boolean isHomeStackResizable) { + setHomeStackResizable(isHomeStackResizable); + if (animDuration > 0) { + mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable); + } else { + mView.setMinimizedDockStack(minimized, isHomeStackResizable); + } + updateTouchable(); + } + /** Switch to minimized state if appropriate */ public void setMinimized(final boolean minimized) { mHandler.post(() -> { - WindowContainerTransaction wct = new WindowContainerTransaction(); - if (setHomeMinimized(minimized, mHomeStackResizable, wct)) { - WindowManagerProxy.applyContainerTransaction(wct); + if (!inSplitMode()) { + return; + } + if (mMinimized == minimized) { + return; } - }); - } - - private boolean setHomeMinimized(final boolean minimized, boolean homeStackResizable, - WindowContainerTransaction wct) { - boolean transact = false; - - // Update minimized state - if (mMinimized != minimized) { mMinimized = minimized; - wct.setFocusable(mSplits.mPrimary.token, !mMinimized); - transact = true; - } - - // Update home-stack resizability - if (mHomeStackResizable != homeStackResizable) { - mHomeStackResizable = homeStackResizable; - if (inSplitMode()) { - WindowManagerProxy.applyHomeTasksMinimized( - mSplitLayout, mSplits.mSecondary.token, wct); - transact = true; - } - } - - // Sync state to DividerView if it exists. - if (mView != null) { - mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable); - } - updateTouchable(); - return transact; + WindowManagerProxy.applyPrimaryFocusable(mSplits, !mMinimized); + mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable); + updateTouchable(); + }); } void setAdjustedForIme(boolean adjustedForIme) { @@ -643,30 +646,46 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } void ensureMinimizedSplit() { - WindowContainerTransaction wct = new WindowContainerTransaction(); - if (setHomeMinimized(true, mSplits.mSecondary.isResizable(), wct)) { - WindowManagerProxy.applyContainerTransaction(wct); - } + final boolean wasMinimized = mMinimized; + mMinimized = true; + setHomeStackResizable(mSplits.mSecondary.isResizable()); + WindowManagerProxy.applyPrimaryFocusable(mSplits, false /* focusable */); if (!inSplitMode()) { // Wasn't in split-mode yet, so enter now. if (DEBUG) { Log.d(TAG, " entering split mode with minimized=true"); } updateVisibility(true /* visible */); + } else if (!wasMinimized) { + if (DEBUG) { + Log.d(TAG, " in split mode, but minimizing "); + } + // Was already in split-mode, update just minimized state. + updateMinimizedDockedStack(mMinimized, getAnimDuration(), + mHomeStackResizable); } } void ensureNormalSplit() { - WindowContainerTransaction wct = new WindowContainerTransaction(); - if (setHomeMinimized(false /* minimized */, mHomeStackResizable, wct)) { - WindowManagerProxy.applyContainerTransaction(wct); + if (mMinimized) { + WindowManagerProxy.applyPrimaryFocusable(mSplits, true /* focusable */); } if (!inSplitMode()) { // Wasn't in split-mode, so enter now. if (DEBUG) { Log.d(TAG, " enter split mode unminimized "); } + mMinimized = false; updateVisibility(true /* visible */); } + if (mMinimized) { + // Was in minimized state, so leave that. + if (DEBUG) { + Log.d(TAG, " in split mode already, but unminimizing "); + } + mMinimized = false; + updateMinimizedDockedStack(mMinimized, getAnimDuration(), + mHomeStackResizable); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java index 729df3887915c..3020a25dfa474 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java @@ -88,9 +88,6 @@ public class DividerWindowManager { } public void setTouchable(boolean touchable) { - if (mView == null) { - return; - } boolean changed = false; if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) { mLp.flags |= FLAG_NOT_TOUCHABLE; diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index fea57a320d04c..167c33abac6e3 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -21,7 +21,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; -import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.graphics.Rect; @@ -138,13 +137,17 @@ public class WindowManagerProxy { return resizable; } + static void applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent) { + applyHomeTasksMinimized(layout, parent, null /* transaction */); + } + /** * Assign a fixed override-bounds to home tasks that reflect their geometry while the primary * split is minimized. This actually "sticks out" of the secondary split area, but when in * minimized mode, the secondary split gets a 'negative' crop to expose it. */ static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent, - @NonNull WindowContainerTransaction wct) { + WindowContainerTransaction t) { // Resize the home/recents stacks to the larger minimized-state size final Rect homeBounds; final ArrayList homeStacks = new ArrayList<>(); @@ -155,9 +158,19 @@ public class WindowManagerProxy { homeBounds = new Rect(0, 0, layout.mDisplayLayout.width(), layout.mDisplayLayout.height()); } + WindowContainerTransaction wct = t != null ? t : new WindowContainerTransaction(); for (int i = homeStacks.size() - 1; i >= 0; --i) { wct.setBounds(homeStacks.get(i), homeBounds); } + if (t != null) { + return isHomeResizable; + } + try { + ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, + null /* organizer */); + } catch (RemoteException e) { + Log.e(TAG, "Failed to resize home stacks ", e); + } return isHomeResizable; } @@ -288,8 +301,10 @@ public class WindowManagerProxy { } } - static void applyContainerTransaction(WindowContainerTransaction wct) { + static void applyPrimaryFocusable(SplitScreenTaskOrganizer splits, boolean focusable) { try { + WindowContainerTransaction wct = new WindowContainerTransaction(); + wct.setFocusable(splits.mPrimary.token, focusable); ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, null /* organizer */); } catch (RemoteException e) { From 7241b493e18222476f18f8f48d70bfc343e32fec Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Fri, 6 Mar 2020 19:35:48 -0800 Subject: [PATCH 110/182] Some clean-up of divider code in preparation for bugfixes Made an actual class for the imecontroller in divider to prepare for some more complicated interactions. Also consolidated the minimize/resizability update logic for the same reason. Bug: 150781668 Test: no change. things should work and tests pass Change-Id: I03ca72ebd7a4b635cb91d78c18c2187b6966e514 (cherry picked from commit fe31c04a33dde4d810f2cf47b7f783c58da558cd) --- .../systemui/stackdivider/Divider.java | 483 ++++++++---------- .../stackdivider/DividerWindowManager.java | 3 + .../stackdivider/WindowManagerProxy.java | 21 +- 3 files changed, 232 insertions(+), 275 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index c6eecf260dac1..fb6815336548f 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -129,217 +129,213 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } }; - private DisplayImeController.ImePositionProcessor mImePositionProcessor = - new DisplayImeController.ImePositionProcessor() { - /** - * These are the y positions of the top of the IME surface when it is hidden and - * when it is shown respectively. These are NOT necessarily the top of the visible - * IME itself. - */ - private int mHiddenTop = 0; - private int mShownTop = 0; + private class DividerImeController implements DisplayImeController.ImePositionProcessor { + /** + * These are the y positions of the top of the IME surface when it is hidden and when it is + * shown respectively. These are NOT necessarily the top of the visible IME itself. + */ + private int mHiddenTop = 0; + private int mShownTop = 0; - // The following are target states (what we are curretly animating towards). - /** - * {@code true} if, at the end of the animation, the split task positions should be - * adjusted by height of the IME. This happens when the secondary split is the IME - * target. - */ - private boolean mTargetAdjusted = false; - /** - * {@code true} if, at the end of the animation, the IME should be shown/visible - * regardless of what has focus. - */ - private boolean mTargetShown = false; + // The following are target states (what we are curretly animating towards). + /** + * {@code true} if, at the end of the animation, the split task positions should be + * adjusted by height of the IME. This happens when the secondary split is the IME target. + */ + private boolean mTargetAdjusted = false; + /** + * {@code true} if, at the end of the animation, the IME should be shown/visible + * regardless of what has focus. + */ + private boolean mTargetShown = false; - // The following are the current (most recent) states set during animation - /** - * {@code true} if the secondary split has IME focus. - */ - private boolean mSecondaryHasFocus = false; - /** The dimming currently applied to the primary/secondary splits. */ - private float mLastPrimaryDim = 0.f; - private float mLastSecondaryDim = 0.f; - /** The most recent y position of the top of the IME surface */ - private int mLastAdjustTop = -1; + // The following are the current (most recent) states set during animation + /** {@code true} if the secondary split has IME focus. */ + private boolean mSecondaryHasFocus = false; + /** The dimming currently applied to the primary/secondary splits. */ + private float mLastPrimaryDim = 0.f; + private float mLastSecondaryDim = 0.f; + /** The most recent y position of the top of the IME surface */ + private int mLastAdjustTop = -1; - // The following are states reached last time an animation fully completed. - /** {@code true} if the IME was shown/visible by the last-completed animation. */ - private boolean mImeWasShown = false; - /** - * {@code true} if the split positions were adjusted by the last-completed - * animation. - */ - private boolean mAdjusted = false; + // The following are states reached last time an animation fully completed. + /** {@code true} if the IME was shown/visible by the last-completed animation. */ + private boolean mImeWasShown = false; + /** {@code true} if the split positions were adjusted by the last-completed animation. */ + private boolean mAdjusted = false; - /** - * When some aspect of split-screen needs to animate independent from the IME, - * this will be non-null and control split animation. - */ - @Nullable - private ValueAnimator mAnimation = null; + /** + * When some aspect of split-screen needs to animate independent from the IME, + * this will be non-null and control split animation. + */ + @Nullable + private ValueAnimator mAnimation = null; - private boolean getSecondaryHasFocus(int displayId) { - try { - IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() - .getImeTarget(displayId); - return imeSplit != null - && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to get IME target", e); - } - return false; - } + private boolean getSecondaryHasFocus(int displayId) { + try { + IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() + .getImeTarget(displayId); + return imeSplit != null + && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to get IME target", e); + } + return false; + } + @Override + public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, + boolean imeShouldShow, SurfaceControl.Transaction t) { + mSecondaryHasFocus = getSecondaryHasFocus(displayId); + mTargetAdjusted = imeShouldShow && mSecondaryHasFocus + && !mSplitLayout.mDisplayLayout.isLandscape(); + mHiddenTop = hiddenTop; + mShownTop = shownTop; + mTargetShown = imeShouldShow; + if (mLastAdjustTop < 0) { + mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; + } + if (mAnimation != null || (mImeWasShown && imeShouldShow + && mTargetAdjusted != mAdjusted)) { + // We need to animate adjustment independently of the IME position, so + // start our own animation to drive adjustment. This happens when a + // different split's editor has gained focus while the IME is still visible. + startAsyncAnimation(); + } + updateImeAdjustState(); + } + + private void updateImeAdjustState() { + // Reposition the server's secondary split position so that it evaluates + // insets properly. + WindowContainerTransaction wct = new WindowContainerTransaction(); + if (mTargetAdjusted) { + mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); + wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); + // "Freeze" the configuration size so that the app doesn't get a config + // or relaunch. This is required because normally nav-bar contributes + // to configuration bounds (via nondecorframe). + Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration + .windowConfiguration.getAppBounds()); + adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top + - mSplitLayout.mSecondary.top); + wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); + wct.setScreenSizeDp(mSplits.mSecondary.token, + mSplits.mSecondary.configuration.screenWidthDp, + mSplits.mSecondary.configuration.screenHeightDp); + } else { + wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); + wct.setAppBounds(mSplits.mSecondary.token, null); + wct.setScreenSizeDp(mSplits.mSecondary.token, + SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); + } + try { + ActivityTaskManager.getTaskOrganizerController() + .applyContainerTransaction(wct, null /* organizer */); + } catch (RemoteException e) { + } + + // Update all the adjusted-for-ime states + mView.setAdjustedForIme(mTargetShown, mTargetShown + ? DisplayImeController.ANIMATION_DURATION_SHOW_MS + : DisplayImeController.ANIMATION_DURATION_HIDE_MS); + setAdjustedForIme(mTargetShown); + } + + @Override + public void onImePositionChanged(int displayId, int imeTop, + SurfaceControl.Transaction t) { + if (mAnimation != null) { + // Not synchronized with IME anymore, so return. + return; + } + final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop); + final float progress = mTargetShown ? fraction : 1.f - fraction; + onProgress(progress, t); + } + + @Override + public void onImeEndPositioning(int displayId, boolean cancelled, + SurfaceControl.Transaction t) { + if (mAnimation != null) { + // Not synchronized with IME anymore, so return. + return; + } + onEnd(cancelled, t); + } + + private void onProgress(float progress, SurfaceControl.Transaction t) { + if (mTargetAdjusted != mAdjusted) { + final float fraction = mTargetAdjusted ? progress : 1.f - progress; + mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); + mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); + mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary, + mSplitLayout.mAdjustedSecondary); + } + final float invProg = 1.f - progress; + final float targetPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + final float targetSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mView.setResizeDimLayer(t, true /* primary */, + mLastPrimaryDim * invProg + progress * targetPrimaryDim); + mView.setResizeDimLayer(t, false /* primary */, + mLastSecondaryDim * invProg + progress * targetSecondaryDim); + } + + private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { + if (!cancelled) { + onProgress(1.f, t); + mAdjusted = mTargetAdjusted; + mImeWasShown = mTargetShown; + mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; + mLastPrimaryDim = + (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mLastSecondaryDim = + (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + } + } + + private void startAsyncAnimation() { + if (mAnimation != null) { + mAnimation.cancel(); + } + mAnimation = ValueAnimator.ofFloat(0.f, 1.f); + mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS); + if (mTargetAdjusted != mAdjusted) { + final float fraction = + ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop); + final float progress = mTargetAdjusted ? fraction : 1.f - fraction; + mAnimation.setCurrentFraction(progress); + } + + mAnimation.addUpdateListener(animation -> { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + float value = (float) animation.getAnimatedValue(); + onProgress(value, t); + t.apply(); + mTransactionPool.release(t); + }); + mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR); + mAnimation.addListener(new AnimatorListenerAdapter() { + private boolean mCancel = false; @Override - public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, - boolean imeShouldShow, SurfaceControl.Transaction t) { - mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = imeShouldShow && mSecondaryHasFocus - && !mSplitLayout.mDisplayLayout.isLandscape(); - mHiddenTop = hiddenTop; - mShownTop = shownTop; - mTargetShown = imeShouldShow; - if (mLastAdjustTop < 0) { - mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; - } - if (mAnimation != null || (mImeWasShown && imeShouldShow - && mTargetAdjusted != mAdjusted)) { - // We need to animate adjustment independently of the IME position, so - // start our own animation to drive adjustment. This happens when a - // different split's editor has gained focus while the IME is still visible. - startAsyncAnimation(); - } - // Reposition the server's secondary split position so that it evaluates - // insets properly. - WindowContainerTransaction wct = new WindowContainerTransaction(); - if (mTargetAdjusted) { - mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); - wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary); - // "Freeze" the configuration size so that the app doesn't get a config - // or relaunch. This is required because normally nav-bar contributes - // to configuration bounds (via nondecorframe). - Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration - .windowConfiguration.getAppBounds()); - adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top - - mSplitLayout.mSecondary.top); - wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds); - wct.setScreenSizeDp(mSplits.mSecondary.token, - mSplits.mSecondary.configuration.screenWidthDp, - mSplits.mSecondary.configuration.screenHeightDp); - } else { - wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary); - wct.setAppBounds(mSplits.mSecondary.token, null); - wct.setScreenSizeDp(mSplits.mSecondary.token, - SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); - } - try { - ActivityTaskManager.getTaskOrganizerController() - .applyContainerTransaction(wct, null /* organizer */); - } catch (RemoteException e) { - } - - // Update all the adjusted-for-ime states - mView.setAdjustedForIme(mTargetShown, mTargetShown - ? DisplayImeController.ANIMATION_DURATION_SHOW_MS - : DisplayImeController.ANIMATION_DURATION_HIDE_MS); - setAdjustedForIme(mTargetShown); + public void onAnimationCancel(Animator animation) { + mCancel = true; } - @Override - public void onImePositionChanged(int displayId, int imeTop, - SurfaceControl.Transaction t) { - if (mAnimation != null) { - // Not synchronized with IME anymore, so return. - return; - } - final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop); - final float progress = mTargetShown ? fraction : 1.f - fraction; - onProgress(progress, t); + public void onAnimationEnd(Animator animation) { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + onEnd(mCancel, t); + t.apply(); + mTransactionPool.release(t); + mAnimation = null; } - - @Override - public void onImeEndPositioning(int displayId, boolean cancelled, - SurfaceControl.Transaction t) { - if (mAnimation != null) { - // Not synchronized with IME anymore, so return. - return; - } - onEnd(cancelled, t); - } - - private void onProgress(float progress, SurfaceControl.Transaction t) { - if (mTargetAdjusted != mAdjusted) { - final float fraction = mTargetAdjusted ? progress : 1.f - progress; - mLastAdjustTop = - (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); - mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); - mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary, - mSplitLayout.mAdjustedSecondary); - } - final float invProg = 1.f - progress; - final float targetPrimaryDim = (mSecondaryHasFocus && mTargetShown) - ? ADJUSTED_NONFOCUS_DIM : 0.f; - final float targetSecondaryDim = (!mSecondaryHasFocus && mTargetShown) - ? ADJUSTED_NONFOCUS_DIM : 0.f; - mView.setResizeDimLayer(t, true /* primary */, - mLastPrimaryDim * invProg + progress * targetPrimaryDim); - mView.setResizeDimLayer(t, false /* primary */, - mLastSecondaryDim * invProg + progress * targetSecondaryDim); - } - - private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { - if (!cancelled) { - onProgress(1.f, t); - mAdjusted = mTargetAdjusted; - mImeWasShown = mTargetShown; - mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; - mLastPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - mLastSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - } - } - - private void startAsyncAnimation() { - if (mAnimation != null) { - mAnimation.cancel(); - } - mAnimation = ValueAnimator.ofFloat(0.f, 1.f); - mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS); - if (mTargetAdjusted != mAdjusted) { - final float fraction = - ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop); - final float progress = mTargetAdjusted ? fraction : 1.f - fraction; - mAnimation.setCurrentFraction(progress); - } - - mAnimation.addUpdateListener(animation -> { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - float value = (float) animation.getAnimatedValue(); - onProgress(value, t); - t.apply(); - mTransactionPool.release(t); - }); - mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR); - mAnimation.addListener(new AnimatorListenerAdapter() { - private boolean mCancel = false; - @Override - public void onAnimationCancel(Animator animation) { - mCancel = true; - } - @Override - public void onAnimationEnd(Animator animation) { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - onEnd(mCancel, t); - t.apply(); - mTransactionPool.release(t); - mAnimation = null; - } - }); - mAnimation.start(); - } - }; + }); + mAnimation.start(); + } + } + private final DividerImeController mImePositionProcessor = new DividerImeController(); public Divider(Context context, Optional> recentsOptionalLazy, DisplayController displayController, SystemWindows systemWindows, @@ -513,44 +509,39 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } } - private void setHomeStackResizable(boolean resizable) { - if (mHomeStackResizable == resizable) { - return; - } - mHomeStackResizable = resizable; - if (!inSplitMode()) { - return; - } - WindowManagerProxy.applyHomeTasksMinimized(mSplitLayout, mSplits.mSecondary.token); - } - - private void updateMinimizedDockedStack(final boolean minimized, final long animDuration, - final boolean isHomeStackResizable) { - setHomeStackResizable(isHomeStackResizable); - if (animDuration > 0) { - mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable); - } else { - mView.setMinimizedDockStack(minimized, isHomeStackResizable); - } - updateTouchable(); - } - /** Switch to minimized state if appropriate */ public void setMinimized(final boolean minimized) { mHandler.post(() -> { - if (!inSplitMode()) { - return; - } - if (mMinimized == minimized) { - return; - } - mMinimized = minimized; - WindowManagerProxy.applyPrimaryFocusable(mSplits, !mMinimized); - mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable); - updateTouchable(); + setHomeMinimized(minimized, mHomeStackResizable); }); } + private void setHomeMinimized(final boolean minimized, boolean homeStackResizable) { + WindowContainerTransaction wct = new WindowContainerTransaction(); + // Update minimized state + if (mMinimized != minimized) { + mMinimized = minimized; + } + // Always set this because we could be entering split when mMinimized is already true + wct.setFocusable(mSplits.mPrimary.token, !mMinimized); + + // Update home-stack resizability + if (mHomeStackResizable != homeStackResizable) { + mHomeStackResizable = homeStackResizable; + if (inSplitMode()) { + WindowManagerProxy.applyHomeTasksMinimized( + mSplitLayout, mSplits.mSecondary.token, wct); + } + } + + // Sync state to DividerView if it exists. + if (mView != null) { + mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable); + } + updateTouchable(); + WindowManagerProxy.applyContainerTransaction(wct); + } + void setAdjustedForIme(boolean adjustedForIme) { if (mAdjustedForIme == adjustedForIme) { return; @@ -646,46 +637,24 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } void ensureMinimizedSplit() { - final boolean wasMinimized = mMinimized; - mMinimized = true; - setHomeStackResizable(mSplits.mSecondary.isResizable()); - WindowManagerProxy.applyPrimaryFocusable(mSplits, false /* focusable */); + setHomeMinimized(true /* minimized */, mSplits.mSecondary.isResizable()); if (!inSplitMode()) { // Wasn't in split-mode yet, so enter now. if (DEBUG) { Log.d(TAG, " entering split mode with minimized=true"); } updateVisibility(true /* visible */); - } else if (!wasMinimized) { - if (DEBUG) { - Log.d(TAG, " in split mode, but minimizing "); - } - // Was already in split-mode, update just minimized state. - updateMinimizedDockedStack(mMinimized, getAnimDuration(), - mHomeStackResizable); } } void ensureNormalSplit() { - if (mMinimized) { - WindowManagerProxy.applyPrimaryFocusable(mSplits, true /* focusable */); - } + setHomeMinimized(false /* minimized */, mHomeStackResizable); if (!inSplitMode()) { // Wasn't in split-mode, so enter now. if (DEBUG) { Log.d(TAG, " enter split mode unminimized "); } - mMinimized = false; updateVisibility(true /* visible */); } - if (mMinimized) { - // Was in minimized state, so leave that. - if (DEBUG) { - Log.d(TAG, " in split mode already, but unminimizing "); - } - mMinimized = false; - updateMinimizedDockedStack(mMinimized, getAnimDuration(), - mHomeStackResizable); - } } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java index 3020a25dfa474..729df3887915c 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java @@ -88,6 +88,9 @@ public class DividerWindowManager { } public void setTouchable(boolean touchable) { + if (mView == null) { + return; + } boolean changed = false; if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) { mLp.flags |= FLAG_NOT_TOUCHABLE; diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index 167c33abac6e3..fea57a320d04c 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.graphics.Rect; @@ -137,17 +138,13 @@ public class WindowManagerProxy { return resizable; } - static void applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent) { - applyHomeTasksMinimized(layout, parent, null /* transaction */); - } - /** * Assign a fixed override-bounds to home tasks that reflect their geometry while the primary * split is minimized. This actually "sticks out" of the secondary split area, but when in * minimized mode, the secondary split gets a 'negative' crop to expose it. */ static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent, - WindowContainerTransaction t) { + @NonNull WindowContainerTransaction wct) { // Resize the home/recents stacks to the larger minimized-state size final Rect homeBounds; final ArrayList homeStacks = new ArrayList<>(); @@ -158,19 +155,9 @@ public class WindowManagerProxy { homeBounds = new Rect(0, 0, layout.mDisplayLayout.width(), layout.mDisplayLayout.height()); } - WindowContainerTransaction wct = t != null ? t : new WindowContainerTransaction(); for (int i = homeStacks.size() - 1; i >= 0; --i) { wct.setBounds(homeStacks.get(i), homeBounds); } - if (t != null) { - return isHomeResizable; - } - try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, - null /* organizer */); - } catch (RemoteException e) { - Log.e(TAG, "Failed to resize home stacks ", e); - } return isHomeResizable; } @@ -301,10 +288,8 @@ public class WindowManagerProxy { } } - static void applyPrimaryFocusable(SplitScreenTaskOrganizer splits, boolean focusable) { + static void applyContainerTransaction(WindowContainerTransaction wct) { try { - WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setFocusable(splits.mPrimary.token, focusable); ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, null /* organizer */); } catch (RemoteException e) { From ea1a0ea8c207258d309b5211c15c03078809fa2c Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Mon, 9 Mar 2020 21:22:44 +0000 Subject: [PATCH 111/182] Revert "media: lazy MediaCodec.release()" Revert submission 10446783-mediacodec-lazy-release Reason for revert: back-to-back video playback jitters Reverted Changes: I119945684:stagefright: MediaCodec::releaseAsync() Ieb4c0b2e1:media: lazy MediaCodec.release() Bug: 150662913 Change-Id: I9388f90ab7befe8415afa82b6b349318c5bdc2f8 (cherry picked from commit 5b610e26eb1be054aa144c39ae3045d5f2c3d29c) --- media/jni/android_media_MediaCodec.cpp | 14 ++------------ media/jni/android_media_MediaCodec.h | 1 - 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 737c95d73e6c4..893e51654b682 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -242,13 +242,6 @@ void JMediaCodec::release() { }); } -void JMediaCodec::releaseAsync() { - if (mCodec != NULL) { - mCodec->releaseAsync(); - } - mInitStatus = NO_INIT; -} - JMediaCodec::~JMediaCodec() { if (mLooper != NULL) { /* MediaCodec and looper should have been released explicitly already @@ -1131,10 +1124,7 @@ static sp getMediaCodec(JNIEnv *env, jobject thiz) { } static void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) { - sp codec = getMediaCodec(env, thiz); - if (codec != NULL) { - codec->releaseAsync(); - } + setMediaCodec(env, thiz, NULL); } static void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) { @@ -2807,7 +2797,7 @@ static void android_media_MediaCodec_native_setup( static void android_media_MediaCodec_native_finalize( JNIEnv *env, jobject thiz) { - setMediaCodec(env, thiz, NULL); + android_media_MediaCodec_release(env, thiz); } // MediaCodec.LinearBlock diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 400ce1bc98e76..8899fee7a73d2 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -61,7 +61,6 @@ struct JMediaCodec : public AHandler { void registerSelf(); void release(); - void releaseAsync(); status_t enableOnFrameRenderedListener(jboolean enable); From c81e8b387489accb47bb2983eb0d1842da471c09 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Tue, 10 Mar 2020 10:24:35 -0700 Subject: [PATCH 112/182] Restores PiP to its original app bounds Deprecated the usage of display bounds in PipTaskOrganizer, instead we can save and restore the application bounds reported in taskAppeared. Bug: 151050577 Test: repeatedly enter/exit PiP Change-Id: If40431ff37e8dd5fa8b228d6085613da23701ea7 (cherry picked from commit 89f18ffad9fdefea59bde08e98e984491912bf78) --- .../systemui/pip/PipTaskOrganizer.java | 35 +++++-------------- .../systemui/pip/phone/PipManager.java | 6 +--- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 3933af00a47a8..cc5664249f007 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -33,10 +33,10 @@ import android.app.PictureInPictureParams; import android.content.Context; import android.graphics.Rect; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Log; -import android.view.DisplayInfo; import android.view.ITaskOrganizer; import android.view.IWindowContainer; import android.view.SurfaceControl; @@ -47,7 +47,9 @@ import com.android.systemui.R; import com.android.systemui.pip.phone.PipUpdateThread; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.Consumer; @@ -76,9 +78,9 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private final PipBoundsHandler mPipBoundsHandler; private final PipAnimationController mPipAnimationController; private final List mPipTransitionCallbacks = new ArrayList<>(); - private final Rect mDisplayBounds = new Rect(); private final Rect mLastReportedBounds = new Rect(); private final int mCornerRadius; + private final Map mBoundsToRestore = new HashMap<>(); // These callbacks are called on the update thread private final PipAnimationController.PipAnimationCallback mPipAnimationCallback = @@ -200,29 +202,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mOneShotAnimationType = animationType; } - /** - * Updates the display dimension with given {@link DisplayInfo} - */ - @SuppressWarnings("unchecked") - public void onDisplayInfoChanged(DisplayInfo displayInfo) { - final Rect newDisplayBounds = new Rect(0, 0, - displayInfo.logicalWidth, displayInfo.logicalHeight); - if (!mDisplayBounds.equals(newDisplayBounds)) { - // Updates the exiting PiP animation in case the screen rotation changes in the middle. - // It's a legit case that PiP window is in portrait mode on home screen and - // the application requests landscape once back to fullscreen mode. - final PipAnimationController.PipTransitionAnimator animator = - mPipAnimationController.getCurrentAnimator(); - if (animator != null - && animator.getAnimationType() == ANIM_TYPE_BOUNDS - && animator.getDestinationBounds().equals(mDisplayBounds)) { - animator.updateEndValue(newDisplayBounds); - animator.setDestinationBounds(newDisplayBounds); - } - } - mDisplayBounds.set(newDisplayBounds); - } - /** * Callback to issue the final {@link WindowContainerTransaction} on end of movements. * @param destinationBounds the final bounds. @@ -252,8 +231,9 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } catch (RemoteException e) { throw new RuntimeException("Unable to get leash", e); } + final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); + mBoundsToRestore.put(mToken.asBinder(), currentBounds); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { - final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); scheduleAnimateResizePip(currentBounds, destinationBounds, TRANSITION_DIRECTION_TO_PIP, DURATION_DEFAULT_MS, null); } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { @@ -277,7 +257,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { Log.wtf(TAG, "Unrecognized token: " + token); return; } - scheduleAnimateResizePip(mLastReportedBounds, mDisplayBounds, + final Rect boundsToRestore = mBoundsToRestore.remove(mToken.asBinder()); + scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore, TRANSITION_DIRECTION_TO_FULLSCREEN, DURATION_DEFAULT_MS, null); mInPip = false; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index 4b97d134761e6..eed81bfc07f94 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -185,10 +185,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio @Override public void onDisplayInfoChanged(DisplayInfo displayInfo) { - mHandler.post(() -> { - mPipBoundsHandler.onDisplayInfoChanged(displayInfo); - mPipTaskOrganizer.onDisplayInfoChanged(displayInfo); - }); + mHandler.post(() -> mPipBoundsHandler.onDisplayInfoChanged(displayInfo)); } @Override @@ -352,7 +349,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, animatingBounds, fromImeAdjustment, fromShelfAdjustment, mTmpDisplayInfo.rotation); - mPipTaskOrganizer.onDisplayInfoChanged(mTmpDisplayInfo); } public void dump(PrintWriter pw) { From 72659bbb2ed635ea7314017ea50e39992bb2c0cb Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Mon, 9 Mar 2020 10:51:27 -0700 Subject: [PATCH 113/182] Don't apply ime adjustments/dims if split is not active Bug: 151053107 Test: Open IME on lockscreen (password) and see that there is no dim. Change-Id: I9aff9ee4b3efc6feba8e8dfd74af9209dd55b05d (cherry picked from commit e5fb45a7084384e8ae20dc313c2366f60e033a37) --- .../systemui/stackdivider/Divider.java | 36 +++++++++++-------- .../systemui/stackdivider/DividerView.java | 14 +++++++- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index fb6815336548f..ea5ec05030675 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -148,6 +148,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, * regardless of what has focus. */ private boolean mTargetShown = false; + private float mTargetPrimaryDim = 0.f; + private float mTargetSecondaryDim = 0.f; // The following are the current (most recent) states set during animation /** {@code true} if the secondary split has IME focus. */ @@ -186,8 +188,12 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, boolean imeShouldShow, SurfaceControl.Transaction t) { + if (!inSplitMode()) { + return; + } + final boolean splitIsVisible = !mView.isHidden(); mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = imeShouldShow && mSecondaryHasFocus + mTargetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus && !mSplitLayout.mDisplayLayout.isLandscape(); mHiddenTop = hiddenTop; mShownTop = shownTop; @@ -195,6 +201,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (mLastAdjustTop < 0) { mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; } + mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible) + ? ADJUSTED_NONFOCUS_DIM : 0.f; + mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible) + ? ADJUSTED_NONFOCUS_DIM : 0.f; if (mAnimation != null || (mImeWasShown && imeShouldShow && mTargetAdjusted != mAdjusted)) { // We need to animate adjustment independently of the IME position, so @@ -202,7 +212,11 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, // different split's editor has gained focus while the IME is still visible. startAsyncAnimation(); } - updateImeAdjustState(); + if (splitIsVisible) { + // If split is hidden, we don't want to trigger any relayouts that would cause the + // divider to show again. + updateImeAdjustState(); + } } private void updateImeAdjustState() { @@ -245,7 +259,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) { - if (mAnimation != null) { + if (mAnimation != null || !inSplitMode()) { // Not synchronized with IME anymore, so return. return; } @@ -257,7 +271,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeEndPositioning(int displayId, boolean cancelled, SurfaceControl.Transaction t) { - if (mAnimation != null) { + if (mAnimation != null || !inSplitMode()) { // Not synchronized with IME anymore, so return. return; } @@ -273,14 +287,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mSplitLayout.mAdjustedSecondary); } final float invProg = 1.f - progress; - final float targetPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - final float targetSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; mView.setResizeDimLayer(t, true /* primary */, - mLastPrimaryDim * invProg + progress * targetPrimaryDim); + mLastPrimaryDim * invProg + progress * mTargetPrimaryDim); mView.setResizeDimLayer(t, false /* primary */, - mLastSecondaryDim * invProg + progress * targetSecondaryDim); + mLastSecondaryDim * invProg + progress * mTargetSecondaryDim); } private void onEnd(boolean cancelled, SurfaceControl.Transaction t) { @@ -289,10 +299,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mAdjusted = mTargetAdjusted; mImeWasShown = mTargetShown; mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop; - mLastPrimaryDim = - (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; - mLastSecondaryDim = - (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f; + mLastPrimaryDim = mTargetPrimaryDim; + mLastSecondaryDim = mTargetSecondaryDim; } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 477cbb7c7ad07..4114bb9d055da 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -165,6 +165,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, // The view is removed or in the process of been removed from the system. private boolean mRemoved; + // Whether the surface for this view has been hidden regardless of actual visibility. This is + // used interact with keyguard. + private boolean mSurfaceHidden = false; + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -414,6 +418,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, /** Unlike setVisible, this directly hides the surface without changing view visibility. */ void setHidden(boolean hidden) { + if (mSurfaceHidden == hidden) { + return; + } + mSurfaceHidden = hidden; post(() -> { final SurfaceControl sc = getWindowSurfaceControl(); if (sc == null) { @@ -430,6 +438,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, }); } + boolean isHidden() { + return mSurfaceHidden; + } + public boolean startDragging(boolean animate, boolean touching) { cancelFlingAnimation(); if (touching) { @@ -1071,7 +1083,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, void setResizeDimLayer(Transaction t, boolean primary, float alpha) { SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim; - if (alpha <= 0.f) { + if (alpha <= 0.001f) { t.hide(dim); } else { t.setAlpha(dim, alpha); From 5ab747b0b13b5a9d5d8245fab0a2d63b8b8efd82 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Wed, 11 Mar 2020 13:14:21 -0400 Subject: [PATCH 114/182] Null-check notif chan when ident people notifs Bug: 151050221 Test: manual Change-Id: I0cbf29a33c228ac9f3566639a592733716eee891 (cherry picked from commit b17ee6c17c0bac69797587041f8ecdcf9b73d5e9) --- .../notification/people/PeopleNotificationIdentifier.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt index 597bdb9f2e745..be3873a5fd772 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt @@ -83,7 +83,7 @@ class PeopleNotificationIdentifierImpl @Inject constructor( private val Ranking.personTypeInfo get() = when { - channel.isImportantConversation -> TYPE_IMPORTANT_PERSON + channel?.isImportantConversation == true -> TYPE_IMPORTANT_PERSON isConversation -> TYPE_PERSON else -> TYPE_NON_PERSON } From 055445fee8a96e5fe24289c95a05a1750be381d5 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 13 Mar 2020 04:42:19 +0000 Subject: [PATCH 115/182] Revert "Fix bouncer race condition" This reverts commit 8833d1eb4c75ab8b6ed7712b2ab7ce48307d3f4e. Reason for revert: b/151050221 Fixes: 151050221 Change-Id: I5ad75dae0471a4e87b46e5fc2f95f38bb010c4c0 (cherry picked from commit 20f5049835f4e8e311c85ec0b161c84484a2a007) --- .../keyguard/KeyguardSecurityContainer.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 3cf07d14cbf24..ba8a1a945a777 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -19,9 +19,7 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.ViewRootImpl.sNewInsetsMode; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.systemBars; - import static com.android.systemui.DejankUtils.whitelistIpcs; - import static java.lang.Integer.max; import android.app.Activity; @@ -30,6 +28,7 @@ import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; +import android.graphics.Rect; import android.metrics.LogMaker; import android.os.Handler; import android.os.Looper; @@ -512,8 +511,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe boolean finish = false; boolean strongAuth = false; int eventSubtype = -1; - mCurrentSecuritySelection = whitelistIpcs(() -> - mSecurityModel.getSecurityMode(targetUserId)); if (mUpdateMonitor.getUserHasTrust(targetUserId)) { finish = true; eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS; @@ -521,8 +518,13 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe finish = true; eventSubtype = BOUNCER_DISMISS_BIOMETRIC; } else if (SecurityMode.None == mCurrentSecuritySelection) { - finish = true; // no security required - eventSubtype = BOUNCER_DISMISS_NONE_SECURITY; + SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId); + if (SecurityMode.None == securityMode) { + finish = true; // no security required + eventSubtype = BOUNCER_DISMISS_NONE_SECURITY; + } else { + showSecurityScreen(securityMode); // switch to the alternate security view + } } else if (authenticated) { switch (mCurrentSecuritySelection) { case Pattern: From 3bcc41924676e69d33a271ed731367d1b22e8833 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 16 Mar 2020 18:43:29 +0000 Subject: [PATCH 116/182] Revert "Do not block autofill on waiting for the IME response" This reverts commit 69471c8f155327fe55b4bb7f9db9ac2be454ab17. Reason for revert: Caused a deadlock between AutofillManagerService#mLock and InlineSuggestionsRequestCallbackImpl#mLock. Bug: 150757314 Fix: 151580124 Test: presubmit Change-Id: Ic021facea34cbc34ad5e113790e739ab7f472c1f (cherry picked from commit 949ec8ad6baf5516cbfd27b7e24d0e563c1f42a9) --- .../autofill/InlineSuggestionSession.java | 79 +++++-------- .../com/android/server/autofill/Session.java | 105 ++++-------------- 2 files changed, 51 insertions(+), 133 deletions(-) diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java index 3376f2bd74f58..7fe086df07294 100644 --- a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java +++ b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.os.Bundle; -import android.os.Handler; import android.os.RemoteException; import android.util.Log; import android.util.Slog; @@ -39,8 +38,11 @@ import com.android.server.inputmethod.InputMethodManagerInternal; import java.util.Collections; import java.util.Optional; +import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * Maintains an autofill inline suggestion session that communicates with the IME. @@ -67,7 +69,7 @@ import java.util.function.Consumer; final class InlineSuggestionSession { private static final String TAG = "AfInlineSuggestionSession"; - private static final int INLINE_REQUEST_TIMEOUT_MS = 200; + private static final int INLINE_REQUEST_TIMEOUT_MS = 1000; @NonNull private final InputMethodManagerInternal mInputMethodManagerInternal; @@ -78,8 +80,6 @@ final class InlineSuggestionSession { private final Object mLock; @NonNull private final ImeStatusListener mImeStatusListener; - @NonNull - private final Handler mHandler; /** * To avoid the race condition, one should not access {@code mPendingImeResponse} without @@ -105,11 +105,10 @@ final class InlineSuggestionSession { private boolean mImeInputViewStarted = false; InlineSuggestionSession(InputMethodManagerInternal inputMethodManagerInternal, - int userId, ComponentName componentName, Handler handler) { + int userId, ComponentName componentName) { mInputMethodManagerInternal = inputMethodManagerInternal; mUserId = userId; mComponentName = componentName; - mHandler = handler; mLock = new Object(); mImeStatusListener = new ImeStatusListener() { @Override @@ -138,8 +137,7 @@ final class InlineSuggestionSession { }; } - public void onCreateInlineSuggestionsRequest(@NonNull AutofillId autofillId, - @NonNull Consumer requestConsumer) { + public void onCreateInlineSuggestionsRequest(@NonNull AutofillId autofillId) { if (sDebug) Log.d(TAG, "onCreateInlineSuggestionsRequest called for " + autofillId); synchronized (mLock) { @@ -156,16 +154,26 @@ final class InlineSuggestionSession { mUserId, new InlineSuggestionsRequestInfo(mComponentName, autofillId, new Bundle()), new InlineSuggestionsRequestCallbackImpl(mPendingImeResponse, - mImeStatusListener, requestConsumer, mHandler, mLock)); + mImeStatusListener)); } } - public Optional getInlineSuggestionsRequest() { + public Optional waitAndGetInlineSuggestionsRequest() { final CompletableFuture pendingImeResponse = getPendingImeResponse(); - if (pendingImeResponse == null || !pendingImeResponse.isDone()) { + if (pendingImeResponse == null) { return Optional.empty(); } - return Optional.ofNullable(pendingImeResponse.getNow(null)).map(ImeResponse::getRequest); + try { + return Optional.ofNullable(pendingImeResponse.get(INLINE_REQUEST_TIMEOUT_MS, + TimeUnit.MILLISECONDS)).map(ImeResponse::getRequest); + } catch (TimeoutException e) { + Log.w(TAG, "Exception getting inline suggestions request in time: " + e); + } catch (CancellationException e) { + Log.w(TAG, "Inline suggestions request cancelled"); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + return Optional.empty(); } public boolean hideInlineSuggestionsUi(@NonNull AutofillId autofillId) { @@ -192,7 +200,8 @@ final class InlineSuggestionSession { if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked without IMS request"); return false; } - // There is no need to wait on the CompletableFuture since it should have been completed. + // There is no need to wait on the CompletableFuture since it should have been completed + // when {@link #waitAndGetInlineSuggestionsRequest()} was called. ImeResponse imeResponse = completedImsResponse.getNow(null); if (imeResponse == null) { if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked with pending IMS response"); @@ -240,50 +249,20 @@ final class InlineSuggestionSession { private static final class InlineSuggestionsRequestCallbackImpl extends IInlineSuggestionsRequestCallback.Stub { - private final Object mLock; - @GuardedBy("mLock") private final CompletableFuture mResponse; - @GuardedBy("mLock") - private final Consumer mRequestConsumer; private final ImeStatusListener mImeStatusListener; - private final Handler mHandler; - private final Runnable mTimeoutCallback; private InlineSuggestionsRequestCallbackImpl(CompletableFuture response, - ImeStatusListener imeStatusListener, - Consumer requestConsumer, - Handler handler, Object lock) { + ImeStatusListener imeStatusListener) { mResponse = response; mImeStatusListener = imeStatusListener; - mRequestConsumer = requestConsumer; - mLock = lock; - - mHandler = handler; - mTimeoutCallback = () -> { - Log.w(TAG, "Timed out waiting for IME callback InlineSuggestionsRequest."); - synchronized (mLock) { - completeIfNotLocked(null); - } - }; - mHandler.postDelayed(mTimeoutCallback, INLINE_REQUEST_TIMEOUT_MS); - } - - private void completeIfNotLocked(@Nullable ImeResponse response) { - if (mResponse.isDone()) { - return; - } - mResponse.complete(response); - mRequestConsumer.accept(response == null ? null : response.mRequest); - mHandler.removeCallbacks(mTimeoutCallback); } @BinderThread @Override public void onInlineSuggestionsUnsupported() throws RemoteException { if (sDebug) Log.d(TAG, "onInlineSuggestionsUnsupported() called."); - synchronized (mLock) { - completeIfNotLocked(null); - } + mResponse.complete(null); } @BinderThread @@ -302,13 +281,9 @@ final class InlineSuggestionSession { mImeStatusListener.onInputMethodFinishInputView(imeFieldId); } if (request != null && callback != null) { - synchronized (mLock) { - completeIfNotLocked(new ImeResponse(request, callback)); - } + mResponse.complete(new ImeResponse(request, callback)); } else { - synchronized (mLock) { - completeIfNotLocked(null); - } + mResponse.complete(null); } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 5064663871e3e..9693535e22864 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -114,9 +114,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; /** * A session for a given activity. @@ -309,47 +307,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** * Receiver of assist data from the app's {@link Activity}. */ - private final AssistDataReceiverImpl mAssistReceiver = new AssistDataReceiverImpl(); - - private final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub { - - @GuardedBy("mLock") - private InlineSuggestionsRequest mPendingInlineSuggestionsRequest; - @GuardedBy("mLock") - private FillRequest mPendingFillRequest; - @GuardedBy("mLock") - private CountDownLatch mCountDownLatch; - - @Nullable Consumer newAutofillRequestLocked( - boolean isInlineRequest) { - mCountDownLatch = new CountDownLatch(isInlineRequest ? 2 : 1); - mPendingFillRequest = null; - mPendingInlineSuggestionsRequest = null; - return isInlineRequest ? (inlineSuggestionsRequest) -> { - synchronized (mLock) { - mPendingInlineSuggestionsRequest = inlineSuggestionsRequest; - mCountDownLatch.countDown(); - maybeRequestFillLocked(); - } - } : null; - } - - void maybeRequestFillLocked() { - if (mCountDownLatch == null || mCountDownLatch.getCount() > 0 - || mPendingFillRequest == null) { - return; - } - if (mPendingInlineSuggestionsRequest != null) { - mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(), - mPendingFillRequest.getFillContexts(), mPendingFillRequest.getClientState(), - mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest); - } - mRemoteFillService.onFillRequest(mPendingFillRequest); - mPendingInlineSuggestionsRequest = null; - mPendingFillRequest = null; - mCountDownLatch = null; - } - + private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() { @Override public void onHandleAssistData(Bundle resultData) throws RemoteException { if (mRemoteFillService == null) { @@ -444,17 +402,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final ArrayList contexts = mergePreviousSessionLocked(/* forSave= */ false); - request = new FillRequest(requestId, contexts, mClientState, flags, - /*inlineSuggestionsRequest=*/null); - mPendingFillRequest = request; - mCountDownLatch.countDown(); - maybeRequestFillLocked(); + final Optional inlineSuggestionsRequest = + mInlineSuggestionSession.waitAndGetInlineSuggestionsRequest(); + request = new FillRequest(requestId, contexts, mClientState, flags, + inlineSuggestionsRequest.orElse(null)); } if (mActivityToken != null) { mService.sendActivityAssistDataToContentCapture(mActivityToken, resultData); } + mRemoteFillService.onFillRequest(request); } @Override @@ -647,15 +605,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void maybeRequestInlineSuggestionsRequestThenFillLocked(@NonNull ViewState viewState, int newState, int flags) { if (isInlineSuggestionsEnabledLocked()) { - Consumer inlineSuggestionsRequestConsumer = - mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ true); - if (inlineSuggestionsRequestConsumer != null) { - mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId, - inlineSuggestionsRequestConsumer); - } - } else { - mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ false); + mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId); } + requestNewFillResponseLocked(viewState, newState, flags); } @@ -756,7 +708,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState setClientLocked(client); mInlineSuggestionSession = new InlineSuggestionSession(inputMethodManagerInternal, userId, - componentName, handler); + componentName); mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags)); @@ -2711,7 +2663,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private boolean requestShowInlineSuggestionsLocked(@NonNull FillResponse response, @Nullable String filterText) { final Optional inlineSuggestionsRequest = - mInlineSuggestionSession.getInlineSuggestionsRequest(); + mInlineSuggestionSession.waitAndGetInlineSuggestionsRequest(); if (!inlineSuggestionsRequest.isPresent()) { Log.w(TAG, "InlineSuggestionsRequest unavailable"); return false; @@ -2944,9 +2896,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** * Tries to trigger Augmented Autofill when the standard service could not fulfill a request. * - *

The request may not have been sent when this method returns as it may be waiting for - * the inline suggestion request asynchronously. - * * @return callback to destroy the autofill UI, or {@code null} if not supported. */ // TODO(b/123099468): might need to call it in other places, like when the service returns a @@ -3029,21 +2978,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final AutofillId focusedId = AutofillId.withoutSession(mCurrentViewId); - final Consumer requestAugmentedAutofill = - (inlineSuggestionsRequest) -> { - remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, - focusedId, - currentValue, inlineSuggestionsRequest, - /*inlineSuggestionsCallback=*/ - response -> mInlineSuggestionSession.onInlineSuggestionsResponse( - mCurrentViewId, response), - /*onErrorCallback=*/ () -> { - synchronized (mLock) { - cancelAugmentedAutofillLocked(); - } - }, mService.getRemoteInlineSuggestionRenderServiceLocked()); - }; - // There are 3 cases when augmented autofill should ask IME for a new request: // 1. standard autofill provider is None // 2. standard autofill provider doesn't support inline (and returns null response) @@ -3051,12 +2985,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // doesn't want autofill if (mForAugmentedAutofillOnly || !isInlineSuggestionsEnabledLocked()) { if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill"); - mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId, - /*requestConsumer=*/ requestAugmentedAutofill); - } else { - requestAugmentedAutofill.accept( - mInlineSuggestionSession.getInlineSuggestionsRequest().orElse(null)); + mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId); } + + Optional inlineSuggestionsRequest = + mInlineSuggestionSession.waitAndGetInlineSuggestionsRequest(); + remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, focusedId, + currentValue, inlineSuggestionsRequest.orElse(null), + response -> mInlineSuggestionSession.onInlineSuggestionsResponse( + mCurrentViewId, response), + () -> { + synchronized (mLock) { + cancelAugmentedAutofillLocked(); + } + }, mService.getRemoteInlineSuggestionRenderServiceLocked()); + if (mAugmentedAutofillDestroyer == null) { mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest(); } From a2bdc2c955986ae0d4b5ae55e2b3789403c3903b Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Mon, 16 Mar 2020 13:31:06 -0400 Subject: [PATCH 117/182] Assign a BluetoothAdapter on creation of LMM When constructing a LocalMediaManager by passing a LocalBluetoothManager and a InfoMediaManager, assign the bluetooth adapter to the default. Fixes: 151580099 Fixes: 151622615 Test: atest LocalMediaManagerTest Test: manual Change-Id: I29ac58bc3635901c713e91ab921d59bfbe58fba7 (cherry picked from commit e731634e1fc7644f3e8bfd1c0e9451f12602815c) --- .../settingslib/media/LocalMediaManager.java | 15 +++++++++++++++ .../settingslib/media/LocalMediaManagerTest.java | 1 - 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index 4a0d16c8d2dbe..d6dcb2cc53dd7 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -93,6 +93,15 @@ public class LocalMediaManager implements BluetoothCallback { mCallbacks.remove(callback); } + /** + * Creates a LocalMediaManager with references to given managers. + * + * It will obtain a {@link LocalBluetoothManager} by calling + * {@link LocalBluetoothManager#getInstance} and create an {@link InfoMediaManager} passing + * that bluetooth manager. + * + * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter. + */ public LocalMediaManager(Context context, String packageName, Notification notification) { mContext = context; mPackageName = packageName; @@ -108,12 +117,18 @@ public class LocalMediaManager implements BluetoothCallback { new InfoMediaManager(context, packageName, notification, mLocalBluetoothManager); } + /** + * Creates a LocalMediaManager with references to given managers. + * + * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter. + */ public LocalMediaManager(Context context, LocalBluetoothManager localBluetoothManager, InfoMediaManager infoMediaManager, String packageName) { mContext = context; mLocalBluetoothManager = localBluetoothManager; mInfoMediaManager = infoMediaManager; mPackageName = packageName; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } /** diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java index 18d8f14eb88d7..eea61cb62e7db 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java @@ -91,7 +91,6 @@ public class LocalMediaManagerTest { mLocalMediaManager = new LocalMediaManager(mContext, mLocalBluetoothManager, mInfoMediaManager, "com.test.packagename"); - mLocalMediaManager.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } @Test From cd90d767657c7504ac6cfcfed3e4b8ae06088268 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Mon, 16 Mar 2020 11:59:28 -0700 Subject: [PATCH 118/182] Use the bounds received in taskAppeared The bounds sent with taskVanished not seem to be up-to-dated Bug: 151050577 Test: Manual enter/exit PiP for play movies in gesture nav Change-Id: If875920ee33bb11d164f3e7778319d4ac921ad91 (cherry picked from commit fbc25fe9fa62c01a62050f805e58a388edf057d6) --- .../src/com/android/systemui/pip/PipTaskOrganizer.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 4076c1bbb367e..dc1b5d70089be 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -33,6 +33,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.Rect; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Log; @@ -47,7 +48,9 @@ import com.android.systemui.R; import com.android.systemui.pip.phone.PipUpdateThread; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.Consumer; @@ -79,6 +82,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private final Rect mLastReportedBounds = new Rect(); private final int mEnterExitAnimationDuration; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; + private final Map mBoundsToRestore = new HashMap<>(); // These callbacks are called on the update thread private final PipAnimationController.PipAnimationCallback mPipAnimationCallback = @@ -222,6 +226,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { throw new RuntimeException("Unable to get leash", e); } final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); + mBoundsToRestore.put(mToken.asBinder(), currentBounds); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { scheduleAnimateResizePip(currentBounds, destinationBounds, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null); @@ -246,8 +251,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { Log.wtf(TAG, "Unrecognized token: " + token); return; } - scheduleAnimateResizePip(mLastReportedBounds, - info.configuration.windowConfiguration.getBounds(), + final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder()); + scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore, TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null); mInPip = false; } From 5af2ed98c7610ff4d2c48afd052502c2464ccf27 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Mon, 16 Mar 2020 13:31:06 -0400 Subject: [PATCH 119/182] Assign a BluetoothAdapter on creation of LMM When constructing a LocalMediaManager by passing a LocalBluetoothManager and a InfoMediaManager, assign the bluetooth adapter to the default. Fixes: 151580099 Fixes: 151622615 Test: atest LocalMediaManagerTest Test: manual Change-Id: I29ac58bc3635901c713e91ab921d59bfbe58fba7 (cherry picked from commit e731634e1fc7644f3e8bfd1c0e9451f12602815c) --- .../settingslib/media/LocalMediaManager.java | 15 +++++++++++++++ .../settingslib/media/LocalMediaManagerTest.java | 1 - 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index 44b481dea77dd..9ae9b4a462277 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -95,6 +95,15 @@ public class LocalMediaManager implements BluetoothCallback { mCallbacks.remove(callback); } + /** + * Creates a LocalMediaManager with references to given managers. + * + * It will obtain a {@link LocalBluetoothManager} by calling + * {@link LocalBluetoothManager#getInstance} and create an {@link InfoMediaManager} passing + * that bluetooth manager. + * + * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter. + */ public LocalMediaManager(Context context, String packageName, Notification notification) { mContext = context; mPackageName = packageName; @@ -110,12 +119,18 @@ public class LocalMediaManager implements BluetoothCallback { new InfoMediaManager(context, packageName, notification, mLocalBluetoothManager); } + /** + * Creates a LocalMediaManager with references to given managers. + * + * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter. + */ public LocalMediaManager(Context context, LocalBluetoothManager localBluetoothManager, InfoMediaManager infoMediaManager, String packageName) { mContext = context; mLocalBluetoothManager = localBluetoothManager; mInfoMediaManager = infoMediaManager; mPackageName = packageName; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } /** diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java index f825ec520d490..559187d2c38ce 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java @@ -113,7 +113,6 @@ public class LocalMediaManagerTest { TEST_PACKAGE_NAME); mLocalMediaManager = new LocalMediaManager(mContext, mLocalBluetoothManager, mInfoMediaManager, "com.test.packagename"); - mLocalMediaManager.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } @Test From 02d879f4b4e0d90ae5a531be055462d9f30ae03e Mon Sep 17 00:00:00 2001 From: Nick Moukhine Date: Mon, 16 Mar 2020 17:51:37 +0100 Subject: [PATCH 120/182] Use BIND_INCLUDE_CAPABILITIES for SoundTriggerService SoundTriggerService is used by Now Playing to read DSP audio. Now that audio permissions are gated on process capability, we need this flag for system server to pass on its capability during the bind. With the new capability, permissions will no longer be denied. Bug: 150508177 Fixes: 150508177 Test: todo Change-Id: I79a18a9c98e5f36000f329bf15ca5a5f73826ffe (cherry picked from commit 67b5e387b5d5af90a3be266a37282073b5f84fdd) --- .../com/android/server/soundtrigger/SoundTriggerService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java index 767010ae821a3..3196758996be7 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java @@ -19,6 +19,7 @@ package com.android.server.soundtrigger; import static android.Manifest.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE; import static android.content.Context.BIND_AUTO_CREATE; import static android.content.Context.BIND_FOREGROUND_SERVICE; +import static android.content.Context.BIND_INCLUDE_CAPABILITIES; import static android.content.pm.PackageManager.GET_META_DATA; import static android.content.pm.PackageManager.GET_SERVICES; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; @@ -1133,7 +1134,8 @@ public class SoundTriggerService extends SystemService { } mIsBound = mContext.bindServiceAsUser(i, this, - BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE, mUser); + BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_INCLUDE_CAPABILITIES, + mUser); if (mIsBound) { mRemoteServiceWakeLock.acquire(); From 5ac5d7143daaef499b46acd2030092465bc6add1 Mon Sep 17 00:00:00 2001 From: arangelov Date: Wed, 18 Mar 2020 20:24:03 +0000 Subject: [PATCH 121/182] Call setAdapter from handleLayoutChanged. Test: manual Fixes: 150918223 Fixes: 150922090 Fixes: 151329221 Fixes: 151077241 Change-Id: I723634840cfdc40eb307f2ce4e170178692f12f3 (cherry picked from commit 2731fa71fe68b862f476eac6c93f9503c695706b) --- .../android/internal/app/ChooserActivity.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 78a0ae0907ff6..a1a434d3bc642 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -2418,13 +2418,20 @@ public class ChooserActivity extends ResolverActivity implements if (isLayoutUpdated || mLastNumberOfChildren != recyclerView.getChildCount()) { mCurrAvailableWidth = availableWidth; - if (isLayoutUpdated - && mChooserMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { - // This fixes b/150936654 - empty work tab in share sheet when swiping - mChooserMultiProfilePagerAdapter.getActiveAdapterView() - .setAdapter(mChooserMultiProfilePagerAdapter.getCurrentRootAdapter()); + if (isLayoutUpdated) { + // It is very important we call setAdapter from here. Otherwise in some cases + // the resolver list doesn't get populated, such as b/150922090, b/150918223 + // and b/150936654 + recyclerView.setAdapter(gridAdapter); + ((GridLayoutManager) recyclerView.getLayoutManager()).setSpanCount( + gridAdapter.getMaxTargetsPerRow()); + } + + if (mChooserMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { return; - } else if (mChooserMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { + } + + if (mLastNumberOfChildren == recyclerView.getChildCount()) { return; } From c97a1dd66efcd0d2459348f87c222f8ddf86b1e6 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Thu, 19 Mar 2020 22:28:43 +0800 Subject: [PATCH 122/182] Make canBeImeTarget be compatible with legacy behavior And let PerDisplay can adjust animation parameters while the insets source control is changed during animation. Fix: 151759336 Test: atest WindowStateTests Change-Id: Ic2a308e6b7ec39b4b8645751e31addd26ddf3735 (cherry picked from commit 00b9d6ed3c4982026522c4396653b8237e5447a8) --- .../systemui/wm/DisplayImeController.java | 51 +++++++++++++------ .../server/wm/InsetsSourceProvider.java | 6 ++- .../com/android/server/wm/WindowState.java | 8 +-- .../android/server/wm/WindowStateTests.java | 2 - 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java index 54118390325cc..16feaadb92c6e 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java @@ -177,6 +177,23 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged int mRotation = Surface.ROTATION_0; boolean mImeShowing = false; + private float mX; + private float mHiddenY; + private float mShownY; + private float mStartY; + private float mEndY; + + private final Runnable mUpdateAnimationParams = () -> { + final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME); + final boolean show = mAnimationDirection == DIRECTION_SHOW; + final float defaultY = mImeSourceControl.getSurfacePosition().y; + mX = mImeSourceControl.getSurfacePosition().x; + mHiddenY = defaultY + imeSource.getFrame().height(); + mShownY = defaultY; + mStartY = show ? mHiddenY : mShownY; + mEndY = show ? mShownY : mHiddenY; + }; + PerDisplay(int displayId, int initialRotation) { mDisplayId = displayId; mRotation = initialRotation; @@ -200,7 +217,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; } if (activeControl.getType() == InsetsState.ITYPE_IME) { - mImeSourceControl = activeControl; + if (mImeSourceControl != activeControl) { + mImeSourceControl = activeControl; + mHandler.post(mUpdateAnimationParams); + } } } } @@ -265,28 +285,28 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE; final float defaultY = mImeSourceControl.getSurfacePosition().y; - final float x = mImeSourceControl.getSurfacePosition().x; - final float hiddenY = defaultY + imeSource.getFrame().height(); - final float shownY = defaultY; - final float startY = show ? hiddenY : shownY; - final float endY = show ? shownY : hiddenY; + mX = mImeSourceControl.getSurfacePosition().x; + mHiddenY = defaultY + imeSource.getFrame().height(); + mShownY = defaultY; + mStartY = show ? mHiddenY : mShownY; + mEndY = show ? mShownY : mHiddenY; if (mImeShowing && show) { // IME is already showing, so set seek to end - seekValue = shownY; + seekValue = mShownY; seek = true; } mImeShowing = show; - mAnimation = ValueAnimator.ofFloat(startY, endY); + mAnimation = ValueAnimator.ofFloat(mStartY, mEndY); mAnimation.setDuration( show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS); if (seek) { - mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY)); + mAnimation.setCurrentFraction((seekValue - mStartY) / (mEndY - mStartY)); } mAnimation.addUpdateListener(animation -> { SurfaceControl.Transaction t = mTransactionPool.acquire(); float value = (float) animation.getAnimatedValue(); - t.setPosition(mImeSourceControl.getLeash(), x, value); + t.setPosition(mImeSourceControl.getLeash(), mX, value); dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t); t.apply(); mTransactionPool.release(t); @@ -297,14 +317,15 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged @Override public void onAnimationStart(Animator animation) { SurfaceControl.Transaction t = mTransactionPool.acquire(); - t.setPosition(mImeSourceControl.getLeash(), x, startY); + t.setPosition(mImeSourceControl.getLeash(), mX, mStartY); if (DEBUG) { Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:" - + imeTop(imeSource, hiddenY) + "->" + imeTop(imeSource, shownY) + + imeTop(imeSource, mHiddenY) + "->" + + imeTop(imeSource, mShownY) + " showing:" + (mAnimationDirection == DIRECTION_SHOW)); } - dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY), - imeTop(imeSource, shownY), mAnimationDirection == DIRECTION_SHOW, + dispatchStartPositioning(mDisplayId, imeTop(imeSource, mHiddenY), + imeTop(imeSource, mShownY), mAnimationDirection == DIRECTION_SHOW, t); if (mAnimationDirection == DIRECTION_SHOW) { t.show(mImeSourceControl.getLeash()); @@ -321,7 +342,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled); SurfaceControl.Transaction t = mTransactionPool.acquire(); if (!mCancelled) { - t.setPosition(mImeSourceControl.getLeash(), x, endY); + t.setPosition(mImeSourceControl.getLeash(), mX, mEndY); } dispatchEndPositioning(mDisplayId, mCancelled, t); if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index ada6d47109675..85361f10f3335 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -215,7 +215,11 @@ class InsetsSourceProvider { final Rect frame = mWin.getWindowFrames().mFrame; if (mControl.setSurfacePosition(frame.left, frame.top) && mControlTarget != null) { // The leash has been stale, we need to create a new one for the client. - updateControlForTarget(mControlTarget, true /* force */); + if (mControlTarget != mDisplayContent.mRemoteInsetsControlTarget) { + // Hacky: recreating leash for RemoteInsetsControlTarget might cause IME + // flicker, so we just report the new surface position to it. + updateControlForTarget(mControlTarget, true /* force */); + } mStateController.notifyControlChanged(mControlTarget); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 36175705b8486..520a15b8f9ab3 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -131,6 +131,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; @@ -138,7 +139,6 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; -import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; @@ -2270,9 +2270,9 @@ class WindowState extends WindowContainer implements WindowManagerP return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { - // Support legacy use cases where completely transparent windows can still be ime target - // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format)) { + // Support legacy use cases where transparent windows can still be ime target with + // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 85e4a1668a352..e95ccab38960e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,11 +251,9 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; - appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; - appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; From ddb7ff934dad66aa6880bdfbfb461ca23780ca87 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Thu, 19 Mar 2020 14:19:57 -0700 Subject: [PATCH 123/182] Fixes query logic when not instant What should have been the final branch of an if / else if sequence was broken from it and so VISIBLE_TO_INSTANT activities were being made visible to normal packages targetting R. This change fixes that. Fixes: 151696596 Test: atest AppEnumerationTests Change-Id: I8e60c52a1e917d56d2714fed049788439bd2acc6 (cherry picked from commit b08116e96162040adb35133cd46c0440ce81215c) --- .../com/android/server/pm/PackageManagerService.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 09e4e602bbd78..89e245cd8568a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7238,8 +7238,8 @@ public class PackageManagerService extends IPackageManager.Stub resolveInfos.set(i, installerInfo); continue; } - // caller is a full app if (ephemeralPkgName == null) { + // caller is a full app SettingBase callingSetting = mSettings.getSettingLPr(UserHandle.getAppId(filterCallingUid)); PackageSetting resolvedSetting = @@ -7259,11 +7259,9 @@ public class PackageManagerService extends IPackageManager.Stub && intent.getComponent() == null) { // ephemeral apps can launch other ephemeral apps indirectly continue; - } - // allow activities that have been explicitly exposed to ephemeral apps - final boolean isEphemeralApp = info.activityInfo.applicationInfo.isInstantApp(); - if (!isEphemeralApp - && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) { + } else if (((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0) + && !info.activityInfo.applicationInfo.isInstantApp()) { + // allow activities that have been explicitly exposed to ephemeral apps continue; } resolveInfos.remove(i); From 676b601751f5476640fe087802d202aea56426bb Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Thu, 19 Mar 2020 14:19:57 -0700 Subject: [PATCH 124/182] Fixes query logic when not instant What should have been the final branch of an if / else if sequence was broken from it and so VISIBLE_TO_INSTANT activities were being made visible to normal packages targetting R. This change fixes that. Fixes: 151696596 Test: atest AppEnumerationTests Change-Id: I8e60c52a1e917d56d2714fed049788439bd2acc6 (cherry picked from commit b08116e96162040adb35133cd46c0440ce81215c) --- .../com/android/server/pm/PackageManagerService.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 09e4e602bbd78..89e245cd8568a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7238,8 +7238,8 @@ public class PackageManagerService extends IPackageManager.Stub resolveInfos.set(i, installerInfo); continue; } - // caller is a full app if (ephemeralPkgName == null) { + // caller is a full app SettingBase callingSetting = mSettings.getSettingLPr(UserHandle.getAppId(filterCallingUid)); PackageSetting resolvedSetting = @@ -7259,11 +7259,9 @@ public class PackageManagerService extends IPackageManager.Stub && intent.getComponent() == null) { // ephemeral apps can launch other ephemeral apps indirectly continue; - } - // allow activities that have been explicitly exposed to ephemeral apps - final boolean isEphemeralApp = info.activityInfo.applicationInfo.isInstantApp(); - if (!isEphemeralApp - && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) { + } else if (((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0) + && !info.activityInfo.applicationInfo.isInstantApp()) { + // allow activities that have been explicitly exposed to ephemeral apps continue; } resolveInfos.remove(i); From 6180ef8af7b7bbf4ae20bdd33bf02b03a197cc8e Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Thu, 19 Mar 2020 22:28:43 +0800 Subject: [PATCH 125/182] Make canBeImeTarget be compatible with legacy behavior And let PerDisplay can adjust animation parameters while the insets source control is changed during animation. Fix: 151759336 Test: atest WindowStateTests Change-Id: Ic2a308e6b7ec39b4b8645751e31addd26ddf3735 (cherry picked from commit 00b9d6ed3c4982026522c4396653b8237e5447a8) --- .../systemui/wm/DisplayImeController.java | 51 +++++++++++++------ .../server/wm/InsetsSourceProvider.java | 6 ++- .../com/android/server/wm/WindowState.java | 8 +-- .../android/server/wm/WindowStateTests.java | 2 - 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java index 54118390325cc..16feaadb92c6e 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java @@ -177,6 +177,23 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged int mRotation = Surface.ROTATION_0; boolean mImeShowing = false; + private float mX; + private float mHiddenY; + private float mShownY; + private float mStartY; + private float mEndY; + + private final Runnable mUpdateAnimationParams = () -> { + final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME); + final boolean show = mAnimationDirection == DIRECTION_SHOW; + final float defaultY = mImeSourceControl.getSurfacePosition().y; + mX = mImeSourceControl.getSurfacePosition().x; + mHiddenY = defaultY + imeSource.getFrame().height(); + mShownY = defaultY; + mStartY = show ? mHiddenY : mShownY; + mEndY = show ? mShownY : mHiddenY; + }; + PerDisplay(int displayId, int initialRotation) { mDisplayId = displayId; mRotation = initialRotation; @@ -200,7 +217,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; } if (activeControl.getType() == InsetsState.ITYPE_IME) { - mImeSourceControl = activeControl; + if (mImeSourceControl != activeControl) { + mImeSourceControl = activeControl; + mHandler.post(mUpdateAnimationParams); + } } } } @@ -265,28 +285,28 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE; final float defaultY = mImeSourceControl.getSurfacePosition().y; - final float x = mImeSourceControl.getSurfacePosition().x; - final float hiddenY = defaultY + imeSource.getFrame().height(); - final float shownY = defaultY; - final float startY = show ? hiddenY : shownY; - final float endY = show ? shownY : hiddenY; + mX = mImeSourceControl.getSurfacePosition().x; + mHiddenY = defaultY + imeSource.getFrame().height(); + mShownY = defaultY; + mStartY = show ? mHiddenY : mShownY; + mEndY = show ? mShownY : mHiddenY; if (mImeShowing && show) { // IME is already showing, so set seek to end - seekValue = shownY; + seekValue = mShownY; seek = true; } mImeShowing = show; - mAnimation = ValueAnimator.ofFloat(startY, endY); + mAnimation = ValueAnimator.ofFloat(mStartY, mEndY); mAnimation.setDuration( show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS); if (seek) { - mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY)); + mAnimation.setCurrentFraction((seekValue - mStartY) / (mEndY - mStartY)); } mAnimation.addUpdateListener(animation -> { SurfaceControl.Transaction t = mTransactionPool.acquire(); float value = (float) animation.getAnimatedValue(); - t.setPosition(mImeSourceControl.getLeash(), x, value); + t.setPosition(mImeSourceControl.getLeash(), mX, value); dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t); t.apply(); mTransactionPool.release(t); @@ -297,14 +317,15 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged @Override public void onAnimationStart(Animator animation) { SurfaceControl.Transaction t = mTransactionPool.acquire(); - t.setPosition(mImeSourceControl.getLeash(), x, startY); + t.setPosition(mImeSourceControl.getLeash(), mX, mStartY); if (DEBUG) { Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:" - + imeTop(imeSource, hiddenY) + "->" + imeTop(imeSource, shownY) + + imeTop(imeSource, mHiddenY) + "->" + + imeTop(imeSource, mShownY) + " showing:" + (mAnimationDirection == DIRECTION_SHOW)); } - dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY), - imeTop(imeSource, shownY), mAnimationDirection == DIRECTION_SHOW, + dispatchStartPositioning(mDisplayId, imeTop(imeSource, mHiddenY), + imeTop(imeSource, mShownY), mAnimationDirection == DIRECTION_SHOW, t); if (mAnimationDirection == DIRECTION_SHOW) { t.show(mImeSourceControl.getLeash()); @@ -321,7 +342,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled); SurfaceControl.Transaction t = mTransactionPool.acquire(); if (!mCancelled) { - t.setPosition(mImeSourceControl.getLeash(), x, endY); + t.setPosition(mImeSourceControl.getLeash(), mX, mEndY); } dispatchEndPositioning(mDisplayId, mCancelled, t); if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index ada6d47109675..85361f10f3335 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -215,7 +215,11 @@ class InsetsSourceProvider { final Rect frame = mWin.getWindowFrames().mFrame; if (mControl.setSurfacePosition(frame.left, frame.top) && mControlTarget != null) { // The leash has been stale, we need to create a new one for the client. - updateControlForTarget(mControlTarget, true /* force */); + if (mControlTarget != mDisplayContent.mRemoteInsetsControlTarget) { + // Hacky: recreating leash for RemoteInsetsControlTarget might cause IME + // flicker, so we just report the new surface position to it. + updateControlForTarget(mControlTarget, true /* force */); + } mStateController.notifyControlChanged(mControlTarget); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 36175705b8486..520a15b8f9ab3 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -131,6 +131,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; @@ -138,7 +139,6 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; -import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; @@ -2270,9 +2270,9 @@ class WindowState extends WindowContainer implements WindowManagerP return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { - // Support legacy use cases where completely transparent windows can still be ime target - // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format)) { + // Support legacy use cases where transparent windows can still be ime target with + // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 85e4a1668a352..e95ccab38960e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,11 +251,9 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; - appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; - appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; From 00d8f1fe5a44cf7658ed15d7dfde4a29d3864faa Mon Sep 17 00:00:00 2001 From: Nicholas Ambur Date: Thu, 19 Mar 2020 21:01:31 -0700 Subject: [PATCH 126/182] add KEYPHRASE_ENROLLMENT_APPLICATION permission Split the model management permission controll into two separate permissions. KEYPHRASE_ENROLLMENT_APPLICATION is reserved for enrollment applications detected by KeyphraseEnrollmentInfo class while MANAGE_VOICE_KEYPHRASES is reserved for VoiceInteractionService implementations. Keyphrase enrollment applications are allowed to enroll at anytime, and VoiceInteractionService implementations are only allowed to enroll when they are the active service (see VoiceInteractionManagerService). Bug: 151405284 Test: Enroll voice model from both enrollment application and active voiceinteraction service. Change-Id: I12eeb09e308af9aa934174dd059f47f789a9ce39 Change-Id: Iffdfeab1d09ec6c8cf4b30a9768ef6efc9bdfa01 (cherry picked from commit 5a207846e63842fed0bd4f7c419951799ea5f4f7) --- core/res/AndroidManifest.xml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1f2f5691fcdb1..4c2e56cbb589a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3447,12 +3447,25 @@ - + + + + From 94c8b2175831d8d6e758c44b5a24dcfed17e2a2b Mon Sep 17 00:00:00 2001 From: Nicholas Ambur Date: Thu, 19 Mar 2020 21:16:10 -0700 Subject: [PATCH 127/182] fix enrollment application permission check Remove check associated with enrollment application UID, and allow enrollment applications holding the KEYPHRASE_ENROLLMENT_APPLICATION privledged permission to enroll. Bug: 151405284 Test: Confirm enrollment from both enrollment application and active voiceinteraction service. Confirm enrollment can still occurr after system user switch. Change-Id: I8686f705fe5405523004eef5de834282a7382464 (cherry picked from commit 55603081c1db07a802ef407c7749fefab03af577) --- .../soundtrigger/KeyphraseEnrollmentInfo.java | 21 --------- .../VoiceInteractionManagerService.java | 45 +++++-------------- 2 files changed, 11 insertions(+), 55 deletions(-) diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java index 1aeb76a396b44..05935452e8abd 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java @@ -43,7 +43,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; /** * Enrollment information about the different available keyphrases. @@ -119,11 +118,6 @@ public class KeyphraseEnrollmentInfo { */ private final KeyphraseMetadata[] mKeyphrases; - /** - * Set of UIDs associated with the detected enrollment applications. - */ - private final Set mEnrollmentApplicationUids; - /** * Map between KeyphraseMetadata and the package name of the enrollment app that provides it. */ @@ -142,13 +136,11 @@ public class KeyphraseEnrollmentInfo { mParseError = "No enrollment applications found"; mKeyphrasePackageMap = Collections.emptyMap(); mKeyphrases = null; - mEnrollmentApplicationUids = Collections.emptySet(); return; } List parseErrors = new LinkedList(); mKeyphrasePackageMap = new HashMap(); - mEnrollmentApplicationUids = new ArraySet<>(); for (ResolveInfo ri : ris) { try { ApplicationInfo ai = pm.getApplicationInfo( @@ -170,7 +162,6 @@ public class KeyphraseEnrollmentInfo { getKeyphraseMetadataFromApplicationInfo(pm, ai, parseErrors); if (metadata != null) { mKeyphrasePackageMap.put(metadata, ai.packageName); - mEnrollmentApplicationUids.add(ai.uid); } } catch (PackageManager.NameNotFoundException e) { String error = "error parsing voice enrollment meta-data for " @@ -373,21 +364,9 @@ public class KeyphraseEnrollmentInfo { return null; } - /** - * Tests if the input UID matches a supported enrollment application. - * - * @param uid UID of the caller to test against. - * @return Returns true if input uid matches the uid of a supported enrollment application. - * False if not. - */ - public boolean isUidSupportedEnrollmentApplication(int uid) { - return mEnrollmentApplicationUids.contains(uid); - } - @Override public String toString() { return "KeyphraseEnrollmentInfo [KeyphrasePackageMap=" + mKeyphrasePackageMap.toString() - + ", enrollmentApplicationUids=" + mEnrollmentApplicationUids.toString() + ", ParseError=" + mParseError + "]"; } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 0eba07b118b54..70c7d50909761 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -41,7 +41,6 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.soundtrigger.IRecognitionStatusCallback; -import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.ModelParams; import android.hardware.soundtrigger.SoundTrigger; @@ -100,7 +99,7 @@ import java.util.concurrent.Executor; * SystemService that publishes an IVoiceInteractionManagerService. */ public class VoiceInteractionManagerService extends SystemService { - static final String TAG = "VoiceInteractionManagerService"; + static final String TAG = "VoiceInteractionManager"; static final boolean DEBUG = false; final Context mContext; @@ -172,17 +171,17 @@ public class VoiceInteractionManagerService extends SystemService { } @Override - public void onStartUser(@NonNull UserInfo userInfo) { - if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")"); + public void onUserStarting(@NonNull TargetUser user) { + if (DEBUG_USER) Slog.d(TAG, "onUserStarting(" + user + ")"); - mServiceStub.initForUser(userInfo.id); + mServiceStub.initForUser(user.getUserIdentifier()); } @Override - public void onUnlockUser(@NonNull UserInfo userInfo) { - if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); + public void onUserUnlocking(@NonNull TargetUser user) { + if (DEBUG_USER) Slog.d(TAG, "onUserUnlocking(" + user + ")"); - mServiceStub.initForUser(userInfo.id); + mServiceStub.initForUser(user.getUserIdentifier()); mServiceStub.switchImplementationIfNeeded(false); } @@ -224,7 +223,6 @@ public class VoiceInteractionManagerService extends SystemService { class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub { VoiceInteractionManagerServiceImpl mImpl; - KeyphraseEnrollmentInfo mEnrollmentApplicationInfo; private boolean mSafeMode; private int mCurUser; @@ -449,15 +447,6 @@ public class VoiceInteractionManagerService extends SystemService { } } - private void getOrCreateEnrollmentApplicationInfo() { - synchronized (this) { - if (mEnrollmentApplicationInfo == null) { - mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo( - mContext.getPackageManager()); - } - } - } - private void setCurrentUserLocked(@UserIdInt int userHandle) { mCurUser = userHandle; final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); @@ -1391,11 +1380,6 @@ public class VoiceInteractionManagerService extends SystemService { pw.println(" mCurUserUnlocked: " + mCurUserUnlocked); pw.println(" mCurUserSupported: " + mCurUserSupported); dumpSupportedUsers(pw, " "); - if (mEnrollmentApplicationInfo == null) { - pw.println(" (No enrollment application info)"); - } else { - pw.println(" " + mEnrollmentApplicationInfo.toString()); - } mDbHelper.dump(pw); if (mImpl == null) { pw.println(" (No active implementation)"); @@ -1440,11 +1424,10 @@ public class VoiceInteractionManagerService extends SystemService { } private void enforceCallerAllowedToEnrollVoiceModel() { - enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES); - if (!isCallerCurrentVoiceInteractionService() - && !isCallerTrustedEnrollmentApplication()) { - throw new SecurityException("Caller is required to be the current voice interaction" - + " service or a system enrollment application to enroll voice models"); + if (isCallerCurrentVoiceInteractionService()) { + enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES); + } else { + enforceCallingPermission(Manifest.permission.KEYPHRASE_ENROLLMENT_APPLICATION); } } @@ -1453,12 +1436,6 @@ public class VoiceInteractionManagerService extends SystemService { && mImpl.mInfo.getServiceInfo().applicationInfo.uid == Binder.getCallingUid(); } - private boolean isCallerTrustedEnrollmentApplication() { - getOrCreateEnrollmentApplicationInfo(); - return mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication( - Binder.getCallingUid()); - } - private void setImplLocked(VoiceInteractionManagerServiceImpl impl) { mImpl = impl; mAtmInternal.notifyActiveVoiceInteractionServiceChanged( From 31667b7d7fc565e41c7bc880e789f9861ebb13b5 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Thu, 19 Mar 2020 22:28:43 +0800 Subject: [PATCH 128/182] Make canBeImeTarget be compatible with legacy behavior And let PerDisplay can adjust animation parameters while the insets source control is changed during animation. Fix: 151759336 Test: atest WindowStateTests Change-Id: Ic2a308e6b7ec39b4b8645751e31addd26ddf3735 (cherry picked from commit 00b9d6ed3c4982026522c4396653b8237e5447a8) --- .../systemui/wm/DisplayImeController.java | 51 +++++++++++++------ .../server/wm/InsetsSourceProvider.java | 6 ++- .../com/android/server/wm/WindowState.java | 8 +-- .../android/server/wm/WindowStateTests.java | 2 - 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java index 54118390325cc..16feaadb92c6e 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java @@ -177,6 +177,23 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged int mRotation = Surface.ROTATION_0; boolean mImeShowing = false; + private float mX; + private float mHiddenY; + private float mShownY; + private float mStartY; + private float mEndY; + + private final Runnable mUpdateAnimationParams = () -> { + final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME); + final boolean show = mAnimationDirection == DIRECTION_SHOW; + final float defaultY = mImeSourceControl.getSurfacePosition().y; + mX = mImeSourceControl.getSurfacePosition().x; + mHiddenY = defaultY + imeSource.getFrame().height(); + mShownY = defaultY; + mStartY = show ? mHiddenY : mShownY; + mEndY = show ? mShownY : mHiddenY; + }; + PerDisplay(int displayId, int initialRotation) { mDisplayId = displayId; mRotation = initialRotation; @@ -200,7 +217,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; } if (activeControl.getType() == InsetsState.ITYPE_IME) { - mImeSourceControl = activeControl; + if (mImeSourceControl != activeControl) { + mImeSourceControl = activeControl; + mHandler.post(mUpdateAnimationParams); + } } } } @@ -265,28 +285,28 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE; final float defaultY = mImeSourceControl.getSurfacePosition().y; - final float x = mImeSourceControl.getSurfacePosition().x; - final float hiddenY = defaultY + imeSource.getFrame().height(); - final float shownY = defaultY; - final float startY = show ? hiddenY : shownY; - final float endY = show ? shownY : hiddenY; + mX = mImeSourceControl.getSurfacePosition().x; + mHiddenY = defaultY + imeSource.getFrame().height(); + mShownY = defaultY; + mStartY = show ? mHiddenY : mShownY; + mEndY = show ? mShownY : mHiddenY; if (mImeShowing && show) { // IME is already showing, so set seek to end - seekValue = shownY; + seekValue = mShownY; seek = true; } mImeShowing = show; - mAnimation = ValueAnimator.ofFloat(startY, endY); + mAnimation = ValueAnimator.ofFloat(mStartY, mEndY); mAnimation.setDuration( show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS); if (seek) { - mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY)); + mAnimation.setCurrentFraction((seekValue - mStartY) / (mEndY - mStartY)); } mAnimation.addUpdateListener(animation -> { SurfaceControl.Transaction t = mTransactionPool.acquire(); float value = (float) animation.getAnimatedValue(); - t.setPosition(mImeSourceControl.getLeash(), x, value); + t.setPosition(mImeSourceControl.getLeash(), mX, value); dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t); t.apply(); mTransactionPool.release(t); @@ -297,14 +317,15 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged @Override public void onAnimationStart(Animator animation) { SurfaceControl.Transaction t = mTransactionPool.acquire(); - t.setPosition(mImeSourceControl.getLeash(), x, startY); + t.setPosition(mImeSourceControl.getLeash(), mX, mStartY); if (DEBUG) { Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:" - + imeTop(imeSource, hiddenY) + "->" + imeTop(imeSource, shownY) + + imeTop(imeSource, mHiddenY) + "->" + + imeTop(imeSource, mShownY) + " showing:" + (mAnimationDirection == DIRECTION_SHOW)); } - dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY), - imeTop(imeSource, shownY), mAnimationDirection == DIRECTION_SHOW, + dispatchStartPositioning(mDisplayId, imeTop(imeSource, mHiddenY), + imeTop(imeSource, mShownY), mAnimationDirection == DIRECTION_SHOW, t); if (mAnimationDirection == DIRECTION_SHOW) { t.show(mImeSourceControl.getLeash()); @@ -321,7 +342,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled); SurfaceControl.Transaction t = mTransactionPool.acquire(); if (!mCancelled) { - t.setPosition(mImeSourceControl.getLeash(), x, endY); + t.setPosition(mImeSourceControl.getLeash(), mX, mEndY); } dispatchEndPositioning(mDisplayId, mCancelled, t); if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index ada6d47109675..85361f10f3335 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -215,7 +215,11 @@ class InsetsSourceProvider { final Rect frame = mWin.getWindowFrames().mFrame; if (mControl.setSurfacePosition(frame.left, frame.top) && mControlTarget != null) { // The leash has been stale, we need to create a new one for the client. - updateControlForTarget(mControlTarget, true /* force */); + if (mControlTarget != mDisplayContent.mRemoteInsetsControlTarget) { + // Hacky: recreating leash for RemoteInsetsControlTarget might cause IME + // flicker, so we just report the new surface position to it. + updateControlForTarget(mControlTarget, true /* force */); + } mStateController.notifyControlChanged(mControlTarget); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 36175705b8486..520a15b8f9ab3 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -131,6 +131,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; @@ -138,7 +139,6 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; -import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; @@ -2270,9 +2270,9 @@ class WindowState extends WindowContainer implements WindowManagerP return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { - // Support legacy use cases where completely transparent windows can still be ime target - // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format)) { + // Support legacy use cases where transparent windows can still be ime target with + // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 85e4a1668a352..e95ccab38960e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,11 +251,9 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; - appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; - appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; From e5b7db3d90879608c7894cabd435ea6da684875f Mon Sep 17 00:00:00 2001 From: bsears Date: Sun, 22 Mar 2020 16:30:19 +0000 Subject: [PATCH 129/182] Revert "Don't override activity display adjustments with app config" Revert "Verify reported display sizes in multi-window" Revert submission 10636794-app_config_updates_adjustments-rvc-dev Reason for revert: See b/151903752#comment29. This CL was identified (via bisection) as the CL that is breaking Android Auto. Reverted Changes: Ib3ee007bc:Don't override activity display adjustments with a... I5ba4dd354:Verify reported display sizes in multi-window Bug: 151903752 Change-Id: I845ed4871637d6d8a5fac1a6a5236378829b837e (cherry picked from commit 558f025f4d01f65df5528bafbb02f9927d8bd750) --- core/java/android/app/ResourcesManager.java | 47 +++++++++++++--- .../app/activity/ActivityThreadTest.java | 55 ------------------- 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 495bb6b437185..5f756033390b8 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -250,6 +250,28 @@ public class ResourcesManager { return dm; } + private static void applyNonDefaultDisplayMetricsToConfiguration( + @NonNull DisplayMetrics dm, @NonNull Configuration config) { + config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; + config.densityDpi = dm.densityDpi; + config.screenWidthDp = (int) (dm.widthPixels / dm.density); + config.screenHeightDp = (int) (dm.heightPixels / dm.density); + int sl = Configuration.resetScreenLayout(config.screenLayout); + if (dm.widthPixels > dm.heightPixels) { + config.orientation = Configuration.ORIENTATION_LANDSCAPE; + config.screenLayout = Configuration.reduceScreenLayout(sl, + config.screenWidthDp, config.screenHeightDp); + } else { + config.orientation = Configuration.ORIENTATION_PORTRAIT; + config.screenLayout = Configuration.reduceScreenLayout(sl, + config.screenHeightDp, config.screenWidthDp); + } + config.smallestScreenWidthDp = Math.min(config.screenWidthDp, config.screenHeightDp); + config.compatScreenWidthDp = config.screenWidthDp; + config.compatScreenHeightDp = config.screenHeightDp; + config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp; + } + public boolean applyCompatConfigurationLocked(int displayDensity, @NonNull Configuration compatConfiguration) { if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) { @@ -496,11 +518,17 @@ public class ResourcesManager { private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) { Configuration config; + final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY); final boolean hasOverrideConfig = key.hasOverrideConfiguration(); - if (hasOverrideConfig) { + if (!isDefaultDisplay || hasOverrideConfig) { config = new Configuration(getConfiguration()); - config.updateFrom(key.mOverrideConfiguration); - if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration); + if (!isDefaultDisplay) { + applyNonDefaultDisplayMetricsToConfiguration(dm, config); + } + if (hasOverrideConfig) { + config.updateFrom(key.mOverrideConfiguration); + if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration); + } } else { config = getConfiguration(); } @@ -1081,6 +1109,8 @@ public class ResourcesManager { + resourcesImpl + " config to: " + config); } int displayId = key.mDisplayId; + final boolean hasOverrideConfiguration = key.hasOverrideConfiguration(); + tmpConfig.setTo(config); // Get new DisplayMetrics based on the DisplayAdjustments given to the ResourcesImpl. Update // a copy if the CompatibilityInfo changed, because the ResourcesImpl object will handle the @@ -1090,12 +1120,15 @@ public class ResourcesManager { daj = new DisplayAdjustments(daj); daj.setCompatibilityInfo(compat); } - tmpConfig.setTo(config); - if (key.hasOverrideConfiguration()) { + daj.setConfiguration(config); + DisplayMetrics dm = getDisplayMetrics(displayId, daj); + if (displayId != Display.DEFAULT_DISPLAY) { + applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig); + } + + if (hasOverrideConfiguration) { tmpConfig.updateFrom(key.mOverrideConfiguration); } - daj.setConfiguration(tmpConfig); - DisplayMetrics dm = getDisplayMetrics(displayId, daj); resourcesImpl.updateConfiguration(tmpConfig, dm, compat); } diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 90d8bab842588..c328d720426d1 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -40,10 +40,7 @@ import android.app.servertransaction.ResumeActivityItem; import android.app.servertransaction.StopActivityItem; import android.content.Intent; import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Rect; import android.os.IBinder; -import android.util.DisplayMetrics; import android.util.MergedConfiguration; import android.view.Display; import android.view.View; @@ -309,58 +306,6 @@ public class ActivityThreadTest { assertEquals(400, activity.mConfig.smallestScreenWidthDp); } - @Test - public void testHandleConfigurationChangedDoesntOverrideActivityConfig() { - final TestActivity activity = mActivityTestRule.launchActivity(new Intent()); - - InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - final Configuration oldActivityConfig = - new Configuration(activity.getResources().getConfiguration()); - final DisplayMetrics oldActivityMetrics = new DisplayMetrics(); - activity.getDisplay().getMetrics(oldActivityMetrics); - final Resources oldAppResources = activity.getApplication().getResources(); - final Configuration oldAppConfig = - new Configuration(oldAppResources.getConfiguration()); - final DisplayMetrics oldApplicationMetrics = new DisplayMetrics(); - oldApplicationMetrics.setTo(oldAppResources.getDisplayMetrics()); - assertEquals("Process config must match the top activity config by default", - 0, oldActivityConfig.diffPublicOnly(oldAppConfig)); - assertEquals("Process config must match the top activity config by default", - oldActivityMetrics, oldApplicationMetrics); - - // Update the application configuration separately from activity config - final Configuration newAppConfig = new Configuration(oldAppConfig); - newAppConfig.densityDpi += 100; - newAppConfig.screenHeightDp += 100; - final Rect newBounds = new Rect(newAppConfig.windowConfiguration.getAppBounds()); - newBounds.bottom += 100; - newAppConfig.windowConfiguration.setAppBounds(newBounds); - newAppConfig.windowConfiguration.setBounds(newBounds); - newAppConfig.seq++; - - final ActivityThread activityThread = activity.getActivityThread(); - activityThread.handleConfigurationChanged(newAppConfig); - - // Verify that application config update was applied, but didn't change activity config. - assertEquals("Activity config must not change if the process config changes", - oldActivityConfig, activity.getResources().getConfiguration()); - - final DisplayMetrics newActivityMetrics = new DisplayMetrics(); - activity.getDisplay().getMetrics(newActivityMetrics); - assertEquals("Activity display size must not change if the process config changes", - oldActivityMetrics, newActivityMetrics); - final Resources newAppResources = activity.getApplication().getResources(); - assertEquals("Application config must be updated", - newAppConfig, newAppResources.getConfiguration()); - final DisplayMetrics newApplicationMetrics = new DisplayMetrics(); - newApplicationMetrics.setTo(newAppResources.getDisplayMetrics()); - assertNotEquals("Application display size must be updated after config update", - oldApplicationMetrics, newApplicationMetrics); - assertNotEquals("Application display size must be updated after config update", - newActivityMetrics, newApplicationMetrics); - }); - } - @Test public void testResumeAfterNewIntent() { final Activity activity = mActivityTestRule.launchActivity(new Intent()); From 04487ee10624a8ca6caca71d2c7eca7662035ad5 Mon Sep 17 00:00:00 2001 From: markchien Date: Thu, 12 Mar 2020 15:22:01 +0800 Subject: [PATCH 130/182] Give tethering bluetooth privilege permission Permisssion of PanService#setBluetoothTethering is change from BLUETOOTH_ADMIN to BLUETOOTH_PRIVILEGED. Tethering service need bluetooth privilege permission to enable bluetooth tethering. Bug: 146045934 Test: on/off bluetooth tethering Merged-In: Ib87a5d5a5bb49390aa55e52713bb3539d4a52348 Change-Id: Ib87a5d5a5bb49390aa55e52713bb3539d4a52348 (cherry picked from commit 1f47e1c22ef82e725575666ddff943c1d560652a) --- data/etc/privapp-permissions-platform.xml | 1 + packages/Tethering/AndroidManifest.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index d8bd81e80ed55..97296efdd4c07 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -255,6 +255,7 @@ applications that come with the platform + diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml index c71d0d7bc543c..9328611f5d3f9 100644 --- a/packages/Tethering/AndroidManifest.xml +++ b/packages/Tethering/AndroidManifest.xml @@ -27,7 +27,7 @@ added to the privileged permissions whitelist for that package. --> - + From da687a071fb0fc420d18c67ff0049c07c926124d Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Thu, 19 Mar 2020 22:28:43 +0800 Subject: [PATCH 131/182] Make canBeImeTarget be compatible with legacy behavior And let PerDisplay can adjust animation parameters while the insets source control is changed during animation. Fix: 151759336 Test: atest WindowStateTests Change-Id: Ic2a308e6b7ec39b4b8645751e31addd26ddf3735 (cherry picked from commit 1ea1ea6a04536238d56a7107badc222500746c8a) --- .../InputMethodService.java | 1 + .../systemui/wm/DisplayImeController.java | 213 ++++++++++-------- .../com/android/server/wm/WindowState.java | 8 +- .../android/server/wm/WindowStateTests.java | 2 - 4 files changed, 119 insertions(+), 105 deletions(-) diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index c2ee21d5115da..91720295206ad 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1249,6 +1249,7 @@ public class InputMethodService extends AbstractInputMethodService { WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false); mWindow.getWindow().getAttributes().setFitInsetsTypes(statusBars() | navigationBars()); mWindow.getWindow().getAttributes().setFitInsetsSides(Side.all() & ~Side.BOTTOM); + mWindow.getWindow().setStatusBarColor(0); // IME layout should always be inset by navigation bar, no matter its current visibility, // unless automotive requests it, since automotive may hide the navigation bar. diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java index 54118390325cc..18fb95381e49b 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java @@ -97,7 +97,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } if (mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation() != pd.mRotation && isImeShowing(displayId)) { - pd.startAnimation(true); + pd.startAnimation(true /* show */, false /* force */); } } @@ -200,7 +200,14 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; } if (activeControl.getType() == InsetsState.ITYPE_IME) { - mImeSourceControl = activeControl; + synchronized (this) { + mImeSourceControl = activeControl; + if (mAnimation != null) { + // The surface position of IME might have been changed during + // animation, so start animation again to update the position. + startAnimation(mImeShowing, true /* force */); + } + } } } } @@ -212,7 +219,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return; } if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); - startAnimation(true /* show */); + startAnimation(true /* show */, false /* force */); } @Override @@ -221,7 +228,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return; } if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); - startAnimation(false /* show */); + startAnimation(false /* show */, false /* force */); } /** @@ -239,111 +246,119 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return imeSource.getFrame().top + (int) surfaceOffset; } - private void startAnimation(final boolean show) { + private void startAnimation(final boolean show, final boolean force) { final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME); if (imeSource == null || mImeSourceControl == null) { return; } mHandler.post(() -> { - if (DEBUG) { - Slog.d(TAG, "Run startAnim show:" + show + " was:" - + (mAnimationDirection == DIRECTION_SHOW ? "SHOW" - : (mAnimationDirection == DIRECTION_HIDE ? "HIDE" : "NONE"))); - } - if ((mAnimationDirection == DIRECTION_SHOW && show) - || (mAnimationDirection == DIRECTION_HIDE && !show)) { - return; - } - boolean seek = false; - float seekValue = 0; - if (mAnimation != null) { - if (mAnimation.isRunning()) { - seekValue = (float) mAnimation.getAnimatedValue(); - seek = true; + synchronized (this) { + if (DEBUG) { + Slog.d(TAG, "Run startAnim show:" + show + " was:" + + (mAnimationDirection == DIRECTION_SHOW ? "SHOW" + : (mAnimationDirection == DIRECTION_HIDE ? "HIDE" : "NONE"))); + } + if (!force && (mAnimationDirection == DIRECTION_SHOW && show) + || (mAnimationDirection == DIRECTION_HIDE && !show)) { + return; + } + boolean seek = false; + float seekValue = 0; + if (mAnimation != null) { + if (mAnimation.isRunning()) { + seekValue = (float) mAnimation.getAnimatedValue(); + seek = true; + } + mAnimation.cancel(); + } + mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE; + final float defaultY = mImeSourceControl.getSurfacePosition().y; + final float x = mImeSourceControl.getSurfacePosition().x; + final float hiddenY = defaultY + imeSource.getFrame().height(); + final float shownY = defaultY; + final float startY = show ? hiddenY : shownY; + final float endY = show ? shownY : hiddenY; + mImeShowing = show; + mAnimation = ValueAnimator.ofFloat(startY, endY); + mAnimation.setDuration( + show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS); + if (seek) { + mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY)); } - mAnimation.cancel(); - } - mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE; - final float defaultY = mImeSourceControl.getSurfacePosition().y; - final float x = mImeSourceControl.getSurfacePosition().x; - final float hiddenY = defaultY + imeSource.getFrame().height(); - final float shownY = defaultY; - final float startY = show ? hiddenY : shownY; - final float endY = show ? shownY : hiddenY; - if (mImeShowing && show) { - // IME is already showing, so set seek to end - seekValue = shownY; - seek = true; - } - mImeShowing = show; - mAnimation = ValueAnimator.ofFloat(startY, endY); - mAnimation.setDuration( - show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS); - if (seek) { - mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY)); - } - mAnimation.addUpdateListener(animation -> { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - float value = (float) animation.getAnimatedValue(); - t.setPosition(mImeSourceControl.getLeash(), x, value); - dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t); - t.apply(); - mTransactionPool.release(t); - }); - mAnimation.setInterpolator(INTERPOLATOR); - mAnimation.addListener(new AnimatorListenerAdapter() { - private boolean mCancelled = false; - @Override - public void onAnimationStart(Animator animation) { - SurfaceControl.Transaction t = mTransactionPool.acquire(); - t.setPosition(mImeSourceControl.getLeash(), x, startY); - if (DEBUG) { - Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:" - + imeTop(imeSource, hiddenY) + "->" + imeTop(imeSource, shownY) - + " showing:" + (mAnimationDirection == DIRECTION_SHOW)); + mAnimation.addUpdateListener(animation -> { + synchronized (this) { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + float value = (float) animation.getAnimatedValue(); + t.setPosition(mImeSourceControl.getLeash(), x, value); + dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t); + t.apply(); + mTransactionPool.release(t); } - dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY), - imeTop(imeSource, shownY), mAnimationDirection == DIRECTION_SHOW, - t); - if (mAnimationDirection == DIRECTION_SHOW) { - t.show(mImeSourceControl.getLeash()); - } - t.apply(); - mTransactionPool.release(t); - } - @Override - public void onAnimationCancel(Animator animation) { - mCancelled = true; - } - @Override - public void onAnimationEnd(Animator animation) { - if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled); - SurfaceControl.Transaction t = mTransactionPool.acquire(); - if (!mCancelled) { - t.setPosition(mImeSourceControl.getLeash(), x, endY); - } - dispatchEndPositioning(mDisplayId, mCancelled, t); - if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { - t.hide(mImeSourceControl.getLeash()); - } - t.apply(); - mTransactionPool.release(t); + }); + mAnimation.setInterpolator(INTERPOLATOR); + mAnimation.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled = false; - mAnimationDirection = DIRECTION_NONE; - mAnimation = null; + @Override + public void onAnimationStart(Animator animation) { + synchronized (this) { + SurfaceControl.Transaction t = mTransactionPool.acquire(); + t.setPosition(mImeSourceControl.getLeash(), x, startY); + if (DEBUG) { + Slog.d(TAG, "onAnimationStart d:" + mDisplayId + + " top:" + imeTop(imeSource, hiddenY) + + "->" + imeTop(imeSource, shownY) + + " showing:" + + (mAnimationDirection == DIRECTION_SHOW)); + } + dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY), + imeTop(imeSource, shownY), + mAnimationDirection == DIRECTION_SHOW, t); + if (mAnimationDirection == DIRECTION_SHOW) { + t.show(mImeSourceControl.getLeash()); + } + t.apply(); + mTransactionPool.release(t); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + synchronized (this) { + if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled); + SurfaceControl.Transaction t = mTransactionPool.acquire(); + if (!mCancelled) { + t.setPosition(mImeSourceControl.getLeash(), x, endY); + } + dispatchEndPositioning(mDisplayId, mCancelled, t); + if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { + t.hide(mImeSourceControl.getLeash()); + } + t.apply(); + mTransactionPool.release(t); + + mAnimationDirection = DIRECTION_NONE; + mAnimation = null; + } + } + }); + if (!show) { + // When going away, queue up insets change first, otherwise any bounds + // changes can have a "flicker" of ime-provided insets. + setVisibleDirectly(false /* visible */); + } + mAnimation.start(); + if (show) { + // When showing away, queue up insets change last, otherwise any bounds + // changes can have a "flicker" of ime-provided insets. + setVisibleDirectly(true /* visible */); } - }); - if (!show) { - // When going away, queue up insets change first, otherwise any bounds changes - // can have a "flicker" of ime-provided insets. - setVisibleDirectly(false /* visible */); - } - mAnimation.start(); - if (show) { - // When showing away, queue up insets change last, otherwise any bounds changes - // can have a "flicker" of ime-provided insets. - setVisibleDirectly(true /* visible */); } }); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 161152ba0d747..cf8773b328e57 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -131,6 +131,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; @@ -138,7 +139,6 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; -import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; @@ -2270,9 +2270,9 @@ class WindowState extends WindowContainer implements WindowManagerP return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { - // Support legacy use cases where completely transparent windows can still be ime target - // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format)) { + // Support legacy use cases where transparent windows can still be ime target with + // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 85e4a1668a352..e95ccab38960e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,11 +251,9 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; - appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; - appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; From b810d3346ac24a0ecce91c1399870a220b8f33ce Mon Sep 17 00:00:00 2001 From: markchien Date: Thu, 12 Mar 2020 15:22:01 +0800 Subject: [PATCH 132/182] Give tethering bluetooth privilege permission Permisssion of PanService#setBluetoothTethering is change from BLUETOOTH_ADMIN to BLUETOOTH_PRIVILEGED. Tethering service need bluetooth privilege permission to enable bluetooth tethering. Bug: 146045934 Test: on/off bluetooth tethering Merged-In: Ib87a5d5a5bb49390aa55e52713bb3539d4a52348 Change-Id: Ib87a5d5a5bb49390aa55e52713bb3539d4a52348 (cherry picked from commit 1f47e1c22ef82e725575666ddff943c1d560652a) --- data/etc/privapp-permissions-platform.xml | 1 + packages/Tethering/AndroidManifest.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index d8bd81e80ed55..97296efdd4c07 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -255,6 +255,7 @@ applications that come with the platform + diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml index c71d0d7bc543c..9328611f5d3f9 100644 --- a/packages/Tethering/AndroidManifest.xml +++ b/packages/Tethering/AndroidManifest.xml @@ -27,7 +27,7 @@ added to the privileged permissions whitelist for that package. --> - + From 7a1d207e1823d6e13b45b4023e391aca2f1ffc65 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Mon, 30 Mar 2020 16:16:16 -0700 Subject: [PATCH 133/182] Work around for display info mismatch during the PiP transition This is a work around for b/152720544, we noticed that when entering PiP from a landscape activity to home screen in portrait mode - OnDisplayChangingListener is not called - PinnedStackListener#onDisplayInfoChanged gets called after the transition is started This work around updates the destination bounds once this mismatch is detected and a more proper fix should be there for b/152809058 Bug: 152720544 Test: manually enter/exit PiP from Play Movies for X times Change-Id: I833027d4a4638a7a99f7abd2f50e493bdf5bad03 (cherry picked from commit 951dc026f5f9d5704422115a904f3b8116094a9e) --- .../systemui/pip/PipAnimationController.java | 7 ++++++ .../systemui/pip/PipBoundsHandler.java | 4 ++++ .../systemui/pip/PipTaskOrganizer.java | 23 +++++++++++++++++++ .../systemui/pip/phone/PipManager.java | 1 + 4 files changed, 35 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java index 232c23dc14f0c..69cbda6d622e6 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java @@ -110,6 +110,10 @@ public class PipAnimationController { return mCurrentAnimator; } + PipTransitionAnimator getCurrentAnimator() { + return mCurrentAnimator; + } + private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setInterpolator(mFastOutSlowInInterpolator); @@ -239,6 +243,9 @@ public class PipAnimationController { void setDestinationBounds(Rect destinationBounds) { mDestinationBounds.set(destinationBounds); + if (mAnimationType == ANIM_TYPE_ALPHA) { + onStartTransaction(mLeash, newSurfaceControlTransaction()); + } } void setCurrentValue(T value) { diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index 4969fc81978ec..1868536dca988 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -199,6 +199,10 @@ public class PipBoundsHandler { return mLastDestinationBounds; } + public Rect getDisplayBounds() { + return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + } + /** * Responds to IPinnedStackListener on {@link DisplayInfo} change. * It will normally follow up with a diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index af8b18482ea83..c5cb01ffb7f9f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -310,6 +310,29 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { null /* updateBoundsCallback */); } + /** + * TODO(b/152809058): consolidate the display info handling logic in SysUI + */ + @SuppressWarnings("unchecked") + public void mayUpdateCurrentAnimationOnRotationChange() { + final PipAnimationController.PipTransitionAnimator animator = + mPipAnimationController.getCurrentAnimator(); + if (animator != null && animator.isRunning() + && animator.getTransitionDirection() == TRANSITION_DIRECTION_TO_PIP) { + final Rect currentDestinationBounds = animator.getDestinationBounds(); + if (mPipBoundsHandler.getDisplayBounds().contains(currentDestinationBounds)) { + return; + } + final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds( + getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams), + null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo)); + if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) { + animator.updateEndValue(newDestinationBounds); + } + animator.setDestinationBounds(newDestinationBounds); + } + } + /** * @return {@code true} if the aspect ratio is changed since no other parameters within * {@link PictureInPictureParams} would affect the bounds. diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index 9722c0873a781..23190b89fdd5b 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -364,6 +364,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, animatingBounds, fromImeAdjustment, fromShelfAdjustment, mTmpDisplayInfo.rotation); + mPipTaskOrganizer.mayUpdateCurrentAnimationOnRotationChange(); } public void dump(PrintWriter pw) { From 56fe5328c37390cd0da2eb80e15fc8990e0110f2 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Mon, 30 Mar 2020 16:16:16 -0700 Subject: [PATCH 134/182] Work around for display info mismatch during the PiP transition This is a work around for b/152720544, we noticed that when entering PiP from a landscape activity to home screen in portrait mode - OnDisplayChangingListener is not called - PinnedStackListener#onDisplayInfoChanged gets called after the transition is started This work around updates the destination bounds once this mismatch is detected and a more proper fix should be there for b/152809058 Bug: 152720544 Test: manually enter/exit PiP from Play Movies for X times Change-Id: I833027d4a4638a7a99f7abd2f50e493bdf5bad03 (cherry picked from commit 951dc026f5f9d5704422115a904f3b8116094a9e) --- .../systemui/pip/PipAnimationController.java | 7 ++++++ .../systemui/pip/PipBoundsHandler.java | 4 ++++ .../systemui/pip/PipTaskOrganizer.java | 23 +++++++++++++++++++ .../systemui/pip/phone/PipManager.java | 1 + 4 files changed, 35 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java index 153359204d5fd..d219a9e65a3cc 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java @@ -110,6 +110,10 @@ public class PipAnimationController { return mCurrentAnimator; } + PipTransitionAnimator getCurrentAnimator() { + return mCurrentAnimator; + } + private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setInterpolator(mFastOutSlowInInterpolator); @@ -239,6 +243,9 @@ public class PipAnimationController { void setDestinationBounds(Rect destinationBounds) { mDestinationBounds.set(destinationBounds); + if (mAnimationType == ANIM_TYPE_ALPHA) { + onStartTransaction(mLeash, newSurfaceControlTransaction()); + } } void setCurrentValue(T value) { diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index 4969fc81978ec..1868536dca988 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -199,6 +199,10 @@ public class PipBoundsHandler { return mLastDestinationBounds; } + public Rect getDisplayBounds() { + return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + } + /** * Responds to IPinnedStackListener on {@link DisplayInfo} change. * It will normally follow up with a diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index da171b27d97cf..4b3847217e016 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -318,6 +318,29 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { null /* updateBoundsCallback */); } + /** + * TODO(b/152809058): consolidate the display info handling logic in SysUI + */ + @SuppressWarnings("unchecked") + public void mayUpdateCurrentAnimationOnRotationChange() { + final PipAnimationController.PipTransitionAnimator animator = + mPipAnimationController.getCurrentAnimator(); + if (animator != null && animator.isRunning() + && animator.getTransitionDirection() == TRANSITION_DIRECTION_TO_PIP) { + final Rect currentDestinationBounds = animator.getDestinationBounds(); + if (mPipBoundsHandler.getDisplayBounds().contains(currentDestinationBounds)) { + return; + } + final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds( + getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams), + null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo)); + if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) { + animator.updateEndValue(newDestinationBounds); + } + animator.setDestinationBounds(newDestinationBounds); + } + } + /** * @return {@code true} if the aspect ratio is changed since no other parameters within * {@link PictureInPictureParams} would affect the bounds. diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index ea195327a410d..8a25f4d441d3c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -363,6 +363,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, animatingBounds, fromImeAdjustment, fromShelfAdjustment, mTmpDisplayInfo.rotation); + mPipTaskOrganizer.mayUpdateCurrentAnimationOnRotationChange(); } public void dump(PrintWriter pw) { From c976c4366c47a56ff463a5158fe1eafd9bb11b2e Mon Sep 17 00:00:00 2001 From: Yan Wang Date: Tue, 31 Mar 2020 13:52:20 -0700 Subject: [PATCH 135/182] startop: Fix a string format bug in EventSequenceValidator. Bug: 152725990 Test: Make and run check the log. Change-Id: Ib56a8f7acadec073946353f8b0a8a4677099b3b2 (cherry picked from commit b5d1353a6998e97aa4f5250a359fc2589b4af34c) --- .../startop/iorap/EventSequenceValidator.java | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java index 47bf14892ccb3..6b194550cc111 100644 --- a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java +++ b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java @@ -103,8 +103,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { @Override public void onIntentStarted(@NonNull Intent intent, long timestampNs) { if (state == State.UNKNOWN) { - logWarningWithStackTrace( - String.format("IntentStarted during UNKNOWN. " + intent)); + logWarningWithStackTrace("IntentStarted during UNKNOWN. " + intent); incAccIntentStartedEvents(); return; } @@ -128,7 +127,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { @Override public void onIntentFailed() { if (state == State.UNKNOWN) { - logWarningWithStackTrace(String.format("onIntentFailed during UNKNOWN.")); + logWarningWithStackTrace("onIntentFailed during UNKNOWN."); decAccIntentStartedEvents(); return; } @@ -147,8 +146,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity, @Temperature int temperature) { if (state == State.UNKNOWN) { - logWarningWithStackTrace( - String.format("onActivityLaunched during UNKNOWN.")); + logWarningWithStackTrace("onActivityLaunched during UNKNOWN."); return; } if (state != State.INTENT_STARTED) { @@ -165,8 +163,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { @Override public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) { if (state == State.UNKNOWN) { - logWarningWithStackTrace( - String.format("onActivityLaunchCancelled during UNKNOWN.")); + logWarningWithStackTrace("onActivityLaunchCancelled during UNKNOWN."); decAccIntentStartedEvents(); return; } @@ -185,8 +182,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity, long timestampNs) { if (state == State.UNKNOWN) { - logWarningWithStackTrace( - String.format("onActivityLaunchFinished during UNKNOWN.")); + logWarningWithStackTrace("onActivityLaunchFinished during UNKNOWN."); decAccIntentStartedEvents(); return; } @@ -206,8 +202,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity, long timestampNs) { if (state == State.UNKNOWN) { - logWarningWithStackTrace( - String.format("onReportFullyDrawn during UNKNOWN.")); + logWarningWithStackTrace("onReportFullyDrawn during UNKNOWN."); return; } if (state == State.INIT) { @@ -237,8 +232,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { private void incAccIntentStartedEvents() { if (accIntentStartedEvents < 0) { - throw new AssertionError( - String.format("The number of unknowns cannot be negative")); + throw new AssertionError("The number of unknowns cannot be negative"); } if (accIntentStartedEvents == 0) { state = State.UNKNOWN; @@ -250,8 +244,7 @@ public class EventSequenceValidator implements ActivityMetricsLaunchObserver { private void decAccIntentStartedEvents() { if (accIntentStartedEvents <= 0) { - throw new AssertionError( - String.format("The number of unknowns cannot be negative")); + throw new AssertionError("The number of unknowns cannot be negative"); } if(accIntentStartedEvents == 1) { state = State.INIT; From c28c530c4d01b82f3e804f12f3f99bdb9c1ed7a0 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Wed, 1 Apr 2020 14:10:04 -0700 Subject: [PATCH 136/182] Fixes NPE and adds @Nullable to PackageSetting.pkg This change addresses an NPE encountered when a package setting refers to an unavailable package and is thus null. It adds a @Nullable annotation to the field to hopefully catch more of this type of error going forward. Fixes: 153007501 Test: atest AppEnumerationTests PackageManagerTest Change-Id: I0ffe1f488d69d45893c96c755e48e19de43fcdf2 (cherry picked from commit 74860927b9cc2e847efe2097e244155f15796d6b) --- services/core/java/com/android/server/pm/AppsFilter.java | 6 ++++-- .../core/java/com/android/server/pm/PackageSetting.java | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 805d91852d8e3..09b782d768d21 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -674,7 +674,8 @@ public class AppsFilter { Trace.endSection(); if (callingPkgSetting != null) { - if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) { + if (callingPkgSetting.pkg != null + && !mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) { if (DEBUG_LOGGING) { log(callingSetting, targetPkgSetting, "DISABLED"); } @@ -682,7 +683,8 @@ public class AppsFilter { } } else { for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { - if (!mFeatureConfig.packageIsEnabled(callingSharedPkgSettings.valueAt(i).pkg)) { + final AndroidPackage pkg = callingSharedPkgSettings.valueAt(i).pkg; + if (pkg != null && !mFeatureConfig.packageIsEnabled(pkg)) { if (DEBUG_LOGGING) { log(callingSetting, targetPkgSetting, "DISABLED"); } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 9a8692d029e04..600518e170304 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -43,6 +43,7 @@ import java.util.Set; public class PackageSetting extends PackageSettingBase { int appId; + @Nullable public AndroidPackage pkg; /** * WARNING. The object reference is important. We perform integer equality and NOT From db5526393b44ee4e845cb61f7e11cb271dbf06a4 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Tue, 31 Mar 2020 18:22:05 +0800 Subject: [PATCH 137/182] Update insets state for each window if its mBehindIme is changed InsetsStateController would dispatch a different insets state to a window accroding to its condition. For example, a window behind IME can get the insets state different from one got from a window above IME. So when the conditions change, we should update the insets state to the client. Fix: 152839133 Test: atest InsetsStateControllerTest Change-Id: I7a846d55da92a652d79fb81dfd79abcc87971830 (cherry picked from commit 53c8eb8ae0689fbe300d0e5f470f6f7247006d6c) --- .../com/android/server/wm/DisplayContent.java | 8 +++- .../server/wm/InsetsStateController.java | 9 ++++ .../server/wm/InsetsStateControllerTest.java | 43 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 01081404a5029..ce7e79714c396 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -503,6 +503,9 @@ class DisplayContent extends WindowContainer mWinRemovedSinceNullFocus = new ArrayList<>(); + /** Windows whose client's insets states are not up-to-date. */ + final ArrayList mWinInsetsChanged = new ArrayList<>(); + private ScreenRotationAnimation mScreenRotationAnimation; /** @@ -708,7 +711,10 @@ class DisplayContent extends WindowContainer= 0; i--) { mProviders.valueAt(i).onPostLayout(); } + final ArrayList winInsetsChanged = mDisplayContent.mWinInsetsChanged; if (!mLastState.equals(mState)) { mLastState.set(mState, true /* copySources */); notifyInsetsChanged(); + } else { + // The global insets state has not changed but there might be windows whose conditions + // (e.g., z-order) have changed. They can affect the insets states that we dispatch to + // the clients. + for (int i = winInsetsChanged.size() - 1; i >= 0; i--) { + winInsetsChanged.get(i).notifyInsetsChanged(); + } } + winInsetsChanged.clear(); } void onInsetsModified(InsetsControlTarget windowState, InsetsState state) { diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index db7bce4c87530..17ebe4f67377f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -32,6 +32,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; @@ -168,6 +172,45 @@ public class InsetsStateControllerTest extends WindowTestsBase { assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME)); } + @Test + public void testStripForDispatch_imeOrderChanged() { + getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null); + + // This window can be the IME target while app cannot be the IME target. + createWindow(null, TYPE_APPLICATION, "base"); + + // Send our spy window (app) into the system so that we can detect the invocation. + final WindowState win = createWindow(null, TYPE_APPLICATION, "app"); + final WindowToken parent = win.mToken; + parent.removeChild(win); + final WindowState app = spy(win); + parent.addWindow(app); + + // Adding FLAG_NOT_FOCUSABLE makes app above IME. + app.mAttrs.flags |= FLAG_NOT_FOCUSABLE; + mDisplayContent.computeImeTarget(true); + mDisplayContent.setLayoutNeeded(); + mDisplayContent.applySurfaceChangesTransaction(); + + // app won't get IME insets while above IME. + assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME)); + + // Reset invocation counter. + clearInvocations(app); + + // Removing FLAG_NOT_FOCUSABLE makes app below IME. + app.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; + mDisplayContent.computeImeTarget(true); + mDisplayContent.setLayoutNeeded(); + mDisplayContent.applySurfaceChangesTransaction(); + + // Make sure app got notified. + verify(app, atLeast(1)).notifyInsetsChanged(); + + // app will get IME insets while below IME. + assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME)); + } + @Test public void testStripForDispatch_childWindow_altFocusable() { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); From 7e661a2ba37e2c2f6b168b4a3e0a93e4e1981151 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 1 Apr 2020 15:48:17 +0200 Subject: [PATCH 138/182] Request fit system windows if soft input mode updates To make sure legacy insets are correct always. Test: Open Message, go to attachments, reopen IME Bug: 152851108 Change-Id: I9ae0930645ca4331d362af7db9ab77bf49d74edc (cherry picked from commit c5c829f675edd91fe1fbf591be5eadbf1b3f9b33) --- core/java/android/view/ViewRootImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 51304dcfe8cbf..35f955f7e78bb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -130,6 +130,7 @@ import android.view.View.MeasureSpec; import android.view.Window.OnContentApplyWindowInsetsListener; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; +import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -1412,6 +1413,10 @@ public final class ViewRootImpl implements ViewParent, | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST); } + if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) { + requestFitSystemWindows(); + } + mWindowAttributesChanged = true; scheduleTraversals(); } From 96b5266ed1ccf0f50fe806ac52f3b53566cadaca Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 1 Apr 2020 14:26:19 +0200 Subject: [PATCH 139/182] WindowInsets: Ignore consumeStableInsets() With the introduction of insets types we no longer support consuming individual insets. Instead we consumed all insets, regardless of whether you consumed stable or system insets - but that led to compat issues. On Q, consumeStableInsets was almost always a no-op anyways, because stable insets already came pre-consumed during dispatch. This change makes consumeStableInsets() a no-op to more closely match that behavior. Bug: 152033222 Test: atest WindowInsetsTest Change-Id: Ic48ee7386320fc16449ac79435b69305a8132bf8 (cherry picked from commit 9ab688d487b50fe14a6b510d44d847908c36d6d6) --- core/java/android/view/WindowInsets.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 9b2a6cbce48f2..bbf1e2a6a57e4 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -818,12 +818,13 @@ public final class WindowInsets { * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} - * instead to stop dispatching insets. + * instead to stop dispatching insets. On {@link android.os.Build.VERSION_CODES#R R}, this + * method has no effect. */ @Deprecated @NonNull public WindowInsets consumeStableInsets() { - return consumeSystemWindowInsets(); + return this; } /** From 6f7aa8050caf00037252d35839b9ff5a38709010 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 1 Apr 2020 15:01:08 +0200 Subject: [PATCH 140/182] WindowInsetsAnimation: Synchronously dispatch window insets animation callbacks Test: atest WindowInsetsAnimationControllerTests Bug: 152617481 Change-Id: Ie002f2e605f841563d8c2669f949be3ddd666146 (cherry picked from commit 6a4448f0f86c408d79c27f29011dc9d3fd6f3036) --- core/java/android/view/InsetsAnimationControlCallbacks.java | 4 +++- core/java/android/view/InsetsAnimationControlImpl.java | 2 +- .../java/android/view/InsetsAnimationThreadControlRunner.java | 2 +- core/java/android/view/InsetsController.java | 4 ++-- .../src/android/view/InsetsAnimationControlImplTest.java | 2 +- services/core/java/com/android/server/wm/InsetsPolicy.java | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java index 4227f78564a7f..74c186948b2f2 100644 --- a/core/java/android/view/InsetsAnimationControlCallbacks.java +++ b/core/java/android/view/InsetsAnimationControlCallbacks.java @@ -40,8 +40,10 @@ public interface InsetsAnimationControlCallbacks { /** * Schedule the apply by posting the animation callback. + * + * @param runner The runner that requested applying insets */ - void scheduleApplyChangeInsets(); + void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner); /** * Finish the final steps after the animation. diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index ef6a9b212e926..05abc60321163 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -156,7 +156,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll mPendingFraction = sanitize(fraction); mPendingInsets = sanitize(insets); mPendingAlpha = sanitize(alpha); - mController.scheduleApplyChangeInsets(); + mController.scheduleApplyChangeInsets(this); } @VisibleForTesting diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java index 3870f26e9990b..9dfdd0604e6bc 100644 --- a/core/java/android/view/InsetsAnimationThreadControlRunner.java +++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java @@ -54,7 +54,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro } @Override - public void scheduleApplyChangeInsets() { + public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) { mControl.applyChangeInsets(mState); } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 8eb9b5f6ef234..72ddaca27a768 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -1076,8 +1076,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting @Override - public void scheduleApplyChangeInsets() { - if (mStartingAnimation) { + public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) { + if (mStartingAnimation || runner.getAnimationType() == ANIMATION_TYPE_USER) { mAnimCallback.run(); mAnimCallbackScheduled = false; return; diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java index 9d251dac7c784..5f12bf04d931b 100644 --- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java +++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java @@ -229,7 +229,7 @@ public class InsetsAnimationControlImplTest { doAnswer(invocation -> { mController.applyChangeInsets(mInsetsState); return null; - }).when(mMockController).scheduleApplyChangeInsets(); + }).when(mMockController).scheduleApplyChangeInsets(any()); mController.finish(true /* shown */); assertEquals(Insets.of(0, 100, 100, 0), mController.getCurrentInsets()); verify(mMockController).notifyFinished(eq(mController), eq(true /* shown */)); diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 9e954f29438c6..007af249c580e 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -398,7 +398,7 @@ class InsetsPolicy { /** Called on SurfaceAnimationThread without global WM lock held. */ @Override - public void scheduleApplyChangeInsets() { + public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) { InsetsState state = getState(); if (mAnimationControl.applyChangeInsets(state)) { mAnimationControl.finish(mAnimatingShown); From b1d6a2013ed5627b3e528448d3c6d5ad56b96025 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 1 Apr 2020 19:48:16 +0200 Subject: [PATCH 141/182] WindowInsetsAnimation: Fix app driven closing of IME When using controlWindowInsetsAnimation to close the IME, delay reporting this to the IME until the animation is actually finished. Otherwise, the IME will self-hide and start a transition that breaks the just-begun app-driven transition. (Regression from I7f6098a61a5942795ffd33a60329e4dd5fb5d6cb which changed InputMethodService to hide itself in reponse to notifyHidden) Bug: 151980214 Test: make WindowInsetsTests, ensure that dragging the IME closed doesnt get cancelled Change-Id: If4e64cc78742a4e1e8c98137bd97d65dd567f674 (cherry picked from commit 3b19ff1e0f7a0c8b180c91e4227db48ab40c03af) --- core/java/android/view/ImeInsetsSourceConsumer.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 35286ba007c4d..2461e96c5b492 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -16,7 +16,6 @@ package android.view; -import static android.view.InsetsController.ANIMATION_TYPE_USER; import static android.view.InsetsController.AnimationType; import static android.view.InsetsState.ITYPE_IME; @@ -104,13 +103,9 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { void hide(boolean animationFinished, @AnimationType int animationType) { super.hide(); - if (!animationFinished) { - if (animationType == ANIMATION_TYPE_USER) { - // if controlWindowInsetsAnimation is hiding keyboard. - notifyHidden(); - } - } else { + if (animationFinished) { // remove IME surface as IME has finished hide animation. + notifyHidden(); removeSurface(); } } From 3ca71e54af7f32a2a36055d79112ccc0f78ccc86 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Tue, 7 Apr 2020 18:27:38 +0800 Subject: [PATCH 142/182] Only use the IME target from IMMS to update the IME control target DisplayContent.mInputMethodTarget is only used for deciding which window IME should attach to. Fix: 152698568 Fix: 153287963 Test: Steps in the bugs. Change-Id: Ife6b700436ffa6ce80af9c6c276c0fcf3a4e057a (cherry picked from commit 304db431533085708d376aa5d1e5292f9a6870b2) --- services/core/java/com/android/server/wm/DisplayContent.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8111c0ef28c2b..09b9321ea106e 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3425,7 +3425,10 @@ class DisplayContent extends WindowContainer Date: Wed, 8 Apr 2020 21:02:22 +0000 Subject: [PATCH 143/182] Revert "Fix exception handling in getState() binder cache" This reverts commit 81a3e1c578b5618bf02968a9b4402e70592b7b9b. Bug: b/153505953 Change-Id: I58c46e534ccadf332d10fff8f99c85ad24340c27 (cherry picked from commit 2a8802d2ca8ca6f1902d2c40ffaacc11c40e9e44) --- .../android/bluetooth/BluetoothAdapter.java | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index fc48e7f18f5fc..f216db6fc7175 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -979,14 +979,17 @@ public final class BluetoothAdapter { 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) { @Override protected Integer recompute(Void query) { - // This function must be called while holding the - // mServiceLock, and with mService not null. The public - // getState() method makes this guarantee. try { - return mService.getState(); + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.getState(); + } } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); } + return BluetoothAdapter.STATE_OFF; } }; @@ -1013,24 +1016,7 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState public int getState() { - int state = BluetoothAdapter.STATE_OFF; - - try { - mServiceLock.readLock().lock(); - // The test for mService must either be outside the cache, or - // the cache must be invalidated when mService changes. - if (mService != null) { - state = mBluetoothGetStateCache.query(null); - } - } catch (RuntimeException e) { - if (e.getCause() instanceof RemoteException) { - Log.e(TAG, "", e.getCause()); - } else { - throw e; - } - } finally { - mServiceLock.readLock().unlock(); - } + int state = mBluetoothGetStateCache.query(null); // Consider all internal states as OFF if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON From 9d592ad5612709518f980a1424b1912dc8cc4a80 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Thu, 9 Apr 2020 18:02:29 -0700 Subject: [PATCH 144/182] Add /apex to the list of allowed SystemServer paths SystemPartitions does not have the /apex mount. We need to do an explicit check for it when recording the system server jars. Test: DexManagerTests, manual Bug: 148774920 Change-Id: I9c92866304d98144cb82f39b3c768948dcf284ea (cherry picked from commit 5bb1b8f3ab9ab717c28c8c62b0a97688e0b100f7) --- services/core/java/com/android/server/pm/dex/DexManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index eb7057dd2994b..6dcf71e9fbf03 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -232,6 +232,10 @@ public class DexManager { private boolean isSystemServerDexPathSupportedForOdex(String dexPath) { ArrayList partitions = PackagePartitions.getOrderedPartitions(identity()); + // First check the apex partition as it's not part of the SystemPartitions. + if (dexPath.startsWith("/apex/")) { + return true; + } for (int i = 0; i < partitions.size(); i++) { if (partitions.get(i).containsPath(dexPath)) { return true; From 23c844b0d230d7cf2f5a38b82d251a67e02edf42 Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Thu, 9 Apr 2020 15:21:07 -0700 Subject: [PATCH 145/182] Reboot the soundtrigger HAL on failure ... and avoid rebooting system_server. There is no benefit in rebooting the system_server. Fixes: 153461865 Test: Tested via a shell command that the sound trigger middleware service can indeed reboot the HAL and correctly recover from it dying. Change-Id: Ie476968b6acf97bf701d0e2929e7bd099e19cd56 (cherry picked from commit 9fac2c86ce2a441463cb523e20746a92e6f735f8) --- .../SoundTriggerMiddlewareService.java | 41 ++++++++++++++++++- .../SoundTriggerMiddlewareValidation.java | 8 +--- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java index 929d92f56c443..635cb613b934d 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java @@ -27,7 +27,9 @@ import android.media.soundtrigger_middleware.PhraseSoundModel; import android.media.soundtrigger_middleware.RecognitionConfig; import android.media.soundtrigger_middleware.SoundModel; import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor; +import android.os.Parcel; import android.os.RemoteException; +import android.os.SystemProperties; import android.util.Log; import com.android.server.SystemService; @@ -99,6 +101,28 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic } } + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + try { + return super.onTransact(code, data, reply, flags); + } catch (InternalServerError e) { + if (e.getCause() instanceof HalException) { + // We recover from any sort of HAL failure by rebooting the HAL process. + // This will likely reboot more than just the sound trigger HAL. + // The rest of the system should be able to tolerate that. + rebootHal(); + } + throw e; + } + } + + private static void rebootHal() { + Log.i(TAG, "Rebooting the sound trigger HAL"); + // This property needs to be defined in an init.rc script and trigger a HAL reboot. + SystemProperties.set("sys.audio.restart.hal", "1"); + } + private final static class ModuleService extends ISoundTriggerModule.Stub { private final ISoundTriggerModule mDelegate; @@ -119,7 +143,6 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic @Override public void unloadModel(int modelHandle) throws RemoteException { mDelegate.unloadModel(modelHandle); - ; } @Override @@ -159,6 +182,22 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic public void detach() throws RemoteException { mDelegate.detach(); } + + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + try { + return super.onTransact(code, data, reply, flags); + } catch (InternalServerError e) { + if (e.getCause() instanceof HalException) { + // We recover from any sort of HAL failure by rebooting the HAL process. + // This will likely reboot more than just the sound trigger HAL. + // The rest of the system should be able to tolerate that. + rebootHal(); + } + throw e; + } + } } /** diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java index da1b7f3113c41..23259558eeb79 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java @@ -149,13 +149,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware e.getMessage()); } - /* Throwing an exception is not enough in this case. When the HAL behaves unexpectedly, the - system service and the HAL must be reset and the client must be notified. Without a full - reset in this catastrophic case, the state of the HAL and the system service cannot be - guaranteed to the client. - */ - Log.wtf(TAG, "Crashing system server due to unrecoverable exception", e); - Process.killProcess(Process.myPid()); + Log.wtf(TAG, "Unexpected exception", e); throw new InternalServerError(e); } From 99b8d33cbcded1c19b4ee0add68eb50c5e8a5ec3 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Mon, 13 Apr 2020 18:27:25 -0700 Subject: [PATCH 146/182] Update destination bounds if rotation finishes first When the entering pip transition is on-going and rotation finishes first, simply schedule a resize on the PiP window Bug: 153827966 Test: repeatedly enter/exit PiP with Play Movies Change-Id: Ie9bf7fbc44970d4fe03b7febde5d69c7348e5bb9 (cherry picked from commit e0412d1fdb0a09f6b1e77960dd4788c898311fa9) --- .../com/android/systemui/pip/PipTaskOrganizer.java | 10 ++++++++-- .../com/android/systemui/pip/phone/PipManager.java | 13 +++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index f89a01e0c73b9..0125153542c1c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -322,13 +322,19 @@ public class PipTaskOrganizer extends TaskOrganizer { * @param destinationBoundsOut the current destination bounds will be populated to this param */ @SuppressWarnings("unchecked") - public void onMovementBoundsChanged(Rect destinationBoundsOut, + public void onMovementBoundsChanged(Rect destinationBoundsOut, boolean fromRotation, boolean fromImeAdjustment, boolean fromShelfAdjustment) { final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController.getCurrentAnimator(); - destinationBoundsOut.set(mLastReportedBounds); if (animator == null || !animator.isRunning() || animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) { + if (mInPip && fromRotation) { + // this could happen if rotation finishes before the animation + mLastReportedBounds.set(destinationBoundsOut); + scheduleFinishResizePip(mLastReportedBounds); + } else if (!mLastReportedBounds.isEmpty()) { + destinationBoundsOut.set(mLastReportedBounds); + } return; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index a2667d9a4c746..c3779efcf4b29 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -97,8 +97,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds, displayId, fromRotation, toRotation, t); if (changed) { - updateMovementBounds(mTmpNormalBounds, false /* fromImeAdjustment */, - false /* fromShelfAdjustment */); + updateMovementBounds(mTmpNormalBounds, true /* fromRotation */, + false /* fromImeAdjustment */, false /* fromShelfAdjustment */); } }; @@ -163,7 +163,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio @Override public void onMovementBoundsChanged(boolean fromImeAdjustment) { mHandler.post(() -> updateMovementBounds(null /* toBounds */, - fromImeAdjustment, false /* fromShelfAdjustment */)); + false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */)); } @Override @@ -294,7 +294,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio if (changed) { mTouchHandler.onShelfVisibilityChanged(visible, height); updateMovementBounds(mPipBoundsHandler.getLastDestinationBounds(), - false /* fromImeAdjustment */, true /* fromShelfAdjustment */); + false /* fromRotation */, false /* fromImeAdjustment */, + true /* fromShelfAdjustment */); } }); } @@ -353,7 +354,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mMenuController.onPinnedStackAnimationEnded(); } - private void updateMovementBounds(@Nullable Rect toBounds, + private void updateMovementBounds(@Nullable Rect toBounds, boolean fromRotation, boolean fromImeAdjustment, boolean fromShelfAdjustment) { // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler before // passing to mTouchHandler/mPipTaskOrganizer @@ -361,7 +362,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, outBounds, mTmpDisplayInfo); // mTouchHandler would rely on the bounds populated from mPipTaskOrganizer - mPipTaskOrganizer.onMovementBoundsChanged(outBounds, + mPipTaskOrganizer.onMovementBoundsChanged(outBounds, fromRotation, fromImeAdjustment, fromShelfAdjustment); mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, outBounds, fromImeAdjustment, fromShelfAdjustment, From 0abadeca7f5ba07837bdca7a849358b501ffb5cd Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Fri, 10 Apr 2020 02:07:30 +0800 Subject: [PATCH 147/182] Re-send the IME control after IME is re-created The control would be revoked when setting window to the insets source provider. So this CL updates the control target again after IME window is set to the provider, and also refines the timing about updating IME control target. Fix: 152185205 Fix: 152698568 Fix: 153831557 Test: atest NexusLauncherTests:MemoryTests MultiDisplayClientTests Test: 1. Add Traditional Chinese as a secondary language in Setitngs. 2. Launch soft keyboard in Messages and use ZhuYin keyboard. 3. Tap microphone icon repeatedly (this will re-create IME). 4. See if the soft keyboard is missing. Test: Also make sure b/149920295 and b/152410995 stay fixed. Change-Id: Ic113f564e964ebb0ab3375cf1df78b3f912169da (cherry picked from commit fdec32c83f7dd828bb962833f220bbf5bc5f7d71) --- .../com/android/server/wm/DisplayContent.java | 36 ++++++++++++------- .../server/wm/WindowManagerService.java | 14 +++++--- .../com/android/server/wm/WindowState.java | 5 +++ 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8d46a6769bc82..c24d83efe5a37 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -73,7 +73,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_TASK_OPEN; import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; -import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; @@ -199,7 +198,6 @@ import android.view.ViewRootImpl; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManagerPolicyConstants.PointerEventListener; -import android.window.ITaskOrganizer; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; @@ -539,6 +537,15 @@ class DisplayContent extends WindowContainer implements WindowManagerP @Override void onDisplayChanged(DisplayContent dc) { + if (dc != null && mDisplayContent != null + && mDisplayContent.mInputMethodInputTarget == this) { + dc.setInputMethodInputTarget(mDisplayContent.mInputMethodInputTarget); + mDisplayContent.mInputMethodInputTarget = null; + } super.onDisplayChanged(dc); // Window was not laid out for this display yet, so make sure mLayoutSeq does not match. if (dc != null && mInputWindowHandle.displayId != dc.getDisplayId()) { From 94891ea9623490eafc82be1c9cf1c11b50c66c45 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 9 Apr 2020 14:54:13 +0200 Subject: [PATCH 148/182] Only give DisplayInsetsController control over IME in split-screen There is additional jank risk as well as animation curves aren't fully aligned with InsetsController, we should limit the scope where we use that controller for now. Once we have better alignment with InsetsController, we can expand it's usage again. Test: DisplayContentTests Test: Open IME in Bubbles Bug: 152197007 Change-Id: Ic8e925842b28c08fc6ea9ba58c7c05627b5a4eaa (cherry picked from commit 54bf9cbaf858e1f30d4fc1ca17da4dacc2b50721) --- .../com/android/server/wm/DisplayContent.java | 57 +++++------- .../server/wm/DisplayContentTests.java | 87 ++++++++++++++----- 2 files changed, 90 insertions(+), 54 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2a676e1de5afb..0064a5eea1661 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; @@ -141,6 +142,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; +import android.app.WindowConfiguration; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.ScreenOrientation; @@ -3370,34 +3372,18 @@ class DisplayContent extends WindowContainer Date: Wed, 15 Apr 2020 14:53:17 -0700 Subject: [PATCH 149/182] Fix NPE when ranking update causes reinflation Pass in the NEM inflation callback to RowBinderImpl's onNotificationRankingUpdated since changes in state in ranking can trigger inflation (smart replies and conversations) Also go ahead and support null callbacks in inflateContentViews. Bug: 154028814 Test: build Change-Id: I265e2a9e6b707bd908ce8c1ae5957cfe76973a5f (cherry picked from commit 1390930fe5084cce01e9bc45d7d7674da90fa81a) --- .../notification/NotificationEntryManager.java | 3 ++- .../collection/inflation/NotificationRowBinder.java | 3 ++- .../inflation/NotificationRowBinderImpl.java | 11 +++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index d37e16b176200..75493f89993b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -699,7 +699,8 @@ public class NotificationEntryManager implements entry, oldImportances.get(entry.getKey()), oldAdjustments.get(entry.getKey()), - NotificationUiAdjustment.extractFromNotificationEntry(entry)); + NotificationUiAdjustment.extractFromNotificationEntry(entry), + mInflationCallback); } updateNotifications("updateNotificationRanking"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java index f4c4924b4b9ae..710b137d27954 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java @@ -51,5 +51,6 @@ public interface NotificationRowBinder { NotificationEntry entry, @Nullable Integer oldImportance, NotificationUiAdjustment oldAdjustment, - NotificationUiAdjustment newAdjustment); + NotificationUiAdjustment newAdjustment, + NotificationRowContentBinder.InflationCallback callback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index 73f12f86e52e5..e6a4cff0d8930 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -180,13 +180,14 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { NotificationEntry entry, @Nullable Integer oldImportance, NotificationUiAdjustment oldAdjustment, - NotificationUiAdjustment newAdjustment) { + NotificationUiAdjustment newAdjustment, + NotificationRowContentBinder.InflationCallback callback) { if (NotificationUiAdjustment.needReinflate(oldAdjustment, newAdjustment)) { if (entry.rowExists()) { ExpandableNotificationRow row = entry.getRow(); row.reset(); updateRow(entry, row); - inflateContentViews(entry, row, null /* callback */); + inflateContentViews(entry, row, callback); } else { // Once the RowInflaterTask is done, it will pick up the updated entry, so // no-op here. @@ -221,7 +222,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { private void inflateContentViews( NotificationEntry entry, ExpandableNotificationRow row, - NotificationRowContentBinder.InflationCallback inflationCallback) { + @Nullable NotificationRowContentBinder.InflationCallback inflationCallback) { final boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(entry.getSbn(), entry.getImportance()); final boolean isLowPriority = entry.isAmbient(); @@ -238,7 +239,9 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { mRowContentBindStage.requestRebind(entry, en -> { row.setUsesIncreasedCollapsedHeight(useIncreasedCollapsedHeight); row.setIsLowPriority(isLowPriority); - inflationCallback.onAsyncInflationFinished(en); + if (inflationCallback != null) { + inflationCallback.onAsyncInflationFinished(en); + } }); } From 2a35ae262b86356248bfc49f8cee1bffae642f56 Mon Sep 17 00:00:00 2001 From: Aran Ink Date: Mon, 20 Apr 2020 16:04:29 -0400 Subject: [PATCH 150/182] Ensure power menu overflow dismissed when dialog dismissed. Test: Manual -- pressing power button while power overflow menu is shown does not result in overflow menu still appearing on lock screen. Fixes: 154441764 Change-Id: Icc7d158a7ff78b06d2234a5a11eb10b3c75a5ba7 (cherry picked from commit 6560ab752dd54e5e8e6d5c756e52cd6984a522fa) --- .../systemui/globalactions/GlobalActionsDialog.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 2c1bd2186dea1..d6df1940849be 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -2220,6 +2220,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, }) .start(); dismissPanel(); + dismissOverflow(); resetOrientation(); } @@ -2227,6 +2228,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mShowing = false; if (mControlsUiController != null) mControlsUiController.hide(); dismissPanel(); + dismissOverflow(); resetOrientation(); completeDismiss(); } @@ -2243,6 +2245,12 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } } + private void dismissOverflow() { + if (mOverflowPopup != null) { + mOverflowPopup.dismiss(); + } + } + private void setRotationSuggestionsEnabled(boolean enabled) { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); From 6117e4ded2d11f81b2d3241654cc7f053af1d7d6 Mon Sep 17 00:00:00 2001 From: Aran Ink Date: Tue, 21 Apr 2020 14:25:46 -0400 Subject: [PATCH 151/182] Disable overflow menu on lock screen. Test: Manual -- overflow menu does not appear when power menu launched from keyguard. All items appear in one row. Fixes: 154441764 Change-Id: I5430b08749603e9d4fcbbbedeeb9644966235d1d (cherry picked from commit cf313aaaad8a76b2b8ae55d54f1753268c1d3dc3) --- .../android/systemui/globalactions/GlobalActionsDialog.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 322660521ee08..910a7e33bcc41 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -479,7 +479,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, */ @VisibleForTesting protected int getMaxShownPowerItems() { - if (shouldUseControlsLayout()) { + // TODO: Overflow disabled on keyguard while we solve for touch blocking issues. + if (shouldUseControlsLayout() && !mKeyguardShowing) { return mResources.getInteger(com.android.systemui.R.integer.power_menu_max_columns); } else { return Integer.MAX_VALUE; From baa7b8d6938190ab7fe5c208edb6774dc0c75970 Mon Sep 17 00:00:00 2001 From: Taran Singh Date: Mon, 20 Apr 2020 17:10:41 -0700 Subject: [PATCH 152/182] Fix Ime consumer isRequestedVisible isRequestedVisible() was mistakenly missed from previous commit I93dd5790e1fb3d7841ad1323a45cd3bae2d6e9b8 Fix: 154440912 Test: atest ImeInsetsControllerTest WindowInsetsControllerTests Change-Id: I958fc5747382109aa2f21bc1067a28746e7242d8 (cherry picked from commit 335ffd017c9bc984bd16f65d6fb5b6bf1b702e39) --- core/java/android/view/ImeInsetsSourceConsumer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index bdc8ba835fbed..df891303bb1d1 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -153,7 +153,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override protected boolean isRequestedVisibleAwaitingControl() { - return mIsRequestedVisibleAwaitingControl; + return mIsRequestedVisibleAwaitingControl || isRequestedVisible(); } private boolean isDummyOrEmptyEditor(EditorInfo info) { From d6b2b8c66317e800db7f3fb6134602e4c6cb23b7 Mon Sep 17 00:00:00 2001 From: Michael Groover Date: Wed, 22 Apr 2020 09:32:47 -0700 Subject: [PATCH 153/182] Add READ_PHONE_STATE back to pregranted phone permissions When READ_PHONE_STATE was moved from a runtime permission to an install permission it was removed from the default phone permissions grant. Now that READ_PHONE_STATE has been reverted back to a runtime permission it needs to be added back to the list of phone permissions that are pregranted. Bug: 154572075 Bug: 154567729 Test: Verified com.google.shared.uid was granted READ_PHONE_STATE Change-Id: I0e0727ed92cbf881d89d56de4e509fb1a9073556 (cherry picked from commit 140e55b469483d110aad3f664ee08727a924e026) --- .../server/pm/permission/DefaultPermissionGrantPolicy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index e3faffa0699bf..a635f982d37db 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -125,6 +125,7 @@ public final class DefaultPermissionGrantPolicy { static { + PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE); PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE); PHONE_PERMISSIONS.add(Manifest.permission.READ_CALL_LOG); PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG); From 102efbcc8c5e0927b2414830a1ddba092301fa8f Mon Sep 17 00:00:00 2001 From: Michael Groover Date: Wed, 22 Apr 2020 09:32:47 -0700 Subject: [PATCH 154/182] Add READ_PHONE_STATE back to pregranted phone permissions When READ_PHONE_STATE was moved from a runtime permission to an install permission it was removed from the default phone permissions grant. Now that READ_PHONE_STATE has been reverted back to a runtime permission it needs to be added back to the list of phone permissions that are pregranted. Bug: 154572075 Bug: 154567729 Test: Verified com.google.shared.uid was granted READ_PHONE_STATE Change-Id: I0e0727ed92cbf881d89d56de4e509fb1a9073556 (cherry picked from commit 140e55b469483d110aad3f664ee08727a924e026) --- .../server/pm/permission/DefaultPermissionGrantPolicy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index e3faffa0699bf..a635f982d37db 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -125,6 +125,7 @@ public final class DefaultPermissionGrantPolicy { static { + PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE); PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE); PHONE_PERMISSIONS.add(Manifest.permission.READ_CALL_LOG); PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG); From 1a5005f804fb51afcff2562af1a688b81b4c50ad Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Tue, 21 Apr 2020 13:46:08 -0700 Subject: [PATCH 155/182] Add delay between quota check alarms. Since we don't need to mark existing jobs as in quota immediately when the quota status changes, adding a min delay between quota check alarms will prevent the system from possibly spinning on checking quotas. Bug: 154444435 Test: atest CtsJobSchedulerTestCases Test: atest QuotaControllerTest Change-Id: I5b5efe9c973090c0f413812afc7479f012768c44 (cherry picked from commit 7e4fc4dcf0b6f3928927fe8ec3e1f631891d246d) --- .../job/controllers/QuotaController.java | 33 +++++++++++++++++-- core/proto/android/server/jobscheduler.proto | 4 ++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index 7256371102f5b..8c55b50957da8 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -1863,6 +1863,9 @@ public final class QuotaController extends StateController { /** The next time the alarm is set to go off, in the elapsed realtime timebase. */ @GuardedBy("mLock") private long mTriggerTimeElapsed = 0; + /** The minimum amount of time between quota check alarms. */ + @GuardedBy("mLock") + private long mMinQuotaCheckDelayMs = QcConstants.DEFAULT_MIN_QUOTA_CHECK_DELAY_MS; @GuardedBy("mLock") void addAlarmLocked(int userId, @NonNull String pkgName, long inQuotaTimeElapsed) { @@ -1872,6 +1875,11 @@ public final class QuotaController extends StateController { setNextAlarmLocked(); } + @GuardedBy("mLock") + void setMinQuotaCheckDelayMs(long minDelayMs) { + mMinQuotaCheckDelayMs = minDelayMs; + } + @GuardedBy("mLock") void removeAlarmLocked(@NonNull Package pkg) { if (mAlarmQueue.remove(pkg)) { @@ -1902,8 +1910,14 @@ public final class QuotaController extends StateController { @GuardedBy("mLock") private void setNextAlarmLocked() { + setNextAlarmLocked(sElapsedRealtimeClock.millis()); + } + + @GuardedBy("mLock") + private void setNextAlarmLocked(long earliestTriggerElapsed) { if (mAlarmQueue.size() > 0) { - final long nextTriggerTimeElapsed = mAlarmQueue.peek().second; + final long nextTriggerTimeElapsed = Math.max(earliestTriggerElapsed, + mAlarmQueue.peek().second); // Only schedule the alarm if one of the following is true: // 1. There isn't one currently scheduled // 2. The new alarm is significantly earlier than the previous alarm. If it's @@ -1939,7 +1953,7 @@ public final class QuotaController extends StateController { break; } } - setNextAlarmLocked(); + setNextAlarmLocked(sElapsedRealtimeClock.millis() + mMinQuotaCheckDelayMs); } } @@ -2022,6 +2036,7 @@ public final class QuotaController extends StateController { "max_session_count_per_rate_limiting_window"; private static final String KEY_TIMING_SESSION_COALESCING_DURATION_MS = "timing_session_coalescing_duration_ms"; + private static final String KEY_MIN_QUOTA_CHECK_DELAY_MS = "min_quota_check_delay_ms"; private static final long DEFAULT_ALLOWED_TIME_PER_PERIOD_MS = 10 * 60 * 1000L; // 10 minutes @@ -2062,6 +2077,7 @@ public final class QuotaController extends StateController { private static final int DEFAULT_MAX_SESSION_COUNT_RESTRICTED = 1; // 1/day private static final int DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 20; private static final long DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS = 5000; // 5 seconds + private static final long DEFAULT_MIN_QUOTA_CHECK_DELAY_MS = MINUTE_IN_MILLIS; /** How much time each app will have to run jobs within their standby bucket window. */ public long ALLOWED_TIME_PER_PERIOD_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_MS; @@ -2195,6 +2211,9 @@ public final class QuotaController extends StateController { public long TIMING_SESSION_COALESCING_DURATION_MS = DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS; + /** The minimum amount of time between quota check alarms. */ + public long MIN_QUOTA_CHECK_DELAY_MS = DEFAULT_MIN_QUOTA_CHECK_DELAY_MS; + // Safeguards /** The minimum number of jobs that any bucket will be allowed to run within its window. */ @@ -2288,6 +2307,8 @@ public final class QuotaController extends StateController { TIMING_SESSION_COALESCING_DURATION_MS = mParser.getLong( KEY_TIMING_SESSION_COALESCING_DURATION_MS, DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS); + MIN_QUOTA_CHECK_DELAY_MS = mParser.getDurationMillis(KEY_MIN_QUOTA_CHECK_DELAY_MS, + DEFAULT_MIN_QUOTA_CHECK_DELAY_MS); updateConstants(); } @@ -2433,6 +2454,11 @@ public final class QuotaController extends StateController { mTimingSessionCoalescingDurationMs = newSessionCoalescingDurationMs; changed = true; } + // Don't set changed to true for this one since we don't need to re-evaluate + // execution stats or constraint status. Limit the delay to the range [0, 15] + // minutes. + mInQuotaAlarmListener.setMinQuotaCheckDelayMs( + Math.min(15 * MINUTE_IN_MILLIS, Math.max(0, MIN_QUOTA_CHECK_DELAY_MS))); if (changed) { // Update job bookkeeping out of band. @@ -2475,6 +2501,7 @@ public final class QuotaController extends StateController { MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW).println(); pw.printPair(KEY_TIMING_SESSION_COALESCING_DURATION_MS, TIMING_SESSION_COALESCING_DURATION_MS).println(); + pw.printPair(KEY_MIN_QUOTA_CHECK_DELAY_MS, MIN_QUOTA_CHECK_DELAY_MS).println(); pw.decreaseIndent(); } @@ -2520,6 +2547,8 @@ public final class QuotaController extends StateController { MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW); proto.write(ConstantsProto.QuotaController.TIMING_SESSION_COALESCING_DURATION_MS, TIMING_SESSION_COALESCING_DURATION_MS); + proto.write(ConstantsProto.QuotaController.MIN_QUOTA_CHECK_DELAY_MS, + MIN_QUOTA_CHECK_DELAY_MS); proto.end(qcToken); } } diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto index b678d627d48c4..ec99684bf6366 100644 --- a/core/proto/android/server/jobscheduler.proto +++ b/core/proto/android/server/jobscheduler.proto @@ -308,8 +308,10 @@ message ConstantsProto { // Treat two distinct {@link TimingSession}s as the same if they start and end within this // amount of time of each other. optional int64 timing_session_coalescing_duration_ms = 18; + // The minimum amount of time between quota check alarms. + optional int64 min_quota_check_delay_ms = 23; - // Next tag: 23 + // Next tag: 24 } optional QuotaController quota_controller = 24; From c2acf99d6e1e2856d628b695fc7af6bc972712b6 Mon Sep 17 00:00:00 2001 From: Michael Groover Date: Wed, 22 Apr 2020 09:32:47 -0700 Subject: [PATCH 156/182] Add READ_PHONE_STATE back to pregranted phone permissions When READ_PHONE_STATE was moved from a runtime permission to an install permission it was removed from the default phone permissions grant. Now that READ_PHONE_STATE has been reverted back to a runtime permission it needs to be added back to the list of phone permissions that are pregranted. Bug: 154572075 Bug: 154567729 Test: Verified com.google.shared.uid was granted READ_PHONE_STATE Change-Id: I0e0727ed92cbf881d89d56de4e509fb1a9073556 (cherry picked from commit 140e55b469483d110aad3f664ee08727a924e026) --- .../server/pm/permission/DefaultPermissionGrantPolicy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index e3faffa0699bf..a635f982d37db 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -125,6 +125,7 @@ public final class DefaultPermissionGrantPolicy { static { + PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE); PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE); PHONE_PERMISSIONS.add(Manifest.permission.READ_CALL_LOG); PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG); From 1bb43b6c4cdd2c94c39491fae609ff286fa2b2b1 Mon Sep 17 00:00:00 2001 From: Beth Thibodeau Date: Mon, 27 Apr 2020 14:17:08 -0400 Subject: [PATCH 157/182] Check URI is valid for loading images ImageDecoder requires URIs to have a scheme of type SCHEME_CONTENT, SCHEME_ANDROID_RESOURCE, or SCHEME_FILE In addition URI scheme being null was causing NPE since ImageDecoder does not check for that. Fixes: 155021174 Test: manual Change-Id: I724c8b7e1000c2fc5b3910550ec69904da079bce (cherry picked from commit dba74bcfa8897da3644df1f97e69ab5f13c23a1c) --- .../android/systemui/media/MediaControlPanel.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 683c7934908ba..f6bd948fe11bb 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -19,6 +19,7 @@ package com.android.systemui.media; import android.annotation.LayoutRes; import android.app.PendingIntent; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -39,6 +40,7 @@ import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.net.Uri; import android.service.media.MediaBrowserService; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -431,7 +433,7 @@ public class MediaControlPanel { // First look in URI fields for (String field : ART_URIS) { String uriString = metadata.getString(field); - if (uriString != null) { + if (!TextUtils.isEmpty(uriString)) { albumArt = loadBitmapFromUri(Uri.parse(uriString)); if (albumArt != null) { Log.d(TAG, "loaded art from " + field); @@ -459,6 +461,17 @@ public class MediaControlPanel { * @return bitmap, or null if couldn't be loaded */ private Bitmap loadBitmapFromUri(Uri uri) { + // ImageDecoder requires a scheme of the following types + if (uri.getScheme() == null) { + return null; + } + + if (!uri.getScheme().equals(ContentResolver.SCHEME_CONTENT) + && !uri.getScheme().equals(ContentResolver.SCHEME_ANDROID_RESOURCE) + && !uri.getScheme().equals(ContentResolver.SCHEME_FILE)) { + return null; + } + ImageDecoder.Source source = ImageDecoder.createSource(mContext.getContentResolver(), uri); try { return ImageDecoder.decodeBitmap(source); From c99a61ac20f661340010e3718fe678fd0a9cad9a Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 12 May 2020 18:37:43 +0000 Subject: [PATCH 158/182] Revert "Fix missing animation when launch activity from notification." This reverts commit 2065eb7d28c258b0315881511c17cdf23b05b4e7. Reason for revert: droidfood blocker b/156322538 Bug: 156322538 Change-Id: I2b63893b95040c17b9dbe8ce9771f57ab7a90ad3 (cherry picked from commit fe40c85543c86e1e7c098e2b983ab793837b7b9f) --- .../phone/NotificationShadeWindowController.java | 9 +-------- .../phone/NotificationShadeWindowViewController.java | 8 +------- .../com/android/systemui/statusbar/phone/StatusBar.java | 2 +- .../statusbar/phone/NotificationShadeWindowViewTest.java | 3 +-- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index 567ddb680848c..fc6a028408911 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -321,8 +321,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, || state.mPanelVisible || state.mKeyguardFadingAway || state.mBouncerShowing || state.mHeadsUpShowing || state.mScrimsVisibility != ScrimController.TRANSPARENT) - || state.mBackgroundBlurRadius > 0 - || state.mLaunchingActivity; + || state.mBackgroundBlurRadius > 0; } private void applyFitsSystemWindows(State state) { @@ -486,11 +485,6 @@ public class NotificationShadeWindowController implements Callback, Dumpable, apply(mCurrentState); } - void setLaunchingActivity(boolean launching) { - mCurrentState.mLaunchingActivity = launching; - apply(mCurrentState); - } - public void setScrimsVisibility(int scrimsVisibility) { mCurrentState.mScrimsVisibility = scrimsVisibility; apply(mCurrentState); @@ -651,7 +645,6 @@ public class NotificationShadeWindowController implements Callback, Dumpable, boolean mForceCollapsed; boolean mForceDozeBrightness; boolean mForceUserActivity; - boolean mLaunchingActivity; boolean mBackdropShowing; boolean mWallpaperSupportsAmbientMode; boolean mNotTouchable; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 0d2589847bcb3..596a607bb8ad9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -93,7 +93,6 @@ public class NotificationShadeWindowViewController { private PhoneStatusBarView mStatusBarView; private PhoneStatusBarTransitions mBarTransitions; private StatusBar mService; - private NotificationShadeWindowController mNotificationShadeWindowController; private DragDownHelper mDragDownHelper; private boolean mDoubleTapEnabled; private boolean mSingleTapEnabled; @@ -431,14 +430,10 @@ public class NotificationShadeWindowViewController { public void setExpandAnimationPending(boolean pending) { mExpandAnimationPending = pending; - mNotificationShadeWindowController - .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning); } public void setExpandAnimationRunning(boolean running) { mExpandAnimationRunning = running; - mNotificationShadeWindowController - .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning); } public void cancelExpandHelper() { @@ -461,9 +456,8 @@ public class NotificationShadeWindowViewController { } } - public void setService(StatusBar statusBar, NotificationShadeWindowController controller) { + public void setService(StatusBar statusBar) { mService = statusBar; - mNotificationShadeWindowController = controller; } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index dd54a3d800fb3..bbf83bc2057a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1001,7 +1001,7 @@ public class StatusBar extends SystemUI implements DemoMode, updateTheme(); inflateStatusBarWindow(); - mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController); + mNotificationShadeWindowViewController.setService(this); mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); // TODO: Deal with the ugliness that comes from having some of the statusbar broken out diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index e04d25b17c710..cc2d1c25de38f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -83,7 +83,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @Mock private NotificationShadeDepthController mNotificationShadeDepthController; @Mock private SuperStatusBarViewFactory mStatusBarViewFactory; - @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Before public void setUp() { @@ -122,7 +121,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mNotificationPanelViewController, mStatusBarViewFactory); mController.setupExpandedStatusBar(); - mController.setService(mStatusBar, mNotificationShadeWindowController); + mController.setService(mStatusBar); mController.setDragDownHelper(mDragDownHelper); } From 07f7b845462ae1b659838ffc786f7116764d35da Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Tue, 12 May 2020 20:23:16 +0000 Subject: [PATCH 159/182] Revert "Prevent NPE in PulseExpansionHandler" This reverts commit 14f069b83ced6680a154753e9d944983e60f78a8. Reason for revert: http://b/156204772 Change-Id: Ie47d41d3d6625d3769005bd46b5dfe20171d5d70 (cherry picked from commit 9a45fe67e97e964e2cb9b2161f3a8a4508a1a52d) --- .../statusbar/PulseExpansionHandler.kt | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt index 02c98ae2867d4..88f148b00cdcc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt @@ -121,14 +121,14 @@ constructor( } override fun onInterceptTouchEvent(event: MotionEvent): Boolean { - return canHandleMotionEvent() && startExpansion(event) + return maybeStartExpansion(event) } - private fun canHandleMotionEvent(): Boolean { - return !wakeUpCoordinator.canShowPulsingHuns || qsExpanded || bouncerShowing - } - - private fun startExpansion(event: MotionEvent): Boolean { + private fun maybeStartExpansion(event: MotionEvent): Boolean { + if (!wakeUpCoordinator.canShowPulsingHuns || qsExpanded || + bouncerShowing) { + return false + } if (velocityTracker == null) { velocityTracker = VelocityTracker.obtain() } @@ -177,14 +177,9 @@ constructor( } override fun onTouchEvent(event: MotionEvent): Boolean { - if (!canHandleMotionEvent()) { - return false + if (!isExpanding) { + return maybeStartExpansion(event) } - - if (!isExpanding || event.actionMasked == MotionEvent.ACTION_DOWN) { - return startExpansion(event) - } - velocityTracker!!.addMovement(event) val y = event.y From ceb752ca8b062cc006597e32674454a5a91a2a10 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 12 May 2020 18:37:43 +0000 Subject: [PATCH 160/182] Revert "Fix missing animation when launch activity from notification." This reverts commit 2065eb7d28c258b0315881511c17cdf23b05b4e7. Reason for revert: droidfood blocker b/156322538 Bug: 156322538 Change-Id: I2b63893b95040c17b9dbe8ce9771f57ab7a90ad3 (cherry picked from commit fe40c85543c86e1e7c098e2b983ab793837b7b9f) --- .../phone/NotificationShadeWindowController.java | 9 +-------- .../phone/NotificationShadeWindowViewController.java | 8 +------- .../com/android/systemui/statusbar/phone/StatusBar.java | 2 +- .../statusbar/phone/NotificationShadeWindowViewTest.java | 3 +-- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index 2e4a929ded5b8..926c1bd7c271a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -321,8 +321,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, || state.mPanelVisible || state.mKeyguardFadingAway || state.mBouncerShowing || state.mHeadsUpShowing || state.mScrimsVisibility != ScrimController.TRANSPARENT) - || state.mBackgroundBlurRadius > 0 - || state.mLaunchingActivity; + || state.mBackgroundBlurRadius > 0; } private void applyFitsSystemWindows(State state) { @@ -486,11 +485,6 @@ public class NotificationShadeWindowController implements Callback, Dumpable, apply(mCurrentState); } - void setLaunchingActivity(boolean launching) { - mCurrentState.mLaunchingActivity = launching; - apply(mCurrentState); - } - public void setScrimsVisibility(int scrimsVisibility) { mCurrentState.mScrimsVisibility = scrimsVisibility; apply(mCurrentState); @@ -651,7 +645,6 @@ public class NotificationShadeWindowController implements Callback, Dumpable, boolean mForceCollapsed; boolean mForceDozeBrightness; boolean mForceUserActivity; - boolean mLaunchingActivity; boolean mBackdropShowing; boolean mWallpaperSupportsAmbientMode; boolean mNotTouchable; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 0d2589847bcb3..596a607bb8ad9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -93,7 +93,6 @@ public class NotificationShadeWindowViewController { private PhoneStatusBarView mStatusBarView; private PhoneStatusBarTransitions mBarTransitions; private StatusBar mService; - private NotificationShadeWindowController mNotificationShadeWindowController; private DragDownHelper mDragDownHelper; private boolean mDoubleTapEnabled; private boolean mSingleTapEnabled; @@ -431,14 +430,10 @@ public class NotificationShadeWindowViewController { public void setExpandAnimationPending(boolean pending) { mExpandAnimationPending = pending; - mNotificationShadeWindowController - .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning); } public void setExpandAnimationRunning(boolean running) { mExpandAnimationRunning = running; - mNotificationShadeWindowController - .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning); } public void cancelExpandHelper() { @@ -461,9 +456,8 @@ public class NotificationShadeWindowViewController { } } - public void setService(StatusBar statusBar, NotificationShadeWindowController controller) { + public void setService(StatusBar statusBar) { mService = statusBar; - mNotificationShadeWindowController = controller; } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index dd54a3d800fb3..bbf83bc2057a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1001,7 +1001,7 @@ public class StatusBar extends SystemUI implements DemoMode, updateTheme(); inflateStatusBarWindow(); - mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController); + mNotificationShadeWindowViewController.setService(this); mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); // TODO: Deal with the ugliness that comes from having some of the statusbar broken out diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index e04d25b17c710..cc2d1c25de38f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -83,7 +83,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @Mock private NotificationShadeDepthController mNotificationShadeDepthController; @Mock private SuperStatusBarViewFactory mStatusBarViewFactory; - @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Before public void setUp() { @@ -122,7 +121,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mNotificationPanelViewController, mStatusBarViewFactory); mController.setupExpandedStatusBar(); - mController.setService(mStatusBar, mNotificationShadeWindowController); + mController.setService(mStatusBar); mController.setDragDownHelper(mDragDownHelper); } From 370b805aafe0c2405af22a069155dcec6e0b73d6 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Tue, 12 May 2020 20:23:16 +0000 Subject: [PATCH 161/182] Revert "Prevent NPE in PulseExpansionHandler" This reverts commit 14f069b83ced6680a154753e9d944983e60f78a8. Reason for revert: http://b/156204772 Change-Id: Ie47d41d3d6625d3769005bd46b5dfe20171d5d70 (cherry picked from commit 9a45fe67e97e964e2cb9b2161f3a8a4508a1a52d) --- .../statusbar/PulseExpansionHandler.kt | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt index 02c98ae2867d4..88f148b00cdcc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt @@ -121,14 +121,14 @@ constructor( } override fun onInterceptTouchEvent(event: MotionEvent): Boolean { - return canHandleMotionEvent() && startExpansion(event) + return maybeStartExpansion(event) } - private fun canHandleMotionEvent(): Boolean { - return !wakeUpCoordinator.canShowPulsingHuns || qsExpanded || bouncerShowing - } - - private fun startExpansion(event: MotionEvent): Boolean { + private fun maybeStartExpansion(event: MotionEvent): Boolean { + if (!wakeUpCoordinator.canShowPulsingHuns || qsExpanded || + bouncerShowing) { + return false + } if (velocityTracker == null) { velocityTracker = VelocityTracker.obtain() } @@ -177,14 +177,9 @@ constructor( } override fun onTouchEvent(event: MotionEvent): Boolean { - if (!canHandleMotionEvent()) { - return false + if (!isExpanding) { + return maybeStartExpansion(event) } - - if (!isExpanding || event.actionMasked == MotionEvent.ACTION_DOWN) { - return startExpansion(event) - } - velocityTracker!!.addMovement(event) val y = event.y From 20d4c6e969fae55b9c8c5055291b8567a7f98b66 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 12 May 2020 18:37:43 +0000 Subject: [PATCH 162/182] Revert "Fix missing animation when launch activity from notification." This reverts commit 2065eb7d28c258b0315881511c17cdf23b05b4e7. Reason for revert: droidfood blocker b/156322538 Bug: 156322538 Change-Id: I2b63893b95040c17b9dbe8ce9771f57ab7a90ad3 (cherry picked from commit fe40c85543c86e1e7c098e2b983ab793837b7b9f) --- .../phone/NotificationShadeWindowController.java | 9 +-------- .../phone/NotificationShadeWindowViewController.java | 8 +------- .../com/android/systemui/statusbar/phone/StatusBar.java | 2 +- .../statusbar/phone/NotificationShadeWindowViewTest.java | 3 +-- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index 2e4a929ded5b8..926c1bd7c271a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -321,8 +321,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, || state.mPanelVisible || state.mKeyguardFadingAway || state.mBouncerShowing || state.mHeadsUpShowing || state.mScrimsVisibility != ScrimController.TRANSPARENT) - || state.mBackgroundBlurRadius > 0 - || state.mLaunchingActivity; + || state.mBackgroundBlurRadius > 0; } private void applyFitsSystemWindows(State state) { @@ -486,11 +485,6 @@ public class NotificationShadeWindowController implements Callback, Dumpable, apply(mCurrentState); } - void setLaunchingActivity(boolean launching) { - mCurrentState.mLaunchingActivity = launching; - apply(mCurrentState); - } - public void setScrimsVisibility(int scrimsVisibility) { mCurrentState.mScrimsVisibility = scrimsVisibility; apply(mCurrentState); @@ -651,7 +645,6 @@ public class NotificationShadeWindowController implements Callback, Dumpable, boolean mForceCollapsed; boolean mForceDozeBrightness; boolean mForceUserActivity; - boolean mLaunchingActivity; boolean mBackdropShowing; boolean mWallpaperSupportsAmbientMode; boolean mNotTouchable; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 0d2589847bcb3..596a607bb8ad9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -93,7 +93,6 @@ public class NotificationShadeWindowViewController { private PhoneStatusBarView mStatusBarView; private PhoneStatusBarTransitions mBarTransitions; private StatusBar mService; - private NotificationShadeWindowController mNotificationShadeWindowController; private DragDownHelper mDragDownHelper; private boolean mDoubleTapEnabled; private boolean mSingleTapEnabled; @@ -431,14 +430,10 @@ public class NotificationShadeWindowViewController { public void setExpandAnimationPending(boolean pending) { mExpandAnimationPending = pending; - mNotificationShadeWindowController - .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning); } public void setExpandAnimationRunning(boolean running) { mExpandAnimationRunning = running; - mNotificationShadeWindowController - .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning); } public void cancelExpandHelper() { @@ -461,9 +456,8 @@ public class NotificationShadeWindowViewController { } } - public void setService(StatusBar statusBar, NotificationShadeWindowController controller) { + public void setService(StatusBar statusBar) { mService = statusBar; - mNotificationShadeWindowController = controller; } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index dd54a3d800fb3..bbf83bc2057a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1001,7 +1001,7 @@ public class StatusBar extends SystemUI implements DemoMode, updateTheme(); inflateStatusBarWindow(); - mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController); + mNotificationShadeWindowViewController.setService(this); mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); // TODO: Deal with the ugliness that comes from having some of the statusbar broken out diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index e04d25b17c710..cc2d1c25de38f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -83,7 +83,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @Mock private NotificationShadeDepthController mNotificationShadeDepthController; @Mock private SuperStatusBarViewFactory mStatusBarViewFactory; - @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Before public void setUp() { @@ -122,7 +121,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mNotificationPanelViewController, mStatusBarViewFactory); mController.setupExpandedStatusBar(); - mController.setService(mStatusBar, mNotificationShadeWindowController); + mController.setService(mStatusBar); mController.setDragDownHelper(mDragDownHelper); } From da7a774b7812f77f1e7fe5408496431458576cb2 Mon Sep 17 00:00:00 2001 From: Jay Aliomer Date: Tue, 5 May 2020 23:52:48 -0400 Subject: [PATCH 163/182] Adding UiModeManager Custom Tests Bug: 153352890 Test: atest UiModeManagerTest Change-Id: I2aa5335da98924713f6c514a6784f248871cc648 From b3b7262b72714e83429a1c83671ddc5dfe4562e9 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Mon, 18 May 2020 13:23:33 -0400 Subject: [PATCH 164/182] Fix crash caused by unhandled bucket We no longer handle all buckets inside of the `when` block, so the default case should no longer throw an error. Fixes: 156866868 Test: manual, atest Change-Id: Ib811165d8b09bca4f3045d4408ac250ef4b9bafa (cherry picked from commit 64320cc2de142984b7e04224e30c796fb0aaaf3a) --- .../statusbar/notification/stack/NotificationSectionsManager.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index 65633a2e209f1..e39a4a0c799fe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -360,7 +360,6 @@ class NotificationSectionsManager @Inject internal constructor( } } } - else -> throw IllegalStateException("Cannot find section bucket for view") } prev = child From 8f818fd481444697cda4aa48f70cca4d2f14c22c Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Mon, 18 May 2020 11:27:32 -0700 Subject: [PATCH 165/182] Fixed a bug where the brighness mirror would make everything invisible Because of some new animation optimization, this could lead to issues where we weren't cancelling the animation in one side case. Fixes: 156569031 Test: tap on brightness mirror, observe Change-Id: I18164b16a612431f8b3ec87a5b5834c0f48dd761 (cherry picked from commit 7d9d378b283c03d8ccc5f35d1f18424ab36549e7) --- .../systemui/statusbar/notification/PropertyAnimator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java index b1b6a1c12a0a2..3517e245f6242 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java @@ -92,6 +92,9 @@ public class PropertyAnimator { AnimatorListenerAdapter listener = properties.getAnimationFinishListener(property); if (currentValue.equals(newEndValue)) { // Skip the animation! + if (previousAnimator != null) { + previousAnimator.cancel(); + } if (listener != null) { listener.onAnimationEnd(null); } From d42403f14994ad2331deb7f3f991e77a92cd1a3f Mon Sep 17 00:00:00 2001 From: Beverly Tai Date: Mon, 18 May 2020 17:08:20 +0000 Subject: [PATCH 166/182] Revert "Don't readd pending notifs to NEM's allNotifs list" This reverts commit cb5e62cc500a5a1b770e2a48b6e5deacd0134db9. Reason for revert: cause of regression b/156874301 Change-Id: If88f1d508180ae7b2e40f11386d5a6b66b639750 (cherry picked from commit 11c576145784b8aafb5b808c8c9f11c7b85b7719) --- .../NotificationEntryManager.java | 54 ++++++++----------- .../NotificationEntryManagerTest.java | 22 -------- 2 files changed, 21 insertions(+), 55 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 2be1531850c54..d6471243e0539 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -151,16 +151,6 @@ public class NotificationEntryManager implements @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("NotificationEntryManager state:"); - pw.println(" mAllNotifications="); - if (mAllNotifications.size() == 0) { - pw.println("null"); - } else { - int i = 0; - for (NotificationEntry entry : mAllNotifications) { - dumpEntry(pw, " ", i, entry); - i++; - } - } pw.print(" mPendingNotifications="); if (mPendingNotifications.size() == 0) { pw.println("null"); @@ -360,8 +350,8 @@ public class NotificationEntryManager implements private final NotificationHandler mNotifListener = new NotificationHandler() { @Override public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) { - final boolean isUpdateToInflatedNotif = mActiveNotifications.containsKey(sbn.getKey()); - if (isUpdateToInflatedNotif) { + final boolean isUpdate = mActiveNotifications.containsKey(sbn.getKey()); + if (isUpdate) { updateNotification(sbn, rankingMap); } else { addNotification(sbn, rankingMap); @@ -452,12 +442,16 @@ public class NotificationEntryManager implements } if (!lifetimeExtended) { // At this point, we are guaranteed the notification will be removed - abortExistingInflation(key, "removeNotification"); mAllNotifications.remove(pendingEntry); - mLeakDetector.trackGarbage(pendingEntry); } } - } else { + } + + if (!lifetimeExtended) { + abortExistingInflation(key, "removeNotification"); + } + + if (entry != null) { // If a manager needs to keep the notification around for whatever reason, we // keep the notification boolean entryDismissed = entry.isRowDismissed(); @@ -475,8 +469,6 @@ public class NotificationEntryManager implements if (!lifetimeExtended) { // At this point, we are guaranteed the notification will be removed - abortExistingInflation(key, "removeNotification"); - mAllNotifications.remove(entry); // Ensure any managers keeping the lifetime extended stop managing the entry cancelLifetimeExtension(entry); @@ -485,10 +477,13 @@ public class NotificationEntryManager implements entry.removeRow(); } + mAllNotifications.remove(entry); + // Let's remove the children if this was a summary handleGroupSummaryRemoved(key); removeVisibleNotification(key); updateNotifications("removeNotificationInternal"); + mLeakDetector.trackGarbage(entry); removedByUser |= entryDismissed; mLogger.logNotifRemoved(entry.getKey(), removedByUser); @@ -502,7 +497,6 @@ public class NotificationEntryManager implements for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryCleanUp(entry); } - mLeakDetector.trackGarbage(entry); } } } @@ -562,24 +556,17 @@ public class NotificationEntryManager implements Ranking ranking = new Ranking(); rankingMap.getRanking(key, ranking); - NotificationEntry entry = mPendingNotifications.get(key); - if (entry != null) { - entry.setSbn(notification); - } else { - entry = new NotificationEntry( - notification, - ranking, - mFgsFeatureController.isForegroundServiceDismissalEnabled(), - SystemClock.uptimeMillis()); - mAllNotifications.add(entry); - mLeakDetector.trackInstance(entry); - } - - abortExistingInflation(key, "addNotification"); - + NotificationEntry entry = new NotificationEntry( + notification, + ranking, + mFgsFeatureController.isForegroundServiceDismissalEnabled(), + SystemClock.uptimeMillis()); for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryBind(entry, notification); } + mAllNotifications.add(entry); + + mLeakDetector.trackInstance(entry); for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryInit(entry); @@ -594,6 +581,7 @@ public class NotificationEntryManager implements mInflationCallback); } + abortExistingInflation(key, "addNotification"); mPendingNotifications.put(key, entry); mLogger.logNotifAdded(entry.getKey()); for (NotificationEntryListener listener : mNotificationEntryListeners) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index a5a5f81bdffe2..d583048fbb268 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -209,28 +209,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase { setUserSentiment(mSbn.getKey(), Ranking.USER_SENTIMENT_NEUTRAL); } - @Test - public void testAddNotification_noDuplicateEntriesCreated() { - // GIVEN a notification has been added - mEntryManager.addNotification(mSbn, mRankingMap); - - // WHEN the same notification is added multiple times before the previous entry (with - // the same key) didn't finish inflating - mEntryManager.addNotification(mSbn, mRankingMap); - mEntryManager.addNotification(mSbn, mRankingMap); - mEntryManager.addNotification(mSbn, mRankingMap); - - // THEN getAllNotifs() only contains exactly one notification with this key - int count = 0; - for (NotificationEntry entry : mEntryManager.getAllNotifs()) { - if (entry.getKey().equals(mSbn.getKey())) { - count++; - } - } - assertEquals("Should only be one entry with key=" + mSbn.getKey() + " in mAllNotifs. " - + "Instead there are " + count, 1, count); - } - @Test public void testAddNotification_setsUserSentiment() { mEntryManager.addNotification(mSbn, mRankingMap); From a40786c7dc6967cdd2c904026a66c35250aba553 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 19 May 2020 16:56:14 +0000 Subject: [PATCH 167/182] Revert "System Bars animation for fixed rotation transform" This reverts commit dca5b93bf9a0ea8ec0b9e4193076cee8cdbcbca9. Reason for revert: b/156868543 Bug: 156868543 Change-Id: Ia59450ef160021494a114715a0035437b28e8d00 (cherry picked from commit 77de74d5392632b34451cbabab43628a04fbc12c) --- .../com/android/server/wm/DisplayContent.java | 14 -- .../android/server/wm/DisplayRotation.java | 2 - .../wm/FixedRotationAnimationController.java | 197 ------------------ .../android/server/wm/SurfaceAnimator.java | 9 +- .../com/android/server/wm/WindowToken.java | 3 - .../server/wm/DisplayContentTests.java | 12 -- 6 files changed, 1 insertion(+), 236 deletions(-) delete mode 100644 services/core/java/com/android/server/wm/FixedRotationAnimationController.java diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0b2bd811bb844..e4fefe9ad86f5 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -498,8 +498,6 @@ class DisplayContent extends WindowContainer mAnimatedWindowStates = new ArrayList<>(2); - private final Runnable[] mDeferredFinishCallbacks; - - public FixedRotationAnimationController(DisplayContent displayContent) { - mWmService = displayContent.mWmService; - addAnimatedWindow(displayContent.getDisplayPolicy().getStatusBar()); - addAnimatedWindow(displayContent.getDisplayPolicy().getNavigationBar()); - mDeferredFinishCallbacks = new Runnable[mAnimatedWindowStates.size()]; - } - - private void addAnimatedWindow(WindowState windowState) { - if (windowState != null) { - mAnimatedWindowStates.add(windowState); - } - } - - /** - * Show the previously hidden {@link WindowToken} if their surfaces have already been rotated. - * - * @return True if the show animation has been started, in which case the caller no longer needs - * this {@link FixedRotationAnimationController}. - */ - boolean show() { - if (!mShowRequested && readyToShow()) { - mShowRequested = true; - for (int i = mAnimatedWindowStates.size() - 1; i >= 0; i--) { - WindowState windowState = mAnimatedWindowStates.get(i); - fadeWindowToken(true, windowState.getParent(), i); - } - return true; - } - return false; - } - - void hide(int targetRotation) { - mTargetRotation = targetRotation; - if (mShowRequested) { - mShowRequested = false; - for (int i = mAnimatedWindowStates.size() - 1; i >= 0; i--) { - WindowState windowState = mAnimatedWindowStates.get(i); - fadeWindowToken(false /* show */, windowState.getParent(), i); - } - } - } - - void cancel() { - for (int i = mAnimatedWindowStates.size() - 1; i >= 0; i--) { - WindowState windowState = mAnimatedWindowStates.get(i); - mShowRequested = true; - fadeWindowToken(true /* show */, windowState.getParent(), i); - } - } - - private void fadeWindowToken(boolean show, WindowContainer windowToken, - int index) { - Animation animation = AnimationUtils.loadAnimation(mWmService.mContext, - show ? R.anim.fade_in : R.anim.fade_out); - LocalAnimationAdapter.AnimationSpec windowAnimationSpec = createAnimationSpec(animation); - - FixedRotationAnimationAdapter animationAdapter = new FixedRotationAnimationAdapter( - windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, index); - - // We deferred the end of the animation when hiding the token, so we need to end it now that - // it's shown again. - SurfaceAnimator.OnAnimationFinishedCallback finishedCallback = show ? (t, r) -> { - if (mDeferredFinishCallbacks[index] != null) { - mDeferredFinishCallbacks[index].run(); - mDeferredFinishCallbacks[index] = null; - } - } : null; - windowToken.startAnimation(windowToken.getPendingTransaction(), animationAdapter, - mShowRequested, ANIMATION_TYPE_FIXED_TRANSFORM, finishedCallback); - } - - /** - * Check if all the mAnimatedWindowState's surfaces have been rotated to the - * mTargetRotation. - */ - private boolean readyToShow() { - for (int i = mAnimatedWindowStates.size() - 1; i >= 0; i--) { - WindowState windowState = mAnimatedWindowStates.get(i); - if (windowState.getConfiguration().windowConfiguration.getRotation() - != mTargetRotation || windowState.mPendingSeamlessRotate != null) { - return false; - } - } - return true; - } - - - private LocalAnimationAdapter.AnimationSpec createAnimationSpec(Animation animation) { - return new LocalAnimationAdapter.AnimationSpec() { - - Transformation mTransformation = new Transformation(); - - @Override - public boolean getShowWallpaper() { - return true; - } - - @Override - public long getDuration() { - return animation.getDuration(); - } - - @Override - public void apply(SurfaceControl.Transaction t, SurfaceControl leash, - long currentPlayTime) { - mTransformation.clear(); - animation.getTransformation(currentPlayTime, mTransformation); - t.setAlpha(leash, mTransformation.getAlpha()); - } - - @Override - public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); - pw.println(animation); - } - - @Override - public void dumpDebugInner(ProtoOutputStream proto) { - final long token = proto.start(WINDOW); - proto.write(ANIMATION, animation.toString()); - proto.end(token); - } - }; - } - - private class FixedRotationAnimationAdapter extends LocalAnimationAdapter { - private final boolean mShow; - private final int mIndex; - - FixedRotationAnimationAdapter(AnimationSpec windowAnimationSpec, - SurfaceAnimationRunner surfaceAnimationRunner, boolean show, int index) { - super(windowAnimationSpec, surfaceAnimationRunner); - mShow = show; - mIndex = index; - } - - @Override - public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { - // We defer the end of the hide animation to ensure the tokens stay hidden until - // we show them again. - if (!mShow) { - mDeferredFinishCallbacks[mIndex] = endDeferFinishCallback; - return true; - } - return false; - } - } -} diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 0143eb1abe032..42342a60ba161 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -488,12 +488,6 @@ class SurfaceAnimator { */ static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5; - /** - * Animation when a fixed rotation transform is applied to a window token. - * @hide - */ - static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6; - /** * Bitmask to include all animation types. This is NOT an {@link AnimationType} * @hide @@ -511,8 +505,7 @@ class SurfaceAnimator { ANIMATION_TYPE_DIMMER, ANIMATION_TYPE_RECENTS, ANIMATION_TYPE_WINDOW_ANIMATION, - ANIMATION_TYPE_INSETS_CONTROL, - ANIMATION_TYPE_FIXED_TRANSFORM + ANIMATION_TYPE_INSETS_CONTROL }) @Retention(RetentionPolicy.SOURCE) @interface AnimationType {} diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 8739bad4398b6..768f89eff774c 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -642,9 +642,6 @@ class WindowToken extends WindowContainer { final int originalRotation = getWindowConfiguration().getRotation(); onConfigurationChanged(parent.getConfiguration()); onCancelFixedRotationTransform(originalRotation); - if (mDisplayContent.mFixedRotationAnimationController != null) { - mDisplayContent.mFixedRotationAnimationController.cancel(); - } } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 7b23bfb48a1a0..ac95a817bec91 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -57,7 +57,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.same; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; -import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; @@ -1060,8 +1059,6 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testApplyTopFixedRotationTransform() { mWm.mIsFixedRotationTransformEnabled = true; - mDisplayContent.getDisplayPolicy().addWindowLw(mStatusBarWindow, mStatusBarWindow.mAttrs); - mDisplayContent.getDisplayPolicy().addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs); final Configuration config90 = new Configuration(); mDisplayContent.computeScreenConfiguration(config90, ROTATION_90); @@ -1082,12 +1079,6 @@ public class DisplayContentTests extends WindowTestsBase { ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */, false /* forceUpdate */)); - assertNotNull(mDisplayContent.mFixedRotationAnimationController); - assertTrue(mStatusBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS, - ANIMATION_TYPE_FIXED_TRANSFORM)); - assertTrue(mNavBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS, - ANIMATION_TYPE_FIXED_TRANSFORM)); - final Rect outFrame = new Rect(); final Rect outInsets = new Rect(); final Rect outStableInsets = new Rect(); @@ -1140,9 +1131,6 @@ public class DisplayContentTests extends WindowTestsBase { assertFalse(app.hasFixedRotationTransform()); assertFalse(app2.hasFixedRotationTransform()); assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation); - - mDisplayContent.finishFixedRotationAnimation(); - assertNull(mDisplayContent.mFixedRotationAnimationController); } @Test From a16a50edfb5b26c6bfcb6efc35b62a580ccfb829 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 20 May 2020 15:01:02 +0000 Subject: [PATCH 168/182] Revert "Flip ENABLE_DYNAMIC_PERMISSIONS." This reverts commit 60e1469c580ab70d8f904e715e3a6d1316cabf66. Bug: 115619667 Bug: 157106728 Reason for revert: b/157106728 Change-Id: I0e658a541659711309ffb166b11867d14ab56dea (cherry picked from commit 6ea250c569c7720a24e344776be60729d8e68a5b) --- .../java/com/android/server/uri/UriGrantsManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 15b6a8df0151e..72cdf4afb0078 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -114,7 +114,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed private static final int MAX_PERSISTED_URI_GRANTS = 128; - private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true; + private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); private final H mH; From 4789a49605f9bb79cfdf7725c1f0c19f7d0c114d Mon Sep 17 00:00:00 2001 From: Nandana Dutt Date: Mon, 1 Jun 2020 08:46:58 +0000 Subject: [PATCH 169/182] Revert "Flip ENABLE_DYNAMIC_PERMISSIONS." This reverts commit 6ab7f6e7a4ff180cd759c7b6c1e5c525587d3f31. Reason for revert: 157863128,157868785 BUG: 157863128,157868785 Change-Id: I9f10f4d98b0d6c122af9f7736de3d096ceb3fde9 (cherry picked from commit e784e680aa3a2367c8bd553377dd5eb6502ba4e5) --- .../java/com/android/server/uri/UriGrantsManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 3796c5fda411b..9476e9260c73f 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -114,7 +114,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed private static final int MAX_PERSISTED_URI_GRANTS = 128; - private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true; + private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); private final H mH; From b4d341837877a6d07d7a297994f2e175865fa991 Mon Sep 17 00:00:00 2001 From: Nandana Dutt Date: Tue, 2 Jun 2020 09:29:02 +0000 Subject: [PATCH 170/182] Revert "Flip ENABLE_DYNAMIC_PERMISSIONS, attempt #4." This reverts commit 14c5c4d9974af798bbad6a6d5a5530f1c1f62d95. Reason for revert: http://b/157970772 BUG: 157970772 Change-Id: I95a35d9b99a7cc6950c7f00e42d11fe07b472a44 (cherry picked from commit 1b8e6766e2ca550fd943756f3955614ce136a09d) --- .../java/com/android/server/uri/UriGrantsManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 3796c5fda411b..9476e9260c73f 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -114,7 +114,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed private static final int MAX_PERSISTED_URI_GRANTS = 128; - private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true; + private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); private final H mH; From 140d341972027f8e0c9da0a49f478ce37ec2088f Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 3 Jun 2020 13:54:04 +0000 Subject: [PATCH 171/182] Revert "Flip ENABLE_DYNAMIC_PERMISSIONS, attempt #5." This reverts commit 836c7089f65da1b8f9ca00c40805aadb0dca569e. Reason for revert: 157863128 Bug: 157863128 Change-Id: I0ec7878c839b397252c975475b4c3a4ff144082e (cherry picked from commit 81ca65d7d506db354d88f103b6214dfacc89a143) --- .../java/com/android/server/uri/UriGrantsManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 5f6323369d0a5..c38d649ada9bd 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -115,7 +115,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed private static final int MAX_PERSISTED_URI_GRANTS = 128; - private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true; + private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); private final H mH; From e6fc5652bda854936d0133346ab47a69379ebd0a Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 3 Jun 2020 16:39:02 +0000 Subject: [PATCH 172/182] Revert "Consolidating MODIFY_AUDIO_SETTINGS permission checks" This reverts commit 7fa00380257b394352cb65bc55cc6e5ec20828f2. Reason for revert: b/158054788 Bug:158054788 Change-Id: If2ef8b4499eea69e7e5f862a851da5414af067ea (cherry picked from commit d68173942c6a6db020bcb17c785086267edd2b96) --- .../android/server/audio/AudioService.java | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index efd3c3e9bfc14..27d9ba08e4a2d 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1908,8 +1908,11 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#adjustVolume(int, int) */ public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller) { + boolean hasModifyAudioSettings = + mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) + == PackageManager.PERMISSION_GRANTED; adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage, - caller, Binder.getCallingUid(), hasModifyAudioSettings(), VOL_ADJUST_NORMAL); + caller, Binder.getCallingUid(), hasModifyAudioSettings, VOL_ADJUST_NORMAL); } private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, @@ -2014,10 +2017,13 @@ public class AudioService extends IAudioService.Stub + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage); return; } + final boolean hasModifyAudioSettings = + mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) + == PackageManager.PERMISSION_GRANTED; sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType, direction/*val1*/, flags/*val2*/, callingPackage)); adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage, - Binder.getCallingUid(), hasModifyAudioSettings(), VOL_ADJUST_NORMAL); + Binder.getCallingUid(), hasModifyAudioSettings, VOL_ADJUST_NORMAL); } protected void adjustStreamVolume(int streamType, int direction, int flags, @@ -2528,10 +2534,13 @@ public class AudioService extends IAudioService.Stub + " MODIFY_AUDIO_ROUTING callingPackage=" + callingPackage); return; } + final boolean hasModifyAudioSettings = + mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) + == PackageManager.PERMISSION_GRANTED; sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType, index/*val1*/, flags/*val2*/, callingPackage)); setStreamVolume(streamType, index, flags, callingPackage, callingPackage, - Binder.getCallingUid(), hasModifyAudioSettings()); + Binder.getCallingUid(), hasModifyAudioSettings); } private boolean canChangeAccessibilityVolume() { @@ -3197,7 +3206,8 @@ public class AudioService extends IAudioService.Stub ensureValidStreamType(streamType); final boolean isPrivileged = Binder.getCallingUid() == Process.SYSTEM_UID - || (hasModifyAudioSettings()) + || (mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) + == PackageManager.PERMISSION_GRANTED) || (mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_ROUTING) == PackageManager.PERMISSION_GRANTED); return (mStreamStates[streamType].getMinIndex(isPrivileged) + 5) / 10; @@ -4755,18 +4765,9 @@ public class AudioService extends IAudioService.Stub handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time); } - private boolean hasModifyAudioSettings() { - return mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS) - == PackageManager.PERMISSION_GRANTED; - } - - private boolean hasModifyAudioSettings(int pid, int uid) { - return mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) - == PackageManager.PERMISSION_GRANTED; - } - boolean checkAudioSettingsPermission(String method) { - if (hasModifyAudioSettings()) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS) + == PackageManager.PERMISSION_GRANTED) { return true; } String msg = "Audio Settings Permission Denial: " + method + " from pid=" @@ -7688,10 +7689,13 @@ public class AudioService extends IAudioService.Stub @Override public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, String callingPackage, int uid, int pid) { + final boolean hasModifyAudioSettings = + mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED; // direction and stream type swap here because the public // adjustSuggested has a different order than the other methods. adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, - callingPackage, uid, hasModifyAudioSettings(pid, uid), VOL_ADJUST_NORMAL); + callingPackage, uid, hasModifyAudioSettings, VOL_ADJUST_NORMAL); } @Override @@ -7702,15 +7706,21 @@ public class AudioService extends IAudioService.Stub direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage) .append(" uid:").append(uid).toString())); } + final boolean hasModifyAudioSettings = + mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED; adjustStreamVolume(streamType, direction, flags, callingPackage, - callingPackage, uid, hasModifyAudioSettings(pid, uid), VOL_ADJUST_NORMAL); + callingPackage, uid, hasModifyAudioSettings, VOL_ADJUST_NORMAL); } @Override public void setStreamVolumeForUid(int streamType, int direction, int flags, String callingPackage, int uid, int pid) { + final boolean hasModifyAudioSettings = + mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED; setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid, - hasModifyAudioSettings(pid, uid)); + hasModifyAudioSettings); } @Override From 71c824c057245c3c36f5b5ae44e3d118162cd8a3 Mon Sep 17 00:00:00 2001 From: Robert Snoeberger Date: Wed, 3 Jun 2020 18:48:19 +0000 Subject: [PATCH 173/182] Revert "Exception if receive move withouth down" This reverts commit a0a20dc23babe74e4ba59262323280367ad76185. Reason for revert: This is causing a number of fatal crashes in SystemUI. See b/158081578, b/158057055, b/158060735, and b/158061923. Fixes: 158081578 Fixes: 158057055 Fixes: 158060735 Fixes: 158061923 Change-Id: If7e6cd4ade3df540ba7d97d9265564132a235292 (cherry picked from commit 0ef6f01bd1f47594af77d5024a8115dfd2b46116) --- core/java/android/view/GestureDetector.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index a9af59543c784..f6c72c4eefbc9 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -288,11 +288,6 @@ public class GestureDetector { */ private VelocityTracker mVelocityTracker; - /** - * True if the detector can throw exception when touch steam is unexpected . - */ - private boolean mExceptionForTouchStream; - /** * Consistency verifier for debugging purposes. */ @@ -472,8 +467,6 @@ public class GestureDetector { mTouchSlopSquare = touchSlop * touchSlop; mDoubleTapTouchSlopSquare = doubleTapTouchSlop * doubleTapTouchSlop; mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop; - mExceptionForTouchStream = context != null - && context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R; } /** @@ -646,13 +639,6 @@ public class GestureDetector { break; case MotionEvent.ACTION_MOVE: - if (mExceptionForTouchStream && !mStillDown) { - throw new IllegalStateException("Incomplete event stream received: " - + "Received ACTION_MOVE before ACTION_DOWN. ACTION_DOWN must precede " - + "ACTION_MOVE following ACTION_UP or ACTION_CANCEL, or when this " - + "GestureDetector has not yet received any events."); - } - if (mInLongPress || mInContextClick) { break; } From 63c959bc9cdd7835018bcd71b5c31074123df18c Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Wed, 3 Jun 2020 20:50:23 -0400 Subject: [PATCH 174/182] Fix missing icon for one-to-one convos Fixes: 158089612 Test: manual Change-Id: If588073ff1df557b755b844277e893e001822d79 (cherry picked from commit 3d360da16dc52a04f36d2c1c05c9d82cd8d76231) --- core/java/android/app/Notification.java | 3 +- .../internal/widget/ConversationLayout.java | 35 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 980fdb87f3fbc..f881616fd35a5 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -7625,7 +7625,6 @@ public class Notification implements Parcelable } boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY; boolean isImportantConversation = mConversationType == CONVERSATION_TYPE_IMPORTANT; - Icon conversationIcon = mShortcutIcon; Icon largeIcon = mBuilder.mN.mLargeIcon; TemplateBindResult bindResult = new TemplateBindResult(); StandardTemplateParams p = mBuilder.mParams.reset() @@ -7671,7 +7670,7 @@ public class Notification implements Parcelable "setConversationTitle", conversationTitle); if (isConversationLayout) { contentView.setIcon(R.id.status_bar_latest_event_content, - "setConversationIcon", conversationIcon); + "setShortcutIcon", mShortcutIcon); contentView.setBoolean(R.id.status_bar_latest_event_content, "setIsImportantConversation", isImportantConversation); } diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index c75f72bdc765f..af72c5057257b 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -161,6 +161,7 @@ public class ConversationLayout extends FrameLayout private Rect mAppOpsTouchRect = new Rect(); private float mMinTouchSize; private Icon mConversationIcon; + private Icon mShortcutIcon; private View mAppNameDivider; public ConversationLayout(@NonNull Context context) { @@ -465,10 +466,9 @@ public class ConversationLayout extends FrameLayout private void updateConversationLayout() { // Set avatar and name CharSequence conversationText = mConversationTitle; + mConversationIcon = mShortcutIcon; if (mIsOneToOne) { // Let's resolve the icon / text from the last sender - mConversationIconView.setVisibility(VISIBLE); - mConversationFacePile.setVisibility(GONE); CharSequence userKey = getKey(mUser); for (int i = mGroups.size() - 1; i >= 0; i--) { MessagingGroup messagingGroup = mGroups.get(i); @@ -490,22 +490,21 @@ public class ConversationLayout extends FrameLayout break; } } + } + if (mConversationIcon == null) { + mConversationIcon = mLargeIcon; + } + if (mIsOneToOne || mConversationIcon != null) { + mConversationIconView.setVisibility(VISIBLE); + mConversationFacePile.setVisibility(GONE); + mConversationIconView.setImageIcon(mConversationIcon); } else { - if (mConversationIcon == null && mLargeIcon != null) { - mConversationIcon = mLargeIcon; - } - if (mConversationIcon != null) { - mConversationIconView.setVisibility(VISIBLE); - mConversationFacePile.setVisibility(GONE); - mConversationIconView.setImageIcon(mConversationIcon); - } else { - mConversationIconView.setVisibility(GONE); - // This will also inflate it! - mConversationFacePile.setVisibility(VISIBLE); - // rebind the value to the inflated view instead of the stub - mConversationFacePile = findViewById(R.id.conversation_face_pile); - bindFacePile(); - } + mConversationIconView.setVisibility(GONE); + // This will also inflate it! + mConversationFacePile.setVisibility(VISIBLE); + // rebind the value to the inflated view instead of the stub + mConversationFacePile = findViewById(R.id.conversation_face_pile); + bindFacePile(); } if (TextUtils.isEmpty(conversationText)) { conversationText = mIsOneToOne ? mFallbackChatName : mFallbackGroupChatName; @@ -712,7 +711,7 @@ public class ConversationLayout extends FrameLayout } @RemotableViewMethod - public void setConversationIcon(Icon conversationIcon) { + public void setShortcutIcon(Icon conversationIcon) { mConversationIcon = conversationIcon; } From 943159d153821eabfa36af32c621f91c5beab4eb Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Wed, 3 Jun 2020 20:50:23 -0400 Subject: [PATCH 175/182] Fix missing icon for one-to-one convos Fixes: 158089612 Test: manual Change-Id: If588073ff1df557b755b844277e893e001822d79 (cherry picked from commit 3d360da16dc52a04f36d2c1c05c9d82cd8d76231) --- core/java/android/app/Notification.java | 3 +- .../internal/widget/ConversationLayout.java | 35 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 980fdb87f3fbc..f881616fd35a5 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -7625,7 +7625,6 @@ public class Notification implements Parcelable } boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY; boolean isImportantConversation = mConversationType == CONVERSATION_TYPE_IMPORTANT; - Icon conversationIcon = mShortcutIcon; Icon largeIcon = mBuilder.mN.mLargeIcon; TemplateBindResult bindResult = new TemplateBindResult(); StandardTemplateParams p = mBuilder.mParams.reset() @@ -7671,7 +7670,7 @@ public class Notification implements Parcelable "setConversationTitle", conversationTitle); if (isConversationLayout) { contentView.setIcon(R.id.status_bar_latest_event_content, - "setConversationIcon", conversationIcon); + "setShortcutIcon", mShortcutIcon); contentView.setBoolean(R.id.status_bar_latest_event_content, "setIsImportantConversation", isImportantConversation); } diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 0d2dbefb9cd7e..1f2ae5f96449f 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -161,6 +161,7 @@ public class ConversationLayout extends FrameLayout private Rect mAppOpsTouchRect = new Rect(); private float mMinTouchSize; private Icon mConversationIcon; + private Icon mShortcutIcon; private View mAppNameDivider; public ConversationLayout(@NonNull Context context) { @@ -465,10 +466,9 @@ public class ConversationLayout extends FrameLayout private void updateConversationLayout() { // Set avatar and name CharSequence conversationText = mConversationTitle; + mConversationIcon = mShortcutIcon; if (mIsOneToOne) { // Let's resolve the icon / text from the last sender - mConversationIconView.setVisibility(VISIBLE); - mConversationFacePile.setVisibility(GONE); CharSequence userKey = getKey(mUser); for (int i = mGroups.size() - 1; i >= 0; i--) { MessagingGroup messagingGroup = mGroups.get(i); @@ -490,22 +490,21 @@ public class ConversationLayout extends FrameLayout break; } } + } + if (mConversationIcon == null) { + mConversationIcon = mLargeIcon; + } + if (mIsOneToOne || mConversationIcon != null) { + mConversationIconView.setVisibility(VISIBLE); + mConversationFacePile.setVisibility(GONE); + mConversationIconView.setImageIcon(mConversationIcon); } else { - if (mConversationIcon == null && mLargeIcon != null) { - mConversationIcon = mLargeIcon; - } - if (mConversationIcon != null) { - mConversationIconView.setVisibility(VISIBLE); - mConversationFacePile.setVisibility(GONE); - mConversationIconView.setImageIcon(mConversationIcon); - } else { - mConversationIconView.setVisibility(GONE); - // This will also inflate it! - mConversationFacePile.setVisibility(VISIBLE); - // rebind the value to the inflated view instead of the stub - mConversationFacePile = findViewById(R.id.conversation_face_pile); - bindFacePile(); - } + mConversationIconView.setVisibility(GONE); + // This will also inflate it! + mConversationFacePile.setVisibility(VISIBLE); + // rebind the value to the inflated view instead of the stub + mConversationFacePile = findViewById(R.id.conversation_face_pile); + bindFacePile(); } if (TextUtils.isEmpty(conversationText)) { conversationText = mIsOneToOne ? mFallbackChatName : mFallbackGroupChatName; @@ -712,7 +711,7 @@ public class ConversationLayout extends FrameLayout } @RemotableViewMethod - public void setConversationIcon(Icon conversationIcon) { + public void setShortcutIcon(Icon conversationIcon) { mConversationIcon = conversationIcon; } From 4a1455c08349ec94c4068c55376b0a14b75ede21 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 8 Jun 2020 11:19:59 -0700 Subject: [PATCH 176/182] Ensure we always bind to overview service when starting up - Previously, the registration of the device provisioned callback triggered the overview service to be started, but the switch to current user tracker removed that path Bug: 158321453 Test: Kill sysui and verify we start the service Change-Id: I9221389b0b1ef3298a93ed8daae7e026bcf772e8 (cherry picked from commit d0f407aacb2c2f83623be19ac8aa4d138d1f0a14) --- .../systemui/recents/OverviewProxyService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index baa2dfdcebf3a..8a012b8b06f18 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -577,10 +577,6 @@ public class OverviewProxyService extends CurrentUserTracker implements // Listen for nav bar mode changes mNavBarMode = navModeController.addListener(this); - // Listen for device provisioned/user setup - updateEnabledState(); - startTracking(); - // Listen for launcher package changes IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addDataScheme("package"); @@ -601,6 +597,13 @@ public class OverviewProxyService extends CurrentUserTracker implements .commitUpdate(mContext.getDisplayId()); } }); + + // Listen for user setup + startTracking(); + + // Connect to the service + updateEnabledState(); + startConnectionToCurrentUser(); } @Override From 3117fbca27f7a1585492ce55b3a805ac97815878 Mon Sep 17 00:00:00 2001 From: Matt Casey Date: Thu, 11 Jun 2020 00:19:19 +0000 Subject: [PATCH 177/182] Revert "Hide bubbles' IME after screenshot is taken." This reverts commit d56eaf68f6524a42594758feb20dc68f9920c33c. Reason for revert: Causing a sysui crash Bug: 157756391 Change-Id: I9df1bf4a3e9e6cb2f03218ba3c56c7c5660483c7 (cherry picked from commit 02805f050bc8d754a4e26d8eb24950b857b493c2) --- packages/SystemUI/AndroidManifest.xml | 4 ---- .../systemui/screenshot/GlobalScreenshot.java | 19 ------------------- 2 files changed, 23 deletions(-) diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index ef3e799a55bfd..985269b2bb759 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -406,10 +406,6 @@ - - - mBubbleController; - - public ScreenshotTakenReceiver(Lazy bubbleController) { - mBubbleController = bubbleController; - } - - @Override - public void onReceive(Context context, Intent intent) { - mBubbleController.get().hideImeFromExpandedBubble(); - } - } } From c6985445ad7cc3c355102f5023d574e1346f0bcf Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Wed, 17 Jun 2020 16:13:41 -0700 Subject: [PATCH 178/182] Repopulate cache with sibling visibility on remove This change ensures that we re-add the visibility state of a shared user id when one of its members is removed. Prior to this change, we were removing the app ID (and thus all other members of the shared uid) but only recomputing on the removed setting, which we ignore in the update (essentially an expensive no-op). This change ensures that we run through the shared settings and re-compute with them instead. Fixes: 159197157 Test: atest AppEnumerationTests SharedUidPermissionsTest Change-Id: I85250e4264888ac8583a2b4798ff6a2f93d6a74d (cherry picked from commit 5c5ac45ea00d469954752c276fa32e7fd0cc1b63) --- .../core/java/com/android/server/pm/AppsFilter.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index ccda5875d9fa0..83a1ddc2ce883 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -819,9 +819,15 @@ public class AppsFilter { mOverlayReferenceMapper.removePkg(setting.name); mFeatureConfig.updatePackageState(setting, true /*removed*/); - if (mShouldFilterCache != null) { - updateShouldFilterCacheForPackage( - setting.name, setting, settings, users, settings.size()); + if (mShouldFilterCache != null && setting.sharedUser != null) { + for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) { + PackageSetting siblingSetting = setting.sharedUser.packages.valueAt(i); + if (siblingSetting == setting) { + continue; + } + updateShouldFilterCacheForPackage( + setting.name, siblingSetting, settings, users, settings.size()); + } } }); mForceQueryable.remove(setting.appId); From de5d8f433993b4a956c31a5ccce1694022586c68 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Fri, 12 Jun 2020 09:25:10 -0700 Subject: [PATCH 179/182] Fixes broadcast filtering for multi-user sys apps This change fixes a bug caused by the assumption that FIRST_APPLICATION_UID is just that and that we should not treat UIDs with an APP_ID < FIRST_APPLICATION_UID in secondary users as system users that can see all packages. Test: atest AppsFilterTest AppEnumerationTests Test: manual; enable/disable apps in work profile Fixes: 157690238 Change-Id: I0aab78954222f0d1cf86a83375a8d0669025144a Merged-In: I0aab78954222f0d1cf86a83375a8d0669025144a (cherry picked from commit 7ecbe5b576a66b0cfa897261cf14c7bb1dc20f53) --- .../server/am/ActivityManagerService.java | 13 +++++++------ .../java/com/android/server/pm/AppsFilter.java | 7 ++++--- .../com/android/server/pm/AppsFilterTest.java | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 133ea8394ba63..3e6a17325f5c5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -15788,9 +15788,10 @@ public class ActivityManagerService extends IActivityManager.Stub } if (receivers != null && broadcastWhitelist != null) { for (int i = receivers.size() - 1; i >= 0; i--) { - final int uid = receivers.get(i).activityInfo.applicationInfo.uid; - if (uid >= Process.FIRST_APPLICATION_UID - && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) { + final int receiverAppId = UserHandle.getAppId( + receivers.get(i).activityInfo.applicationInfo.uid); + if (receiverAppId >= Process.FIRST_APPLICATION_UID + && Arrays.binarySearch(broadcastWhitelist, receiverAppId) < 0) { receivers.remove(i); } } @@ -16436,9 +16437,9 @@ public class ActivityManagerService extends IActivityManager.Stub // if a uid whitelist was provided, remove anything in the application space that wasn't // in it. for (int i = registeredReceivers.size() - 1; i >= 0; i--) { - final int uid = registeredReceivers.get(i).owningUid; - if (uid >= Process.FIRST_APPLICATION_UID - && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) { + final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid); + if (owningAppId >= Process.FIRST_APPLICATION_UID + && Arrays.binarySearch(broadcastWhitelist, owningAppId) < 0) { registeredReceivers.remove(i); } } diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 83a1ddc2ce883..01e5a469d2987 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -849,8 +849,9 @@ public class AppsFilter { PackageSetting targetPkgSetting, int userId) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication"); try { - if (callingUid < Process.FIRST_APPLICATION_UID - || UserHandle.getAppId(callingUid) == targetPkgSetting.appId) { + int callingAppId = UserHandle.getAppId(callingUid); + if (callingAppId < Process.FIRST_APPLICATION_UID + || callingAppId == targetPkgSetting.appId) { return false; } if (mShouldFilterCache != null) { // use cache @@ -875,7 +876,7 @@ public class AppsFilter { return false; } } - if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(UserHandle.getAppId(callingUid))) { + if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(callingAppId)) { log(callingSetting, targetPkgSetting, "BLOCKED"); } return !DEBUG_ALLOW_ALL; diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java index 4f21ee13a5e29..eb6b043dbfd9c 100644 --- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java @@ -512,6 +512,22 @@ public class AppsFilterTest { null, target, SYSTEM_USER)); } + @Test + public void testSystemUidSecondaryUser_DoesntFilter() throws Exception { + final AppsFilter appsFilter = + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); + simulateAddBasicAndroid(appsFilter); + appsFilter.onSystemReady(); + + PackageSetting target = simulateAddPackage(appsFilter, + pkg("com.some.package"), DUMMY_TARGET_APPID); + + assertFalse(appsFilter.shouldFilterApplication(0, null, target, SECONDARY_USER)); + assertFalse(appsFilter.shouldFilterApplication( + UserHandle.getUid(SECONDARY_USER, Process.FIRST_APPLICATION_UID - 1), + null, target, SECONDARY_USER)); + } + @Test public void testNonSystemUid_NoCallingSetting_Filters() throws Exception { final AppsFilter appsFilter = From e79d159e22693f5c863f391248b29289b350b60d Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Tue, 16 Jun 2020 13:50:58 -0700 Subject: [PATCH 180/182] Early exit when target app ID < FIRST_APP_UID This change ensures that we also grant visibility to the framework and other settings that are outside of the APPLICATION_UID space. Fixes: 159152185 Test: atest com.android.server.pm.UserManagerTest#testAddManagedProfile_withDisallowedPackages Change-Id: I00c8390dfa748f90c538a57243b472610886be7b (cherry picked from commit 947d63d1158d4727d382a952c8a677859ba1884c) --- services/core/java/com/android/server/pm/AppsFilter.java | 1 + .../src/com/android/server/pm/AppsFilterTest.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 01e5a469d2987..e7e6fe9d6b9da 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -851,6 +851,7 @@ public class AppsFilter { try { int callingAppId = UserHandle.getAppId(callingUid); if (callingAppId < Process.FIRST_APPLICATION_UID + || targetPkgSetting.appId < Process.FIRST_APPLICATION_UID || callingAppId == targetPkgSetting.appId) { return false; } diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java index eb6b043dbfd9c..26230949cda64 100644 --- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java @@ -806,7 +806,8 @@ public class AppsFilterTest { final SparseArray systemFilter = appsFilter.getVisibilityWhitelist(system, USER_ARRAY, mExisting); - assertThat(toList(systemFilter.get(SYSTEM_USER)), empty()); + assertThat(toList(systemFilter.get(SYSTEM_USER)), + contains(seesNothingAppId, hasProviderAppId, queriesProviderAppId)); final SparseArray seesNothingFilter = appsFilter.getVisibilityWhitelist(seesNothing, USER_ARRAY, mExisting); From 6a9464c08061aa4fa5f8a073c45bb30667fb4577 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Wed, 17 Jun 2020 10:21:55 -0700 Subject: [PATCH 181/182] Remove incorrect optimization in visibility cache During review when introducing the visibility cache, a suggested optimization when iterating over users turned out to prevent populating of the cache for certain multi-user cases. This change ensures that we pass over all users in both directions, making for a complete cache. Test: atest AppEnumerationTests AppsFilterTest Fixes: 159193336 Change-Id: Ic9ae27f1e1402b42a60a333c3ae99373f4829101 (cherry picked from commit 8132b22315e634cb5972e2b5f1b6782128b638de) --- services/core/java/com/android/server/pm/AppsFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index e7e6fe9d6b9da..178f6491d4fad 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -646,7 +646,7 @@ public class AppsFilter { final int appxUidCount = userCount * allSettings.size(); for (int su = 0; su < userCount; su++) { int subjectUser = allUsers[su].id; - for (int ou = su; ou < userCount; ou++) { + for (int ou = 0; ou < userCount; ou++) { int otherUser = allUsers[ou].id; int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId); if (!mShouldFilterCache.contains(subjectUid)) { From 7b5cd95fa69fe83ff63411ec5cab3d522a4777b5 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 30 Jun 2020 01:22:08 +0800 Subject: [PATCH 182/182] Wait for remote animation to stop freezing display If display is rotated 180 degree, the display might not have configuration change. And if there is remote rotation and it hasn't done, the rotation of display is still the old one. Once there is a path calls stop-freezing-display, the rotation animation will be executed directly with 0 degree delta. And if the activity needs to relaunch, there will be obvious flickering. Fixes: 160107205 Test: atest DisplayContentTests#testRemoteRotation Change-Id: I66a02b67f7066abafd65c2c282144222701feaae (cherry picked from commit 96ed092b109907b9e094dcffbd81a5d44021b0f4) --- data/etc/services.core.protolog.json | 18 ++++------- .../server/wm/WindowManagerService.java | 30 ++++++++++++------- .../server/wm/DisplayContentTests.java | 12 ++++++-- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index bfc623faeaefb..33ab16de79056 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1663,12 +1663,6 @@ "group": "WM_SHOW_SURFACE_ALLOC", "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" }, - "1108406230": { - "message": "stopFreezingDisplayLocked: Returning mWaitingForConfig=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d", - "level": "DEBUG", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "1112047265": { "message": "finishDrawingWindow: %s mDrawState=%s", "level": "DEBUG", @@ -1729,6 +1723,12 @@ "group": "WM_DEBUG_BOOT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "1246035185": { + "message": "stopFreezingDisplayLocked: Returning waitingForConfig=%b, waitingForRemoteRotation=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d", + "level": "DEBUG", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "1254403969": { "message": "Surface returned was null: %s", "level": "VERBOSE", @@ -1951,12 +1951,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", "at": "com\/android\/server\/wm\/AppTransition.java" }, - "1591969812": { - "message": "updateImeControlTarget %s", - "level": "INFO", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "1628345525": { "message": "Now opening app %s", "level": "VERBOSE", diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b1756b07ad83a..f4281fc0cafdb 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5606,17 +5606,28 @@ public class WindowManagerService extends IWindowManager.Stub } final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId); - final boolean waitingForConfig = displayContent != null && displayContent.mWaitingForConfig; - final int numOpeningApps = displayContent != null ? displayContent.mOpeningApps.size() : 0; - if (waitingForConfig || mAppsFreezingScreen > 0 + final int numOpeningApps; + final boolean waitingForConfig; + final boolean waitingForRemoteRotation; + if (displayContent != null) { + numOpeningApps = displayContent.mOpeningApps.size(); + waitingForConfig = displayContent.mWaitingForConfig; + waitingForRemoteRotation = + displayContent.getDisplayRotation().isWaitingForRemoteRotation(); + } else { + waitingForConfig = waitingForRemoteRotation = false; + numOpeningApps = 0; + } + if (waitingForConfig || waitingForRemoteRotation || mAppsFreezingScreen > 0 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE || mClientFreezingScreen || numOpeningApps > 0) { - ProtoLog.d(WM_DEBUG_ORIENTATION, - "stopFreezingDisplayLocked: Returning mWaitingForConfig=%b, " - + "mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, " - + "mClientFreezingScreen=%b, mOpeningApps.size()=%d", - waitingForConfig, mAppsFreezingScreen, mWindowsFreezingScreen, - mClientFreezingScreen, numOpeningApps); + ProtoLog.d(WM_DEBUG_ORIENTATION, "stopFreezingDisplayLocked: Returning " + + "waitingForConfig=%b, waitingForRemoteRotation=%b, " + + "mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, " + + "mClientFreezingScreen=%b, mOpeningApps.size()=%d", + waitingForConfig, waitingForRemoteRotation, + mAppsFreezingScreen, mWindowsFreezingScreen, + mClientFreezingScreen, numOpeningApps); return; } @@ -5627,7 +5638,6 @@ public class WindowManagerService extends IWindowManager.Stub // We must make a local copy of the displayId as it can be potentially overwritten later on // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result // of update rotation, but we reference the frozen display after that call in this method. - final int displayId = mFrozenDisplayId; mFrozenDisplayId = INVALID_DISPLAY; mDisplayFrozen = false; mInputManagerCallback.thawInputDispatchingLw(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 30af1d34f5585..ddb186a1d2da5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1328,9 +1328,10 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayRotation dr = dc.getDisplayRotation(); doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean()); - Mockito.doReturn(ROTATION_90).when(dr).rotationForOrientation(anyInt(), anyInt()); + // Rotate 180 degree so the display doesn't have configuration change. This condition is + // used for the later verification of stop-freezing (without setting mWaitingForConfig). + doReturn((dr.getRotation() + 2) % 4).when(dr).rotationForOrientation(anyInt(), anyInt()); final boolean[] continued = new boolean[1]; - // TODO(display-merge): Remove cast doAnswer( invocation -> { continued[0] = true; @@ -1356,9 +1357,16 @@ public class DisplayContentTests extends WindowTestsBase { dc.setRotationAnimation(null); mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */); + // If remote rotation is not finished, the display should not be able to unfreeze. + mWm.stopFreezingDisplayLocked(); + assertTrue(mWm.mDisplayFrozen); + assertTrue(called[0]); waitUntilHandlersIdle(); assertTrue(continued[0]); + + mWm.stopFreezingDisplayLocked(); + assertFalse(mWm.mDisplayFrozen); } @Test