diff options
32 files changed, 494 insertions, 204 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index e27c29f657eb..f130c69c5de8 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7983,6 +7983,7 @@ package android.webkit { method public void callDrawGlFunction(android.graphics.Canvas, long, java.lang.Runnable); method public boolean canInvokeDrawGlFunctor(android.view.View); method public void detachDrawGlFunctor(android.view.View, long); + method public void drawWebViewFunctor(android.graphics.Canvas, int); method public android.app.Application getApplication(); method public java.lang.String getDataDirectorySuffix(); method public java.lang.String getErrorString(android.content.Context, int); diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java index 6ab7f66aedd3..ef69b6333cce 100644 --- a/core/java/android/webkit/WebViewDelegate.java +++ b/core/java/android/webkit/WebViewDelegate.java @@ -138,6 +138,20 @@ public final class WebViewDelegate { } /** + * Call webview draw functor. See API in draw_fn.h. + * @param canvas a hardware accelerated canvas (see {@link Canvas#isHardwareAccelerated()}). + * @param functor created by AwDrawFn_CreateFunctor in draw_fn.h. + */ + public void drawWebViewFunctor(@NonNull Canvas canvas, int functor) { + if (!(canvas instanceof RecordingCanvas)) { + // Canvas#isHardwareAccelerated() is only true for subclasses of RecordingCanvas. + throw new IllegalArgumentException(canvas.getClass().getName() + + " is not a RecordingCanvas canvas"); + } + ((RecordingCanvas) canvas).drawWebViewFunctor(functor); + } + + /** * Detaches the draw GL functor. * * @param nativeDrawGLFunctor the pointer to the native functor that implements diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java index 78d366cd2436..2995a8f43268 100644 --- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java +++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java @@ -16,14 +16,14 @@ package com.android.internal.hardware; -import com.android.internal.R; - import android.content.Context; import android.os.Build; import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; +import com.android.internal.R; + public class AmbientDisplayConfiguration { private final Context mContext; @@ -37,7 +37,8 @@ public class AmbientDisplayConfiguration { public boolean enabled(int user) { return pulseOnNotificationEnabled(user) || pulseOnLongPressEnabled(user) - || alwaysOnEnabled(user); + || alwaysOnEnabled(user) + || wakeLockScreenGestureEnabled(user); } public boolean pulseOnNotificationEnabled(int user) { diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 7e69e3a8a73f..96798f978465 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -61,6 +61,7 @@ cc_defaults { "libstatslog", "libutils", "libEGL", + "libGLESv1_CM", "libGLESv2", "libGLESv3", "libvulkan", diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp index 20e77b453706..5b7ae70e821c 100644 --- a/libs/hwui/WebViewFunctorManager.cpp +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -37,7 +37,8 @@ RenderMode WebViewFunctor_queryPlatformRenderMode() { } } -int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode) { +int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype, + RenderMode functorMode) { if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) { ALOGW("Unknown rendermode %d", (int)functorMode); return -1; @@ -47,7 +48,7 @@ int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode f ALOGW("Unable to map from GLES platform to a vulkan functor"); return -1; } - return WebViewFunctorManager::instance().createFunctor(prototype, functorMode); + return WebViewFunctorManager::instance().createFunctor(data, prototype, functorMode); } void WebViewFunctor_release(int functor) { @@ -56,7 +57,9 @@ void WebViewFunctor_release(int functor) { static std::atomic_int sNextId{1}; -WebViewFunctor::WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) { +WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, + RenderMode functorMode) + : mData(data) { mFunctor = sNextId++; mCallbacks = callbacks; mMode = functorMode; @@ -66,12 +69,12 @@ WebViewFunctor::~WebViewFunctor() { destroyContext(); ATRACE_NAME("WebViewFunctor::onDestroy"); - mCallbacks.onDestroyed(mFunctor); + mCallbacks.onDestroyed(mFunctor, mData); } void WebViewFunctor::sync(const WebViewSyncData& syncData) const { ATRACE_NAME("WebViewFunctor::sync"); - mCallbacks.onSync(mFunctor, syncData); + mCallbacks.onSync(mFunctor, mData, syncData); } void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { @@ -79,14 +82,14 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { if (!mHasContext) { mHasContext = true; } - mCallbacks.gles.draw(mFunctor, drawInfo); + mCallbacks.gles.draw(mFunctor, mData, drawInfo); } void WebViewFunctor::destroyContext() { if (mHasContext) { mHasContext = false; ATRACE_NAME("WebViewFunctor::onContextDestroyed"); - mCallbacks.onContextDestroyed(mFunctor); + mCallbacks.onContextDestroyed(mFunctor, mData); } } @@ -95,9 +98,9 @@ WebViewFunctorManager& WebViewFunctorManager::instance() { return sInstance; } -int WebViewFunctorManager::createFunctor(const WebViewFunctorCallbacks& callbacks, +int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) { - auto object = std::make_unique<WebViewFunctor>(callbacks, functorMode); + auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode); int id = object->id(); auto handle = object->createHandle(); { @@ -164,4 +167,4 @@ sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) { return nullptr; } -} // namespace android::uirenderer
\ No newline at end of file +} // namespace android::uirenderer diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h index 2a621dd411e3..1719ce7cca75 100644 --- a/libs/hwui/WebViewFunctorManager.h +++ b/libs/hwui/WebViewFunctorManager.h @@ -29,7 +29,7 @@ class WebViewFunctorManager; class WebViewFunctor { public: - WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode); + WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode); ~WebViewFunctor(); class Handle : public LightRefBase<Handle> { @@ -63,6 +63,7 @@ public: private: WebViewFunctorCallbacks mCallbacks; + void* const mData; int mFunctor; RenderMode mMode; bool mHasContext = false; @@ -73,7 +74,7 @@ class WebViewFunctorManager { public: static WebViewFunctorManager& instance(); - int createFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode); + int createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode); void releaseFunctor(int functor); void onContextDestroyed(); void destroyFunctor(int functor); diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h index e5346aabaee3..da3d06a4d60c 100644 --- a/libs/hwui/private/hwui/WebViewFunctor.h +++ b/libs/hwui/private/hwui/WebViewFunctor.h @@ -17,6 +17,7 @@ #ifndef FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H #define FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H +#include <cutils/compiler.h> #include <private/hwui/DrawGlInfo.h> namespace android::uirenderer { @@ -27,7 +28,7 @@ enum class RenderMode { }; // Static for the lifetime of the process -RenderMode WebViewFunctor_queryPlatformRenderMode(); +ANDROID_API RenderMode WebViewFunctor_queryPlatformRenderMode(); struct WebViewSyncData { bool applyForceDark; @@ -35,21 +36,21 @@ struct WebViewSyncData { struct WebViewFunctorCallbacks { // kModeSync, called on RenderThread - void (*onSync)(int functor, const WebViewSyncData& syncData); + void (*onSync)(int functor, void* data, const WebViewSyncData& syncData); // Called when either the context is destroyed _or_ when the functor's last reference goes // away. Will always be called with an active context and always on renderthread. - void (*onContextDestroyed)(int functor); + void (*onContextDestroyed)(int functor, void* data); // Called when the last reference to the handle goes away and the handle is considered // irrevocably destroyed. Will always be proceeded by a call to onContextDestroyed if // this functor had ever been drawn. - void (*onDestroyed)(int functor); + void (*onDestroyed)(int functor, void* data); union { struct { // Called on RenderThread. initialize is guaranteed to happen before this call - void (*draw)(int functor, const DrawGlInfo& params); + void (*draw)(int functor, void* data, const DrawGlInfo& params); } gles; // TODO: VK support. The current DrawVkInfo is monolithic and needs to be split up for // what params are valid on what callbacks @@ -70,12 +71,12 @@ struct WebViewFunctorCallbacks { // Creates a new WebViewFunctor from the given prototype. The prototype is copied after // this function returns. Caller retains full ownership of it. // Returns -1 if the creation fails (such as an unsupported functorMode + platform mode combination) -int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode); +ANDROID_API int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype, RenderMode functorMode); // May be called on any thread to signal that the functor should be destroyed. // The functor will receive an onDestroyed when the last usage of it is released, // and it should be considered alive & active until that point. -void WebViewFunctor_release(int functor); +ANDROID_API void WebViewFunctor_release(int functor); } // namespace android::uirenderer diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h index 5ff8993e6779..6a1ca5a25361 100644 --- a/libs/hwui/tests/common/TestUtils.h +++ b/libs/hwui/tests/common/TestUtils.h @@ -315,24 +315,24 @@ public: static WebViewFunctorCallbacks createMockFunctor(RenderMode mode) { auto callbacks = WebViewFunctorCallbacks{ .onSync = - [](int functor, const WebViewSyncData& data) { + [](int functor, void* client_data, const WebViewSyncData& data) { expectOnRenderThread(); sMockFunctorCounts[functor].sync++; }, .onContextDestroyed = - [](int functor) { + [](int functor, void* client_data) { expectOnRenderThread(); sMockFunctorCounts[functor].contextDestroyed++; }, .onDestroyed = - [](int functor) { + [](int functor, void* client_data) { expectOnRenderThread(); sMockFunctorCounts[functor].destroyed++; }, }; switch (mode) { case RenderMode::OpenGL_ES: - callbacks.gles.draw = [](int functor, const DrawGlInfo& params) { + callbacks.gles.draw = [](int functor, void* client_data, const DrawGlInfo& params) { expectOnRenderThread(); sMockFunctorCounts[functor].glesDraw++; }; diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp index 53bf84f13fd6..1b4cf7e144bd 100644 --- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp +++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp @@ -100,8 +100,8 @@ TEST(SkiaDisplayList, syncContexts) { GLFunctorDrawable functorDrawable(&functor, nullptr, &dummyCanvas); skiaDL.mChildFunctors.push_back(&functorDrawable); - int functor2 = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES), - RenderMode::OpenGL_ES); + int functor2 = WebViewFunctor_create( + nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES); auto& counts = TestUtils::countsForFunctor(functor2); skiaDL.mChildFunctors.push_back( skiaDL.allocateDrawable<GLFunctorDrawable>(functor2, &dummyCanvas)); diff --git a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp index c8169aff1c5e..e1fb8b7069ff 100644 --- a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp +++ b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp @@ -27,8 +27,8 @@ using namespace android; using namespace android::uirenderer; TEST(WebViewFunctor, createDestroyGLES) { - int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES), - RenderMode::OpenGL_ES); + int functor = WebViewFunctor_create( + nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES); ASSERT_NE(-1, functor); WebViewFunctor_release(functor); TestUtils::runOnRenderThreadUnmanaged([](renderthread::RenderThread&) { @@ -41,8 +41,8 @@ TEST(WebViewFunctor, createDestroyGLES) { } TEST(WebViewFunctor, createSyncHandleGLES) { - int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES), - RenderMode::OpenGL_ES); + int functor = WebViewFunctor_create( + nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES); ASSERT_NE(-1, functor); auto handle = WebViewFunctorManager::instance().handleFor(functor); ASSERT_TRUE(handle); @@ -82,8 +82,8 @@ TEST(WebViewFunctor, createSyncHandleGLES) { } TEST(WebViewFunctor, createSyncDrawGLES) { - int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES), - RenderMode::OpenGL_ES); + int functor = WebViewFunctor_create( + nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES); ASSERT_NE(-1, functor); auto handle = WebViewFunctorManager::instance().handleFor(functor); ASSERT_TRUE(handle); @@ -109,8 +109,8 @@ TEST(WebViewFunctor, createSyncDrawGLES) { } TEST(WebViewFunctor, contextDestroyed) { - int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES), - RenderMode::OpenGL_ES); + int functor = WebViewFunctor_create( + nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES); ASSERT_NE(-1, functor); auto handle = WebViewFunctorManager::instance().handleFor(functor); ASSERT_TRUE(handle); @@ -151,4 +151,4 @@ TEST(WebViewFunctor, contextDestroyed) { EXPECT_EQ(2, counts.glesDraw); EXPECT_EQ(2, counts.contextDestroyed); EXPECT_EQ(1, counts.destroyed); -}
\ No newline at end of file +} diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl index 5c1915b724de..f0db1b4c62e3 100644 --- a/media/java/android/media/session/ISessionController.aidl +++ b/media/java/android/media/session/ISessionController.aidl @@ -47,9 +47,9 @@ interface ISessionController { PendingIntent getLaunchPendingIntent(); long getFlags(); ParcelableVolumeInfo getVolumeAttributes(); - void adjustVolume(String packageName, in ControllerCallbackLink caller, + void adjustVolume(String packageName, String opPackageName, in ControllerCallbackLink caller, boolean asSystemService, int direction, int flags); - void setVolumeTo(String packageName, in ControllerCallbackLink caller, + void setVolumeTo(String packageName, String opPackageName, in ControllerCallbackLink caller, int value, int flags); // These commands are for the TransportControls diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl index 580196736aba..f2c0e32781c2 100644 --- a/media/java/android/media/session/ISessionManager.aidl +++ b/media/java/android/media/session/ISessionManager.aidl @@ -35,9 +35,10 @@ interface ISessionManager { List<IBinder> getSessions(in ComponentName compName, int userId); void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent, boolean needWakeLock); - void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent, - int stream, boolean musicOnly); - void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, int flags); + void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService, + in KeyEvent keyEvent, int stream, boolean musicOnly); + void dispatchAdjustVolume(String packageName, String opPackageName, int suggestedStream, + int delta, int flags); void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName, int userId); void removeSessionsListener(in IActiveSessionsListener listener); diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index 5eb77f9b58e2..7b061fe8e546 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -154,7 +154,7 @@ public final class MediaController { return false; } try { - return mSessionBinder.sendMediaButton(mContext.getOpPackageName(), mCbStub, + return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub, asSystemService, keyEvent); } catch (RemoteException e) { // System is dead. =( @@ -187,8 +187,12 @@ public final class MediaController { break; } try { - mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true, - direction, AudioManager.FLAG_SHOW_UI); + // Note: Need both package name and OP package name. Package name is used for + // RemoteUserInfo, and OP package name is used for AudioService's internal + // AppOpsManager usages. + mSessionBinder.adjustVolume(mContext.getPackageName(), + mContext.getOpPackageName(), mCbStub, true, direction, + AudioManager.FLAG_SHOW_UI); } catch (RemoteException e) { Log.wtf(TAG, "Error calling adjustVolumeBy", e); } @@ -198,8 +202,11 @@ public final class MediaController { final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE | AudioManager.FLAG_FROM_KEY; try { - mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true, 0, - flags); + // Note: Need both package name and OP package name. Package name is used for + // RemoteUserInfo, and OP package name is used for AudioService's internal + // AppOpsManager usages. + mSessionBinder.adjustVolume(mContext.getPackageName(), + mContext.getOpPackageName(), mCbStub, true, 0, flags); } catch (RemoteException e) { Log.wtf(TAG, "Error calling adjustVolumeBy", e); } @@ -365,7 +372,11 @@ public final class MediaController { */ public void setVolumeTo(int value, int flags) { try { - mSessionBinder.setVolumeTo(mContext.getOpPackageName(), mCbStub, value, flags); + // Note: Need both package name and OP package name. Package name is used for + // RemoteUserInfo, and OP package name is used for AudioService's internal + // AppOpsManager usages. + mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(), + mCbStub, value, flags); } catch (RemoteException e) { Log.wtf(TAG, "Error calling setVolumeTo.", e); } @@ -386,8 +397,11 @@ public final class MediaController { */ public void adjustVolume(int direction, int flags) { try { - mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, false, direction, - flags); + // Note: Need both package name and OP package name. Package name is used for + // RemoteUserInfo, and OP package name is used for AudioService's internal + // AppOpsManager usages. + mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(), + mCbStub, false, direction, flags); } catch (RemoteException e) { Log.wtf(TAG, "Error calling adjustVolumeBy.", e); } @@ -453,7 +467,7 @@ public final class MediaController { throw new IllegalArgumentException("command cannot be null or empty"); } try { - mSessionBinder.sendCommand(mContext.getOpPackageName(), mCbStub, command, args, cb); + mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb); } catch (RemoteException e) { Log.d(TAG, "Dead object in sendCommand.", e); } @@ -519,7 +533,7 @@ public final class MediaController { if (!mCbRegistered) { try { - mSessionBinder.registerCallbackListener(mContext.getOpPackageName(), mCbStub); + mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub); mCbRegistered = true; } catch (RemoteException e) { Log.e(TAG, "Dead object in registerCallback", e); @@ -666,7 +680,7 @@ public final class MediaController { */ public void prepare() { try { - mSessionBinder.prepare(mContext.getOpPackageName(), mCbStub); + mSessionBinder.prepare(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling prepare.", e); } @@ -690,7 +704,7 @@ public final class MediaController { "You must specify a non-empty String for prepareFromMediaId."); } try { - mSessionBinder.prepareFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId, + mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId, extras); } catch (RemoteException e) { Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e); @@ -717,7 +731,7 @@ public final class MediaController { query = ""; } try { - mSessionBinder.prepareFromSearch(mContext.getOpPackageName(), mCbStub, query, + mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query, extras); } catch (RemoteException e) { Log.wtf(TAG, "Error calling prepare(" + query + ").", e); @@ -742,7 +756,7 @@ public final class MediaController { "You must specify a non-empty Uri for prepareFromUri."); } try { - mSessionBinder.prepareFromUri(mContext.getOpPackageName(), mCbStub, uri, extras); + mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras); } catch (RemoteException e) { Log.wtf(TAG, "Error calling prepare(" + uri + ").", e); } @@ -753,7 +767,7 @@ public final class MediaController { */ public void play() { try { - mSessionBinder.play(mContext.getOpPackageName(), mCbStub); + mSessionBinder.play(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling play.", e); } @@ -772,7 +786,7 @@ public final class MediaController { "You must specify a non-empty String for playFromMediaId."); } try { - mSessionBinder.playFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId, + mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId, extras); } catch (RemoteException e) { Log.wtf(TAG, "Error calling play(" + mediaId + ").", e); @@ -795,7 +809,7 @@ public final class MediaController { query = ""; } try { - mSessionBinder.playFromSearch(mContext.getOpPackageName(), mCbStub, query, extras); + mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras); } catch (RemoteException e) { Log.wtf(TAG, "Error calling play(" + query + ").", e); } @@ -814,7 +828,7 @@ public final class MediaController { "You must specify a non-empty Uri for playFromUri."); } try { - mSessionBinder.playFromUri(mContext.getOpPackageName(), mCbStub, uri, extras); + mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras); } catch (RemoteException e) { Log.wtf(TAG, "Error calling play(" + uri + ").", e); } @@ -826,7 +840,7 @@ public final class MediaController { */ public void skipToQueueItem(long id) { try { - mSessionBinder.skipToQueueItem(mContext.getOpPackageName(), mCbStub, id); + mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id); } catch (RemoteException e) { Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e); } @@ -838,7 +852,7 @@ public final class MediaController { */ public void pause() { try { - mSessionBinder.pause(mContext.getOpPackageName(), mCbStub); + mSessionBinder.pause(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling pause.", e); } @@ -850,7 +864,7 @@ public final class MediaController { */ public void stop() { try { - mSessionBinder.stop(mContext.getOpPackageName(), mCbStub); + mSessionBinder.stop(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling stop.", e); } @@ -863,7 +877,7 @@ public final class MediaController { */ public void seekTo(long pos) { try { - mSessionBinder.seekTo(mContext.getOpPackageName(), mCbStub, pos); + mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos); } catch (RemoteException e) { Log.wtf(TAG, "Error calling seekTo.", e); } @@ -875,7 +889,7 @@ public final class MediaController { */ public void fastForward() { try { - mSessionBinder.fastForward(mContext.getOpPackageName(), mCbStub); + mSessionBinder.fastForward(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling fastForward.", e); } @@ -886,7 +900,7 @@ public final class MediaController { */ public void skipToNext() { try { - mSessionBinder.next(mContext.getOpPackageName(), mCbStub); + mSessionBinder.next(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling next.", e); } @@ -898,7 +912,7 @@ public final class MediaController { */ public void rewind() { try { - mSessionBinder.rewind(mContext.getOpPackageName(), mCbStub); + mSessionBinder.rewind(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling rewind.", e); } @@ -909,7 +923,7 @@ public final class MediaController { */ public void skipToPrevious() { try { - mSessionBinder.previous(mContext.getOpPackageName(), mCbStub); + mSessionBinder.previous(mContext.getPackageName(), mCbStub); } catch (RemoteException e) { Log.wtf(TAG, "Error calling previous.", e); } @@ -924,7 +938,7 @@ public final class MediaController { */ public void setRating(Rating rating) { try { - mSessionBinder.rate(mContext.getOpPackageName(), mCbStub, rating); + mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating); } catch (RemoteException e) { Log.wtf(TAG, "Error calling rate.", e); } @@ -959,7 +973,7 @@ public final class MediaController { throw new IllegalArgumentException("CustomAction cannot be null."); } try { - mSessionBinder.sendCustomAction(mContext.getOpPackageName(), mCbStub, action, args); + mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args); } catch (RemoteException e) { Log.d(TAG, "Dead object in sendCustomAction.", e); } diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 73dd55c1b88a..7a4116f8baa8 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -312,7 +312,7 @@ public final class MediaSessionManager { private void dispatchMediaKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent, boolean needWakeLock) { try { - mService.dispatchMediaKeyEvent(mContext.getOpPackageName(), asSystemService, keyEvent, + mService.dispatchMediaKeyEvent(mContext.getPackageName(), asSystemService, keyEvent, needWakeLock); } catch (RemoteException e) { Log.e(TAG, "Failed to send key event.", e); @@ -348,8 +348,8 @@ public final class MediaSessionManager { private void dispatchVolumeKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent, int stream, boolean musicOnly) { try { - mService.dispatchVolumeKeyEvent(mContext.getOpPackageName(), asSystemService, keyEvent, - stream, musicOnly); + mService.dispatchVolumeKeyEvent(mContext.getPackageName(), mContext.getOpPackageName(), + asSystemService, keyEvent, stream, musicOnly); } catch (RemoteException e) { Log.e(TAG, "Failed to send volume key event.", e); } @@ -369,8 +369,8 @@ public final class MediaSessionManager { */ public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) { try { - mService.dispatchAdjustVolume(mContext.getOpPackageName(), suggestedStream, direction, - flags); + mService.dispatchAdjustVolume(mContext.getPackageName(), mContext.getOpPackageName(), + suggestedStream, direction, flags); } catch (RemoteException e) { Log.e(TAG, "Failed to send adjust volume.", e); } diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 7481fff74765..f75f69b4f2ee 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -95,14 +95,16 @@ cc_library_shared { ], shared_libs: [ - "android.hardware.cas@1.0", // for CasManager. VNDK??? - "android.hardware.cas.native@1.0", // CasManager. VNDK??? + // MediaCas + "android.hardware.cas@1.0", + "android.hardware.cas.native@1.0", "android.hidl.allocator@1.0", + "libhidlbase", "libhidlmemory", - "libbinder", - "libgui", // for VideoFrameScheduler - "libhidlbase", // VNDK??? - "libpowermanager", // for JWakeLock. to be removed + + "libpowermanager", // Used by JWakeLock. Will be replace with public SDJ API. + "libmediametrics", // Used by MediaMetrics. Will be replaced with stable C API. + "libbinder", // Used by JWakeLock and MediaMetrics. "libutils", // Have to use shared lib to make libandroid_runtime behave correctly. // Otherwise, AndroidRuntime::getJNIEnv() will return NULL. @@ -124,7 +126,6 @@ cc_library_shared { "libmedia_helper", "libmedia_player2_util", "libmediaextractor", - "libmediametrics", "libmediaplayer2", "libmediaplayer2-protos", "libmediandk_utils", diff --git a/native/webview/plat_support/Android.bp b/native/webview/plat_support/Android.bp index 96c9c1c85a60..09362566d915 100644 --- a/native/webview/plat_support/Android.bp +++ b/native/webview/plat_support/Android.bp @@ -22,6 +22,7 @@ cc_library_shared { name: "libwebviewchromium_plat_support", srcs: [ + "draw_functor.cpp", "draw_gl_functor.cpp", "draw_vk_functor.cpp", "functor_utils.cpp", diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h index 8d48a58ac293..6afd8837594c 100644 --- a/native/webview/plat_support/draw_fn.h +++ b/native/webview/plat_support/draw_fn.h @@ -129,31 +129,31 @@ struct AwDrawFn_PostDrawVkParams { // Called on render thread while UI thread is blocked. Called for both GL and // VK. -typedef void AwDrawFn_OnSync(int functor, AwDrawFn_OnSyncParams* params); +typedef void AwDrawFn_OnSync(int functor, void* data, AwDrawFn_OnSyncParams* params); // Called on render thread when either the context is destroyed _or_ when the // functor's last reference goes away. Will always be called with an active // context. Called for both GL and VK. -typedef void AwDrawFn_OnContextDestroyed(int functor); +typedef void AwDrawFn_OnContextDestroyed(int functor, void* data); // Called on render thread when the last reference to the handle goes away and -// the handle is considered irrevocably destroyed. Will always be proceeded by +// the handle is considered irrevocably destroyed. Will always be preceded by // a call to OnContextDestroyed if this functor had ever been drawn. Called for // both GL and VK. -typedef void AwDrawFn_OnDestroyed(int functor); +typedef void AwDrawFn_OnDestroyed(int functor, void* data); // Only called for GL. -typedef void AwDrawFn_DrawGL(int functor, AwDrawFn_DrawGLParams* params); +typedef void AwDrawFn_DrawGL(int functor, void* data, AwDrawFn_DrawGLParams* params); // Initialize vulkan state. Needs to be called again after any // OnContextDestroyed. Only called for Vulkan. -typedef void AwDrawFn_InitVk(int functor, AwDrawFn_InitVkParams* params); +typedef void AwDrawFn_InitVk(int functor, void* data, AwDrawFn_InitVkParams* params); // Only called for Vulkan. -typedef void AwDrawFn_DrawVk(int functor, AwDrawFn_DrawVkParams* params); +typedef void AwDrawFn_DrawVk(int functor, void* data, AwDrawFn_DrawVkParams* params); // Only called for Vulkan. -typedef void AwDrawFn_PostDrawVk(int functor, +typedef void AwDrawFn_PostDrawVk(int functor, void* data, AwDrawFn_PostDrawVkParams* params); struct AwDrawFnFunctorCallbacks { @@ -176,7 +176,7 @@ enum AwDrawFnRenderMode { typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void); // Create a functor. |functor_callbacks| should be valid until OnDestroyed. -typedef int AwDrawFn_CreateFunctor(AwDrawFnFunctorCallbacks* functor_callbacks); +typedef int AwDrawFn_CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks); // May be called on any thread to signal that the functor should be destroyed. // The functor will receive an onDestroyed when the last usage of it is diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp new file mode 100644 index 000000000000..820bac509d2e --- /dev/null +++ b/native/webview/plat_support/draw_functor.cpp @@ -0,0 +1,144 @@ +/* + * 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. + */ + +#include "draw_fn.h" + +#include <jni.h> +#include <private/hwui/WebViewFunctor.h> +#include <utils/Log.h> + +#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) +#define COMPILE_ASSERT(expr, err) \ +__unused static const char (err)[(expr) ? 1 : -1] = ""; + +namespace android { +namespace { + +struct SupportData { + void* const data; + AwDrawFnFunctorCallbacks callbacks; +}; + +void onSync(int functor, void* data, + const uirenderer::WebViewSyncData& syncData) { + AwDrawFn_OnSyncParams params = { + .version = kAwDrawFnVersion, + .apply_force_dark = syncData.applyForceDark, + }; + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.on_sync(functor, support->data, ¶ms); +} + +void onContextDestroyed(int functor, void* data) { + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.on_context_destroyed(functor, support->data); +} + +void onDestroyed(int functor, void* data) { + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.on_destroyed(functor, support->data); + delete support; +} + +void draw_gl(int functor, void* data, + const uirenderer::DrawGlInfo& draw_gl_params) { + AwDrawFn_DrawGLParams params = { + .version = kAwDrawFnVersion, + .clip_left = draw_gl_params.clipLeft, + .clip_top = draw_gl_params.clipTop, + .clip_right = draw_gl_params.clipRight, + .clip_bottom = draw_gl_params.clipBottom, + .width = draw_gl_params.width, + .height = draw_gl_params.height, + .is_layer = draw_gl_params.isLayer, + }; + COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform), + mismatched_transform_matrix_sizes); + for (int i = 0; i < NELEM(params.transform); ++i) { + params.transform[i] = draw_gl_params.transform[i]; + } + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.draw_gl(functor, support->data, ¶ms); +} + +int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { + static bool callbacks_initialized = false; + static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = { + .onSync = &onSync, + .onContextDestroyed = &onContextDestroyed, + .onDestroyed = &onDestroyed, + }; + if (!callbacks_initialized) { + switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) { + case uirenderer::RenderMode::OpenGL_ES: + webview_functor_callbacks.gles.draw = &draw_gl; + break; + case uirenderer::RenderMode::Vulkan: + break; + } + callbacks_initialized = true; + } + SupportData* support = new SupportData{ + .data = data, + .callbacks = *functor_callbacks, + }; + int functor = uirenderer::WebViewFunctor_create( + support, webview_functor_callbacks, + uirenderer::WebViewFunctor_queryPlatformRenderMode()); + if (functor <= 0) delete support; + return functor; +} + +void ReleaseFunctor(int functor) { + uirenderer::WebViewFunctor_release(functor); +} + +AwDrawFnRenderMode QueryRenderMode(void) { + switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) { + case uirenderer::RenderMode::OpenGL_ES: + return AW_DRAW_FN_RENDER_MODE_OPENGL_ES; + case uirenderer::RenderMode::Vulkan: + return AW_DRAW_FN_RENDER_MODE_VULKAN; + } +} + +jlong GetDrawFnFunctionTable() { + static AwDrawFnFunctionTable function_table = { + .version = kAwDrawFnVersion, + .query_render_mode = &QueryRenderMode, + .create_functor = &CreateFunctor, + .release_functor = &ReleaseFunctor, + }; + return reinterpret_cast<intptr_t>(&function_table); +} + +const char kClassName[] = "com/android/webview/chromium/DrawFunctor"; +const JNINativeMethod kJniMethods[] = { + {"nativeGetFunctionTable", "()J", + reinterpret_cast<void*>(GetDrawFnFunctionTable)}, +}; + +} // namespace + +void RegisterDrawFunctor(JNIEnv* env) { + jclass clazz = env->FindClass(kClassName); + LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName); + + int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods)); + LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res); +} + +} // namespace android diff --git a/native/webview/plat_support/jni_entry_point.cpp b/native/webview/plat_support/jni_entry_point.cpp index 4771be1bc258..9599fa6da516 100644 --- a/native/webview/plat_support/jni_entry_point.cpp +++ b/native/webview/plat_support/jni_entry_point.cpp @@ -21,6 +21,7 @@ namespace android { +void RegisterDrawFunctor(JNIEnv* env); void RegisterDrawGLFunctor(JNIEnv* env); void RegisterGraphicsUtils(JNIEnv* env); @@ -30,6 +31,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint ret = vm->AttachCurrentThread(&env, NULL); LOG_ALWAYS_FATAL_IF(ret != JNI_OK, "AttachCurrentThread failed"); + android::RegisterDrawFunctor(env); android::RegisterDrawGLFunctor(env); android::RegisterGraphicsUtils(env); diff --git a/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml b/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml index cbebbb32dc89..d6dc211ad8c4 100644 --- a/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml +++ b/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml @@ -18,12 +18,11 @@ <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:paddingMode="stack"> <item> - <shape - android:tint="?android:attr/colorForeground"> + <shape> <corners android:radius="20dp"/> <solid - android:color="@android:color/transparent"/> + android:color="?android:attr/colorPrimary"/> <stroke android:color="#1f000000" android:width="1dp"/> diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 04362c17141c..b6fc35553760 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -85,6 +85,7 @@ public class DozeSensors { mProxCallback = proxCallback; mResolver = mContext.getContentResolver(); + boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT); mSensors = new TriggerSensor[] { new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), @@ -116,7 +117,7 @@ public class DozeSensors { new PluginSensor( new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY), Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, - mConfig.wakeScreenGestureAvailable(), + mConfig.wakeScreenGestureAvailable() && alwaysOn, DozeLog.REASON_SENSOR_WAKE_UP, false /* reports touch coordinates */, false /* touchscreen */), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java index 32acb8df173c..610d3003f0e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java @@ -174,7 +174,7 @@ public class NotificationLogger implements StateListener { NotificationVisibility visibility, boolean lifetimeExtended, boolean removedByUser) { - if (removedByUser && visibility != null && entry.notification != null) { + if (removedByUser && visibility != null && entry != null) { logNotificationClear(key, entry.notification, visibility); } } 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 1b18c6cf8440..fd34ac553c8a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -2803,6 +2803,11 @@ public class NotificationPanelView extends PanelView implements if (animatePulse) { mAnimateNextPositionUpdate = true; } + // Do not animate the clock when waking up from a pulse. + // The height callback will take care of pushing the clock to the right position. + if (!mPulsing && !mDozing) { + mAnimateNextPositionUpdate = false; + } mNotificationStackScroller.setPulsing(pulsing, animatePulse); mKeyguardStatusView.setPulsing(pulsing, animatePulse); mKeyguardBottomArea.setPulsing(pulsing, animatePulse); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 2c756ceb1b48..d4049826a50a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -33,6 +33,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.SystemClock; import android.util.AttributeSet; +import android.util.Log; import android.util.TypedValue; import android.view.HapticFeedbackConstants; import android.view.InputDevice; @@ -304,6 +305,10 @@ public class KeyButtonView extends ImageView implements ButtonInterface { .setSubtype(mCode) .addTaggedData(MetricsEvent.FIELD_NAV_ACTION, action) .addTaggedData(MetricsEvent.FIELD_FLAGS, flags)); + // TODO(b/122195391): Added logs to make sure sysui is sending back button events + if (mCode == KeyEvent.KEYCODE_BACK && flags != KeyEvent.FLAG_LONG_PRESS) { + Log.i(TAG, "Back button event: " + KeyEvent.actionToString(action)); + } final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0; final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java index 7b96518ad13f..983ca837b639 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java @@ -42,6 +42,7 @@ import com.android.systemui.UiOffloadThread; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotificationData; +import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; @@ -51,6 +52,8 @@ import com.google.android.collect.Lists; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -72,9 +75,11 @@ public class NotificationLoggerTest extends SysuiTestCase { // Dependency mocks: @Mock private NotificationEntryManager mEntryManager; @Mock private NotificationListener mListener; + @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor; private NotificationData.Entry mEntry; private TestableNotificationLogger mLogger; + private NotificationEntryListener mNotificationEntryListener; private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>(); @Before @@ -94,6 +99,8 @@ public class NotificationLoggerTest extends SysuiTestCase { mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class), mEntryManager, mock(StatusBarStateController.class), mBarService); mLogger.setUpWithContainer(mListContainer); + verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture()); + mNotificationEntryListener = mEntryListenerCaptor.getValue(); } @Test @@ -152,6 +159,11 @@ public class NotificationLoggerTest extends SysuiTestCase { verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any()); } + @Test + public void testHandleNullEntryOnEntryRemoved() { + mNotificationEntryListener.onEntryRemoved(null, "foobar", null, null, false, false); + } + private class TestableNotificationLogger extends NotificationLogger { TestableNotificationLogger(NotificationListener notificationListener, diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index dd2abde10433..d49c4a94256e 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -236,6 +236,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { * {@link AudioManager#ADJUST_SAME}. * * @param packageName The package that made the original volume request. + * @param opPackageName The op package that made the original volume request. * @param pid The pid that made the original volume request. * @param uid The uid that made the original volume request. * @param caller caller binder. can be {@code null} if it's from the volume key. @@ -248,7 +249,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { * @param flags Any of the flags from {@link AudioManager}. * @param useSuggested True to use adjustSuggestedStreamVolume instead of */ - public void adjustVolume(String packageName, int pid, int uid, + public void adjustVolume(String packageName, String opPackageName, int pid, int uid, ControllerCallbackLink caller, boolean asSystemService, int direction, int flags, boolean useSuggested) { int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND; @@ -258,8 +259,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { // Adjust the volume with a handler not to be blocked by other system service. int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs); - postAdjustLocalVolume(stream, direction, flags, packageName, uid, asSystemService, - useSuggested, previousFlagPlaySound); + postAdjustLocalVolume(stream, direction, flags, opPackageName, pid, uid, + asSystemService, useSuggested, previousFlagPlaySound); } else { if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) { // Nothing to do, the volume cannot be changed @@ -290,11 +291,23 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } } - private void setVolumeTo(String packageName, int pid, int uid, + private void setVolumeTo(String packageName, String opPackageName, int pid, int uid, ControllerCallbackLink caller, int value, int flags) { if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs); - mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid); + final int volumeValue = value; + mHandler.post(new Runnable() { + @Override + public void run() { + try { + mAudioManagerInternal.setStreamVolumeForUid(stream, volumeValue, flags, + opPackageName, uid); + } catch (IllegalArgumentException | SecurityException e) { + Log.e(TAG, "Cannot set volume: stream=" + stream + ", value=" + volumeValue + + ", flags=" + flags, e); + } + } + }); } else { if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) { // Nothing to do. The volume can't be set directly. @@ -465,11 +478,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } private void postAdjustLocalVolume(final int stream, final int direction, final int flags, - final String callingPackageName, final int callingUid, final boolean asSystemService, - final boolean useSuggested, final int previousFlagPlaySound) { - final String packageName = asSystemService - ? mContext.getOpPackageName() : callingPackageName; - final int uid = asSystemService ? Process.SYSTEM_UID : callingUid; + final String callingOpPackageName, final int callingPid, final int callingUid, + final boolean asSystemService, final boolean useSuggested, + final int previousFlagPlaySound) { + // Must use opPackageName for adjusting volumes with UID. + final String opPackageName; + final int uid; + if (asSystemService) { + opPackageName = mContext.getOpPackageName(); + uid = Process.SYSTEM_UID; + } else { + opPackageName = callingOpPackageName; + uid = callingUid; + } mHandler.post(new Runnable() { @Override public void run() { @@ -477,19 +498,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { if (useSuggested) { if (AudioSystem.isStreamActive(stream, 0)) { mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, - direction, flags, packageName, uid); + direction, flags, opPackageName, uid); } else { mAudioManagerInternal.adjustSuggestedStreamVolumeForUid( AudioManager.USE_DEFAULT_STREAM_TYPE, direction, - flags | previousFlagPlaySound, packageName, uid); + flags | previousFlagPlaySound, opPackageName, uid); } } else { mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, - packageName, uid); + opPackageName, uid); } } catch (IllegalArgumentException | SecurityException e) { Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream=" - + stream + ", flags=" + flags + ", packageName=" + packageName + + stream + ", flags=" + flags + ", opPackageName=" + opPackageName + ", uid=" + uid + ", useSuggested=" + useSuggested + ", previousFlagPlaySound=" + previousFlagPlaySound, e); } @@ -1256,27 +1277,28 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void adjustVolume(String packageName, ControllerCallbackLink caller, - boolean asSystemService, int direction, int flags) { + public void adjustVolume(String packageName, String opPackageName, + ControllerCallbackLink caller, boolean asSystemService, int direction, int flags) { int pid = Binder.getCallingPid(); int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionRecord.this.adjustVolume(packageName, pid, uid, caller, asSystemService, - direction, flags, false /* useSuggested */); + MediaSessionRecord.this.adjustVolume(packageName, opPackageName, pid, uid, caller, + asSystemService, direction, flags, false /* useSuggested */); } finally { Binder.restoreCallingIdentity(token); } } @Override - public void setVolumeTo(String packageName, ControllerCallbackLink caller, - int value, int flags) { + public void setVolumeTo(String packageName, String opPackageName, + ControllerCallbackLink caller, int value, int flags) { int pid = Binder.getCallingPid(); int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionRecord.this.setVolumeTo(packageName, pid, uid, caller, value, flags); + MediaSessionRecord.this.setVolumeTo(packageName, opPackageName, pid, uid, caller, + value, flags); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index b807c47c09b9..7dbabda21b19 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -35,6 +35,7 @@ import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.media.AudioManager; +import android.media.AudioManagerInternal; import android.media.AudioPlaybackConfiguration; import android.media.AudioSystem; import android.media.IAudioService; @@ -72,6 +73,7 @@ import android.view.KeyEvent; import android.view.ViewConfiguration; import com.android.internal.util.DumpUtils; +import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.Watchdog; import com.android.server.Watchdog.Monitor; @@ -108,6 +110,8 @@ public class MediaSessionService extends SystemService implements Monitor { private KeyguardManager mKeyguardManager; private IAudioService mAudioService; + private AudioManagerInternal mAudioManagerInternal; + private ActivityManager mActivityManager; private ContentResolver mContentResolver; private SettingsObserver mSettingsObserver; private boolean mHasFeatureLeanback; @@ -139,6 +143,9 @@ public class MediaSessionService extends SystemService implements Monitor { mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); mAudioService = getAudioService(); + mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); + mActivityManager = + (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor.registerListener( (config, isRemoved) -> { @@ -1202,7 +1209,8 @@ public class MediaSessionService extends SystemService implements Monitor { * there's no active global priority session, long-pressess will be sent to the * long-press listener instead of adjusting volume. * - * @param packageName The caller package. + * @param packageName The caller's package name, obtained by Context#getPackageName() + * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName() * @param asSystemService {@code true} if the event sent to the session as if it was come * from the system service instead of the app process. This helps sessions to * distinguish between the key injection by the app and key events from the @@ -1217,8 +1225,8 @@ public class MediaSessionService extends SystemService implements Monitor { * @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume. */ @Override - public void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, - KeyEvent keyEvent, int stream, boolean musicOnly) { + public void dispatchVolumeKeyEvent(String packageName, String opPackageName, + boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) { if (keyEvent == null || (keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN @@ -1240,8 +1248,8 @@ public class MediaSessionService extends SystemService implements Monitor { synchronized (mLock) { if (isGlobalPriorityActiveLocked() || mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) { - dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService, - keyEvent, stream, musicOnly); + dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid, + asSystemService, keyEvent, stream, musicOnly); } else { // TODO: Consider the case when both volume up and down keys are pressed // at the same time. @@ -1274,12 +1282,13 @@ public class MediaSessionService extends SystemService implements Monitor { && mCurrentFullUserRecord.mInitialDownVolumeKeyEvent .getDownTime() == keyEvent.getDownTime()) { // Short-press. Should change volume. - dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService, + dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid, + asSystemService, mCurrentFullUserRecord.mInitialDownVolumeKeyEvent, mCurrentFullUserRecord.mInitialDownVolumeStream, mCurrentFullUserRecord.mInitialDownMusicOnly); - dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService, - keyEvent, stream, musicOnly); + dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid, + asSystemService, keyEvent, stream, musicOnly); } else { dispatchVolumeKeyLongPressLocked(keyEvent); } @@ -1291,8 +1300,9 @@ public class MediaSessionService extends SystemService implements Monitor { } } - private void dispatchVolumeKeyEventLocked(String packageName, int pid, int uid, - boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) { + private void dispatchVolumeKeyEventLocked(String packageName, String opPackageName, int pid, + int uid, boolean asSystemService, KeyEvent keyEvent, int stream, + boolean musicOnly) { boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN; boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP; int direction = 0; @@ -1326,26 +1336,26 @@ public class MediaSessionService extends SystemService implements Monitor { if (up) { direction = 0; } - dispatchAdjustVolumeLocked(packageName, pid, uid, asSystemService, stream, - direction, flags); + dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, + asSystemService, stream, direction, flags); } else if (isMute) { if (down && keyEvent.getRepeatCount() == 0) { - dispatchAdjustVolumeLocked(packageName, pid, uid, asSystemService, stream, - AudioManager.ADJUST_TOGGLE_MUTE, flags); + dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, + asSystemService, stream, AudioManager.ADJUST_TOGGLE_MUTE, flags); } } } } @Override - public void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, - int flags) { + public void dispatchAdjustVolume(String packageName, String opPackageName, + int suggestedStream, int delta, int flags) { final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - dispatchAdjustVolumeLocked(packageName, pid, uid, false, + dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, false, suggestedStream, delta, flags); } } finally { @@ -1409,24 +1419,14 @@ public class MediaSessionService extends SystemService implements Monitor { final int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - int controllerUserId = UserHandle.getUserId(controllerUid); - int controllerUidFromPackageName; - try { - controllerUidFromPackageName = getContext().getPackageManager() - .getPackageUidAsUser(controllerPackageName, controllerUserId); - } catch (NameNotFoundException e) { - if (DEBUG) { - Log.d(TAG, "Package " + controllerPackageName + " doesn't exist"); - } - return false; - } - if (controllerUidFromPackageName != controllerUid) { - if (DEBUG) { - Log.d(TAG, "Package name " + controllerPackageName - + " doesn't match with the uid " + controllerUid); - } - return false; - } + // Don't perform sanity check between controllerPackageName and controllerUid. + // When an (activity|service) runs on the another apps process by specifying + // android:process in the AndroidManifest.xml, then PID and UID would have the + // running process' information instead of the (activity|service) that has created + // MediaController. + // Note that we can use Context#getOpPackageName() instead of + // Context#getPackageName() for getting package name that matches with the PID/UID, + // but it doesn't tell which package has created the MediaController, so useless. return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName, controllerPid, controllerUid); } finally { @@ -1497,8 +1497,8 @@ public class MediaSessionService extends SystemService implements Monitor { return false; } - private void dispatchAdjustVolumeLocked(String packageName, int pid, int uid, - boolean asSystemService, int suggestedStream, int direction, int flags) { + private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid, + int uid, boolean asSystemService, int suggestedStream, int direction, int flags) { MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession(); @@ -1529,21 +1529,28 @@ public class MediaSessionService extends SystemService implements Monitor { mHandler.post(new Runnable() { @Override public void run() { + final String callingOpPackageName; + final int callingUid; + if (asSystemService) { + callingOpPackageName = getContext().getOpPackageName(); + callingUid = Process.myUid(); + } else { + callingOpPackageName = opPackageName; + callingUid = uid; + } try { - String packageName = getContext().getOpPackageName(); - mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, - flags, packageName, TAG); - } catch (RemoteException|SecurityException e) { - Log.e(TAG, "Error adjusting default volume.", e); - } catch (IllegalArgumentException e) { + mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream, + direction, flags, callingOpPackageName, callingUid); + } catch (SecurityException | IllegalArgumentException e) { Log.e(TAG, "Cannot adjust volume: direction=" + direction - + ", suggestedStream=" + suggestedStream + ", flags=" + flags, - e); + + ", suggestedStream=" + suggestedStream + ", flags=" + flags + + ", packageName=" + packageName + ", uid=" + uid + + ", asSystemService=" + asSystemService, e); } } }); } else { - session.adjustVolume(packageName, pid, uid, null, asSystemService, + session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService, direction, flags, true); } } diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 6187583a0253..88d73fb10902 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -558,7 +558,7 @@ abstract public class ManagedServices { if (pkgList != null && (pkgList.length > 0)) { boolean anyServicesInvolved = false; // Remove notification settings for uninstalled package - if (removingPackage) { + if (removingPackage && uidList != null) { int size = Math.min(pkgList.length, uidList.length); for (int i = 0; i < size; i++) { final String pkg = pkgList[i]; @@ -570,9 +570,11 @@ abstract public class ManagedServices { if (mEnabledServicesPackageNames.contains(pkgName)) { anyServicesInvolved = true; } - for (int uid : uidList) { - if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) { - anyServicesInvolved = true; + if (uidList != null && uidList.length > 0) { + for (int uid : uidList) { + if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) { + anyServicesInvolved = true; + } } } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index f370edf50708..c7928633eef6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -844,7 +844,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void interceptBackKeyDown() { - MetricsLogger.count(mContext, "key_back_down", 1); + mLogger.count("key_back_down", 1); // Reset back key state for long press mBackKeyHandled = false; @@ -858,6 +858,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // returns true if the key was handled and should not be passed to the user private boolean interceptBackKeyUp(KeyEvent event) { + mLogger.count("key_back_up", 1); // Cache handled state boolean handled = mBackKeyHandled; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index a5ceee268fa2..fecc8da3d645 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2506,6 +2506,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mWmService.mAnimator.removeDisplayLocked(mDisplayId); mWindowingLayer.release(); mOverlayLayer.release(); + mInputMonitor.onDisplayRemoved(); } finally { mDisplayReady = false; mRemovingDisplay = false; diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index fc1c65cf5807..632db3842839 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -32,6 +32,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITION import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.graphics.Rect; +import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Process; @@ -45,7 +46,9 @@ import android.view.InputChannel; import android.view.InputEventReceiver; import android.view.InputWindowHandle; import android.view.SurfaceControl; +import android.view.animation.Animation; +import com.android.server.AnimationThread; import com.android.server.policy.WindowManagerPolicy; import java.io.PrintWriter; @@ -60,6 +63,7 @@ final class InputMonitor { // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; + private boolean mUpdateInputWindowsPending; // Currently focused input window handle. private InputWindowHandle mFocusedInputWindowHandle; @@ -70,8 +74,11 @@ final class InputMonitor { new UpdateInputForAllWindowsConsumer(); private final int mDisplayId; + private final DisplayContent mDisplayContent; + private boolean mDisplayRemoved; private final SurfaceControl.Transaction mInputTransaction; + private final Handler mHandler; /** * The set of input consumer added to the window manager by name, which consumes input events @@ -105,10 +112,64 @@ final class InputMonitor { } } + private final Runnable mUpdateInputWindows = new Runnable() { + @Override + public void run() { + synchronized (mService.mGlobalLock) { + mUpdateInputWindowsPending = false; + mUpdateInputWindowsNeeded = false; + + if (mDisplayRemoved) { + return; + } + + // Populate the input window list with information about all of the windows that + // could potentially receive input. + // As an optimization, we could try to prune the list of windows but this turns + // out to be difficult because only the native code knows for sure which window + // currently has touch focus. + + // If there's a drag in flight, provide a pseudo-window to catch drag input + final boolean inDrag = mService.mDragDropController.dragDropActiveLocked(); + if (inDrag) { + if (DEBUG_DRAG) { + Log.d(TAG_WM, "Inserting drag window"); + } + mService.mDragDropController.showInputSurface(mInputTransaction, mDisplayId); + } else { + mService.mDragDropController.hideInputSurface(mInputTransaction, mDisplayId); + } + + final boolean inPositioning = + mService.mTaskPositioningController.isPositioningLocked(); + if (inPositioning) { + if (DEBUG_TASK_POSITIONING) { + Log.d(TAG_WM, "Inserting window handle for repositioning"); + } + mService.mTaskPositioningController.showInputSurface(mInputTransaction, + mDisplayId); + } else { + mService.mTaskPositioningController.hideInputSurface(mInputTransaction, + mDisplayId); + } + + // Add all windows on the default display. + mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag); + } + } + }; + public InputMonitor(WindowManagerService service, int displayId) { mService = service; + mDisplayContent = mService.mRoot.getDisplayContent(displayId); mDisplayId = displayId; - mInputTransaction = mService.mRoot.getDisplayContent(mDisplayId).getPendingTransaction(); + mInputTransaction = mDisplayContent.getPendingTransaction(); + mHandler = AnimationThread.getHandler(); + } + + void onDisplayRemoved() { + mHandler.removeCallbacks(mUpdateInputWindows); + mDisplayRemoved = true; } private void addInputConsumer(String name, InputConsumerImpl consumer) { @@ -248,41 +309,18 @@ final class InputMonitor { if (!force && !mUpdateInputWindowsNeeded) { return; } - mUpdateInputWindowsNeeded = false; - - if (false) Slog.d(TAG_WM, ">>>>>> ENTERED updateInputWindowsLw"); - - // Populate the input window list with information about all of the windows that - // could potentially receive input. - // As an optimization, we could try to prune the list of windows but this turns - // out to be difficult because only the native code knows for sure which window - // currently has touch focus. + scheduleUpdateInputWindows(); + } - // If there's a drag in flight, provide a pseudo-window to catch drag input - final boolean inDrag = mService.mDragDropController.dragDropActiveLocked(); - if (inDrag) { - if (DEBUG_DRAG) { - Log.d(TAG_WM, "Inserting drag window"); - } - mService.mDragDropController.showInputSurface(mInputTransaction, mDisplayId); - } else { - mService.mDragDropController.hideInputSurface(mInputTransaction, mDisplayId); + private void scheduleUpdateInputWindows() { + if (mDisplayRemoved) { + return; } - final boolean inPositioning = mService.mTaskPositioningController.isPositioningLocked(); - if (inPositioning) { - if (DEBUG_TASK_POSITIONING) { - Log.d(TAG_WM, "Inserting window handle for repositioning"); - } - mService.mTaskPositioningController.showInputSurface(mInputTransaction, mDisplayId); - } else { - mService.mTaskPositioningController.hideInputSurface(mInputTransaction, mDisplayId); + if (!mUpdateInputWindowsPending) { + mUpdateInputWindowsPending = true; + mHandler.post(mUpdateInputWindows); } - - // Add all windows on the default display. - mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag); - - if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw"); } /* Called when the current input focus changes. @@ -385,19 +423,18 @@ final class InputMonitor { mTmpRect.setEmpty(); mDisableWallpaperTouchEvents = false; this.inDrag = inDrag; - final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); - wallpaperController = dc.mWallpaperController; + wallpaperController = mDisplayContent.mWallpaperController; resetInputConsumers(mInputTransaction); - dc.forAllWindows(this, + mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */); if (mAddWallpaperInputConsumerHandle) { wallpaperInputConsumer.show(mInputTransaction, 0); } - dc.scheduleAnimation(); + mDisplayContent.scheduleAnimation(); Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index 659c6e7aeed3..8b65e763b088 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -859,6 +859,19 @@ public class ManagedServicesTest extends UiServiceTestCase { assertTrue(componentsToBind.get(10).contains(ComponentName.unflattenFromString("c/c"))); } + @Test + public void testOnPackagesChanged_nullValuesPassed_noNullPointers() { + for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { + ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, + mIpm, approvalLevel); + // null uid list + service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, null); + + // null package list + service.onPackagesChanged(true, null, new int[]{103}); + } + } + private void loadXml(ManagedServices service) throws Exception { final StringBuffer xml = new StringBuffer(); xml.append("<" + service.getConfig().xmlTag + ">\n"); |