diff options
196 files changed, 3801 insertions, 1671 deletions
diff --git a/apct-tests/perftests/windowmanager/Android.bp b/apct-tests/perftests/windowmanager/Android.bp index 9fa99853ace3..dbfe6ab3210f 100644 --- a/apct-tests/perftests/windowmanager/Android.bp +++ b/apct-tests/perftests/windowmanager/Android.bp @@ -23,6 +23,7 @@ android_test { "platform-test-annotations", ], test_suites: ["device-tests"], + data: [":perfetto_artifacts"], platform_apis: true, certificate: "platform", } diff --git a/apct-tests/perftests/windowmanager/AndroidTest.xml b/apct-tests/perftests/windowmanager/AndroidTest.xml index 0a80cf96fba3..aee02c7ab767 100644 --- a/apct-tests/perftests/windowmanager/AndroidTest.xml +++ b/apct-tests/perftests/windowmanager/AndroidTest.xml @@ -28,14 +28,42 @@ <option name="run-command" value="cmd package compile -m speed com.android.perftests.wm" /> </target_preparer> + <!-- Needed for pushing the trace config file --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" /> + </target_preparer> + + <!-- Needed for storing the perfetto trace files in the sdcard/test_results--> + <option name="isolated-storage" value="false" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.perftests.wm" /> <option name="hidden-api-checks" value="false"/> - <option name="device-listeners" value="android.wm.WmPerfRunListener" /> + + <!-- Listener related args for collecting the traces and waiting for the device to stabilize. --> + <option name="device-listeners" value="android.wm.WmPerfRunListener,android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" /> + + <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. --> + <option name="instrumentation-arg" key="newRunListenerMode" value="true" /> + + <!-- ProcLoadListener related arguments --> + <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run --> + <option name="instrumentation-arg" key="procload-collector:per_run" value="true" /> + <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" /> + <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" /> + <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" /> + + <!-- PerfettoListener related arguments --> + <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" /> + <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" /> + + <option name="instrumentation-arg" key="newRunListenerMode" value="true" /> </test> <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> - <option name="directory-keys" value="/data/local/WmPerfTests" /> - <option name="collect-on-run-ended-only" value="true" /> + <option name="directory-keys" value="/data/local/tmp/WmPerfTests" /> + <!-- Needed for pulling the collected trace config on to the host --> + <option name="pull-pattern-keys" value="perfetto_file_path" /> </metrics_collector> </configuration> diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java index dc6245bf2c09..cc0e939a2a80 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java @@ -55,7 +55,7 @@ public class WindowManagerPerfTestBase { * is in /data because while enabling method profling of system server, it cannot write the * trace to external storage. */ - static final File BASE_OUT_PATH = new File("/data/local/WmPerfTests"); + static final File BASE_OUT_PATH = new File("/data/local/tmp/WmPerfTests"); @BeforeClass public static void setUpOnce() { diff --git a/api/current.txt b/api/current.txt index 532c3d938334..9e0d88ecdfd1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -46987,7 +46987,7 @@ package android.telephony { method public long getNci(); method @IntRange(from=0, to=3279165) public int getNrarfcn(); method @IntRange(from=0, to=1007) public int getPci(); - method @IntRange(from=0, to=65535) public int getTac(); + method @IntRange(from=0, to=16777215) public int getTac(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR; } diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index 7cd8a628c9fc..17545a469cb8 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -46,6 +46,13 @@ package android.media.session { field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000 } + public final class MediaSessionManager { + method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent); + method public boolean dispatchMediaKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent); + method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int); + method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent); + } + } package android.net { diff --git a/api/system-current.txt b/api/system-current.txt index ea16238316ac..3ab164554da6 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -12171,6 +12171,7 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); + field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43 field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 diff --git a/api/test-current.txt b/api/test-current.txt index a1d1fa781096..620c5b30b925 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4618,6 +4618,7 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); + field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43 field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 diff --git a/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp index 744ec375efdf..86b148dd8657 100644 --- a/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp @@ -65,7 +65,7 @@ void SimpleAtomMatchingTracker::onLogEvent( bool matched = matchesSimple(mUidMap, mMatcher, event); matcherResults[mIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched; - VLOG("Stats SimpleLogMatcher %lld matched? %d", (long long)mId, matched); + VLOG("Stats SimpleAtomMatcher %lld matched? %d", (long long)mId, matched); } } // namespace statsd diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 267b81823688..d67b98620f37 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -614,7 +614,7 @@ public final class ActivityThread extends ClientTransactionHandler { throw new IllegalStateException( "Received config update for non-existing activity"); } - activity.mMainThread.handleActivityConfigurationChanged(this, overrideConfig, + activity.mMainThread.handleActivityConfigurationChanged(token, overrideConfig, newDisplayId); }; } @@ -3475,9 +3475,13 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handleStartActivity(ActivityClientRecord r, - PendingTransactionActions pendingActions) { + public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) { + final ActivityClientRecord r = mActivities.get(token); final Activity activity = r.activity; + if (r.activity == null) { + // TODO(lifecycler): What do we do in this case? + return; + } if (!r.stopped) { throw new IllegalStateException("Can't start activity that is not stopped."); } @@ -3683,7 +3687,12 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handleNewIntent(ActivityClientRecord r, List<ReferrerIntent> intents) { + public void handleNewIntent(IBinder token, List<ReferrerIntent> intents) { + final ActivityClientRecord r = mActivities.get(token); + if (r == null) { + return; + } + checkAndBlockForNetworkAccess(); deliverNewIntents(r, intents); } @@ -3872,7 +3881,13 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handlePictureInPictureRequested(ActivityClientRecord r) { + public void handlePictureInPictureRequested(IBinder token) { + final ActivityClientRecord r = mActivities.get(token); + if (r == null) { + Log.w(TAG, "Activity to request PIP to no longer exists"); + return; + } + final boolean receivedByApp = r.activity.onPictureInPictureRequested(); if (!receivedByApp) { // Previous recommendation was for apps to enter picture-in-picture in @@ -4402,21 +4417,22 @@ public final class ActivityThread extends ClientTransactionHandler { /** * Resume the activity. - * @param r Target activity record. + * @param token Target activity token. * @param finalStateRequest Flag indicating if this is part of final state resolution for a * transaction. * @param reason Reason for performing the action. * - * @return {@code true} that was resumed, {@code false} otherwise. + * @return The {@link ActivityClientRecord} that was resumed, {@code null} otherwise. */ @VisibleForTesting - public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest, + public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest, String reason) { + final ActivityClientRecord r = mActivities.get(token); if (localLOGV) { Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished); } - if (r.activity.mFinished) { - return false; + if (r == null || r.activity.mFinished) { + return null; } if (r.getLifecycleState() == ON_RESUME) { if (!finalStateRequest) { @@ -4430,7 +4446,7 @@ public final class ActivityThread extends ClientTransactionHandler { // handle two resume requests for the final state. For cases other than this // one, we don't expect it to happen. } - return false; + return null; } if (finalStateRequest) { r.hideForNow = false; @@ -4461,7 +4477,7 @@ public final class ActivityThread extends ClientTransactionHandler { + r.intent.getComponent().toShortString() + ": " + e.toString(), e); } } - return true; + return r; } static final void cleanUpPendingRemoveWindows(ActivityClientRecord r, boolean force) { @@ -4482,19 +4498,20 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest, - boolean isForward, String reason) { + public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, + String reason) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true; // TODO Push resumeArgs into the activity for consideration - // skip below steps for double-resume and r.mFinish = true case. - if (!performResumeActivity(r, finalStateRequest, reason)) { + final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason); + if (r == null) { + // We didn't actually resume the activity, so skipping any follow-up actions. return; } - if (mActivitiesToBeDestroyed.containsKey(r.token)) { + if (mActivitiesToBeDestroyed.containsKey(token)) { // Although the activity is resumed, it is going to be destroyed. So the following // UI operations are unnecessary and also prevents exception because its token may // be gone that window manager cannot recognize it. All necessary cleanup actions @@ -4612,8 +4629,13 @@ public final class ActivityThread extends ClientTransactionHandler { @Override - public void handleTopResumedActivityChanged(ActivityClientRecord r, boolean onTop, - String reason) { + public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) { + ActivityClientRecord r = mActivities.get(token); + if (r == null || r.activity == null) { + Slog.w(TAG, "Not found target activity to report position change for token: " + token); + return; + } + if (DEBUG_ORDER) { Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r); } @@ -4646,20 +4668,23 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving, + public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) { - if (userLeaving) { - performUserLeavingActivity(r); - } + ActivityClientRecord r = mActivities.get(token); + if (r != null) { + if (userLeaving) { + performUserLeavingActivity(r); + } - r.activity.mConfigChangeFlags |= configChanges; - performPauseActivity(r, finished, reason, pendingActions); + r.activity.mConfigChangeFlags |= configChanges; + performPauseActivity(r, finished, reason, pendingActions); - // Make sure any pending writes are now committed. - if (r.isPreHoneycomb()) { - QueuedWork.waitToFinish(); + // Make sure any pending writes are now committed. + if (r.isPreHoneycomb()) { + QueuedWork.waitToFinish(); + } + mSomeActivitiesChanged = true; } - mSomeActivitiesChanged = true; } final void performUserLeavingActivity(ActivityClientRecord r) { @@ -4756,11 +4781,8 @@ public final class ActivityThread extends ClientTransactionHandler { r.setState(ON_PAUSE); } - // TODO(b/127877792): Make LocalActivityManager call performStopActivityInner. We cannot do this - // since it's a high usage hidden API. /** Called from {@link LocalActivityManager}. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 127877792, - publicAlternatives = "{@code N/A}") + @UnsupportedAppUsage final void performStopActivity(IBinder token, boolean saveState, String reason) { ActivityClientRecord r = mActivities.get(token); performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */, @@ -4801,37 +4823,39 @@ public final class ActivityThread extends ClientTransactionHandler { private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean saveState, boolean finalStateRequest, String reason) { if (localLOGV) Slog.v(TAG, "Performing stop of " + r); - if (r.stopped) { - if (r.activity.mFinished) { - // If we are finishing, we won't call onResume() in certain - // cases. So here we likewise don't want to call onStop() - // if the activity isn't resumed. - return; - } - if (!finalStateRequest) { - final RuntimeException e = new RuntimeException( - "Performing stop of activity that is already stopped: " - + r.intent.getComponent().toShortString()); - Slog.e(TAG, e.getMessage(), e); - Slog.e(TAG, r.getStateString()); + if (r != null) { + if (r.stopped) { + if (r.activity.mFinished) { + // If we are finishing, we won't call onResume() in certain + // cases. So here we likewise don't want to call onStop() + // if the activity isn't resumed. + return; + } + if (!finalStateRequest) { + final RuntimeException e = new RuntimeException( + "Performing stop of activity that is already stopped: " + + r.intent.getComponent().toShortString()); + Slog.e(TAG, e.getMessage(), e); + Slog.e(TAG, r.getStateString()); + } } - } - // One must first be paused before stopped... - performPauseActivityIfNeeded(r, reason); + // One must first be paused before stopped... + performPauseActivityIfNeeded(r, reason); - if (info != null) { - try { - // First create a thumbnail for the activity... - // For now, don't create the thumbnail here; we are - // doing that by doing a screen snapshot. - info.setDescription(r.activity.onCreateDescription()); - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to save state of activity " - + r.intent.getComponent().toShortString() - + ": " + e.toString(), e); + if (info != null) { + try { + // First create a thumbnail for the activity... + // For now, don't create the thumbnail here; we are + // doing that by doing a screen snapshot. + info.setDescription(r.activity.onCreateDescription()); + } catch (Exception e) { + if (!mInstrumentation.onException(r.activity, e)) { + throw new RuntimeException( + "Unable to save state of activity " + + r.intent.getComponent().toShortString() + + ": " + e.toString(), e); + } } } @@ -4903,8 +4927,9 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handleStopActivity(ActivityClientRecord r, int configChanges, + public void handleStopActivity(IBinder token, int configChanges, PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) { + final ActivityClientRecord r = mActivities.get(token); r.activity.mConfigChangeFlags |= configChanges; final StopInfo stopInfo = new StopInfo(); @@ -4940,7 +4965,8 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void performRestartActivity(ActivityClientRecord r, boolean start) { + public void performRestartActivity(IBinder token, boolean start) { + ActivityClientRecord r = mActivities.get(token); if (r.stopped) { r.activity.performRestart(start, "performRestartActivity"); if (start) { @@ -5027,101 +5053,107 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handleSendResult(ActivityClientRecord r, List<ResultInfo> results, String reason) { + public void handleSendResult(IBinder token, List<ResultInfo> results, String reason) { + ActivityClientRecord r = mActivities.get(token); if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r); - final boolean resumed = !r.paused; - if (!r.activity.mFinished && r.activity.mDecor != null - && r.hideForNow && resumed) { - // We had hidden the activity because it started another - // one... we have gotten a result back and we are not - // paused, so make sure our window is visible. - updateVisibility(r, true); - } - if (resumed) { - try { - // Now we are idle. - r.activity.mCalled = false; - mInstrumentation.callActivityOnPause(r.activity); - if (!r.activity.mCalled) { - throw new SuperNotCalledException( - "Activity " + r.intent.getComponent().toShortString() - + " did not call through to super.onPause()"); - } - } catch (SuperNotCalledException e) { - throw e; - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to pause activity " - + r.intent.getComponent().toShortString() - + ": " + e.toString(), e); + if (r != null) { + final boolean resumed = !r.paused; + if (!r.activity.mFinished && r.activity.mDecor != null + && r.hideForNow && resumed) { + // We had hidden the activity because it started another + // one... we have gotten a result back and we are not + // paused, so make sure our window is visible. + updateVisibility(r, true); + } + if (resumed) { + try { + // Now we are idle. + r.activity.mCalled = false; + mInstrumentation.callActivityOnPause(r.activity); + if (!r.activity.mCalled) { + throw new SuperNotCalledException( + "Activity " + r.intent.getComponent().toShortString() + + " did not call through to super.onPause()"); + } + } catch (SuperNotCalledException e) { + throw e; + } catch (Exception e) { + if (!mInstrumentation.onException(r.activity, e)) { + throw new RuntimeException( + "Unable to pause activity " + + r.intent.getComponent().toShortString() + + ": " + e.toString(), e); + } } } - } - checkAndBlockForNetworkAccess(); - deliverResults(r, results, reason); - if (resumed) { - r.activity.performResume(false, reason); + checkAndBlockForNetworkAccess(); + deliverResults(r, results, reason); + if (resumed) { + r.activity.performResume(false, reason); + } } } /** Core implementation of activity destroy call. */ - ActivityClientRecord performDestroyActivity(ActivityClientRecord r, boolean finishing, + ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) { + ActivityClientRecord r = mActivities.get(token); Class<? extends Activity> activityClass = null; if (localLOGV) Slog.v(TAG, "Performing finish of " + r); - activityClass = r.activity.getClass(); - r.activity.mConfigChangeFlags |= configChanges; - if (finishing) { - r.activity.mFinished = true; - } + if (r != null) { + activityClass = r.activity.getClass(); + r.activity.mConfigChangeFlags |= configChanges; + if (finishing) { + r.activity.mFinished = true; + } - performPauseActivityIfNeeded(r, "destroy"); + performPauseActivityIfNeeded(r, "destroy"); - if (!r.stopped) { - callActivityOnStop(r, false /* saveState */, "destroy"); - } - if (getNonConfigInstance) { + if (!r.stopped) { + callActivityOnStop(r, false /* saveState */, "destroy"); + } + if (getNonConfigInstance) { + try { + r.lastNonConfigurationInstances + = r.activity.retainNonConfigurationInstances(); + } catch (Exception e) { + if (!mInstrumentation.onException(r.activity, e)) { + throw new RuntimeException( + "Unable to retain activity " + + r.intent.getComponent().toShortString() + + ": " + e.toString(), e); + } + } + } try { - r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances(); + r.activity.mCalled = false; + mInstrumentation.callActivityOnDestroy(r.activity); + if (!r.activity.mCalled) { + throw new SuperNotCalledException( + "Activity " + safeToComponentShortString(r.intent) + + " did not call through to super.onDestroy()"); + } + if (r.window != null) { + r.window.closeAllPanels(); + } + } catch (SuperNotCalledException e) { + throw e; } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( - "Unable to retain activity " - + r.intent.getComponent().toShortString() + "Unable to destroy activity " + safeToComponentShortString(r.intent) + ": " + e.toString(), e); } } r.setState(ON_DESTROY); mLastReportedWindowingMode.remove(r.activity.getActivityToken()); } - try { - r.activity.mCalled = false; - mInstrumentation.callActivityOnDestroy(r.activity); - if (!r.activity.mCalled) { - throw new SuperNotCalledException( - "Activity " + safeToComponentShortString(r.intent) - + " did not call through to super.onDestroy()"); - } - if (r.window != null) { - r.window.closeAllPanels(); - } - } catch (SuperNotCalledException e) { - throw e; - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to destroy activity " + safeToComponentShortString(r.intent) - + ": " + e.toString(), e); - } - } - r.setState(ON_DESTROY); schedulePurgeIdler(); // updatePendingActivityConfiguration() reads from mActivities to update // ActivityClientRecord which runs in a different thread. Protect modifications to // mActivities to avoid race. synchronized (mResourcesManager) { - mActivities.remove(r.token); + mActivities.remove(token); } StrictMode.decrementExpectedActivityCount(activityClass); return r; @@ -5138,67 +5170,70 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges, + public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) { - r = performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason); - cleanUpPendingRemoveWindows(r, finishing); - WindowManager wm = r.activity.getWindowManager(); - View v = r.activity.mDecor; - if (v != null) { - if (r.activity.mVisibleFromServer) { - mNumVisibleActivities--; - } - IBinder wtoken = v.getWindowToken(); - if (r.activity.mWindowAdded) { - if (r.mPreserveWindow) { - // Hold off on removing this until the new activity's - // window is being added. - r.mPendingRemoveWindow = r.window; - r.mPendingRemoveWindowManager = wm; - // We can only keep the part of the view hierarchy that we control, - // everything else must be removed, because it might not be able to - // behave properly when activity is relaunching. - r.window.clearContentView(); - } else { - wm.removeViewImmediate(v); + ActivityClientRecord r = performDestroyActivity(token, finishing, + configChanges, getNonConfigInstance, reason); + if (r != null) { + cleanUpPendingRemoveWindows(r, finishing); + WindowManager wm = r.activity.getWindowManager(); + View v = r.activity.mDecor; + if (v != null) { + if (r.activity.mVisibleFromServer) { + mNumVisibleActivities--; } - } - if (wtoken != null && r.mPendingRemoveWindow == null) { - WindowManagerGlobal.getInstance().closeAll(wtoken, - r.activity.getClass().getName(), "Activity"); - } else if (r.mPendingRemoveWindow != null) { - // We're preserving only one window, others should be closed so app views - // will be detached before the final tear down. It should be done now because - // some components (e.g. WebView) rely on detach callbacks to perform receiver - // unregister and other cleanup. - WindowManagerGlobal.getInstance().closeAllExceptView(r.token, v, + IBinder wtoken = v.getWindowToken(); + if (r.activity.mWindowAdded) { + if (r.mPreserveWindow) { + // Hold off on removing this until the new activity's + // window is being added. + r.mPendingRemoveWindow = r.window; + r.mPendingRemoveWindowManager = wm; + // We can only keep the part of the view hierarchy that we control, + // everything else must be removed, because it might not be able to + // behave properly when activity is relaunching. + r.window.clearContentView(); + } else { + wm.removeViewImmediate(v); + } + } + if (wtoken != null && r.mPendingRemoveWindow == null) { + WindowManagerGlobal.getInstance().closeAll(wtoken, + r.activity.getClass().getName(), "Activity"); + } else if (r.mPendingRemoveWindow != null) { + // We're preserving only one window, others should be closed so app views + // will be detached before the final tear down. It should be done now because + // some components (e.g. WebView) rely on detach callbacks to perform receiver + // unregister and other cleanup. + WindowManagerGlobal.getInstance().closeAllExceptView(token, v, + r.activity.getClass().getName(), "Activity"); + } + r.activity.mDecor = null; + } + if (r.mPendingRemoveWindow == null) { + // If we are delaying the removal of the activity window, then + // we can't clean up all windows here. Note that we can't do + // so later either, which means any windows that aren't closed + // by the app will leak. Well we try to warning them a lot + // about leaking windows, because that is a bug, so if they are + // using this recreate facility then they get to live with leaks. + WindowManagerGlobal.getInstance().closeAll(token, r.activity.getClass().getName(), "Activity"); } - r.activity.mDecor = null; - } - if (r.mPendingRemoveWindow == null) { - // If we are delaying the removal of the activity window, then - // we can't clean up all windows here. Note that we can't do - // so later either, which means any windows that aren't closed - // by the app will leak. Well we try to warning them a lot - // about leaking windows, because that is a bug, so if they are - // using this recreate facility then they get to live with leaks. - WindowManagerGlobal.getInstance().closeAll(r.token, - r.activity.getClass().getName(), "Activity"); - } - // Mocked out contexts won't be participating in the normal - // process lifecycle, but if we're running with a proper - // ApplicationContext we need to have it tear down things - // cleanly. - Context c = r.activity.getBaseContext(); - if (c instanceof ContextImpl) { - ((ContextImpl) c).scheduleFinalCleanup( - r.activity.getClass().getName(), "Activity"); + // Mocked out contexts won't be participating in the normal + // process lifecycle, but if we're running with a proper + // ApplicationContext we need to have it tear down things + // cleanly. + Context c = r.activity.getBaseContext(); + if (c instanceof ContextImpl) { + ((ContextImpl) c).scheduleFinalCleanup( + r.activity.getClass().getName(), "Activity"); + } } if (finishing) { try { - ActivityTaskManager.getService().activityDestroyed(r.token); + ActivityTaskManager.getService().activityDestroyed(token); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } @@ -5421,7 +5456,7 @@ public final class ActivityThread extends ClientTransactionHandler { callActivityOnStop(r, true /* saveState */, reason); } - handleDestroyActivity(r, false, configChanges, true, reason); + handleDestroyActivity(r.token, false, configChanges, true, reason); r.activity = null; r.window = null; @@ -5449,10 +5484,12 @@ public final class ActivityThread extends ClientTransactionHandler { } @Override - public void reportRelaunch(ActivityClientRecord r, PendingTransactionActions pendingActions) { + public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) { try { - ActivityTaskManager.getService().activityRelaunched(r.token); - if (pendingActions.shouldReportRelaunchToWindowManager() && r.window != null) { + ActivityTaskManager.getService().activityRelaunched(token); + final ActivityClientRecord r = mActivities.get(token); + if (pendingActions.shouldReportRelaunchToWindowManager() && r != null + && r.window != null) { r.window.reportActivityRelaunched(); } } catch (RemoteException e) { @@ -5611,7 +5648,13 @@ public final class ActivityThread extends ClientTransactionHandler { */ private Configuration performActivityConfigurationChanged(Activity activity, Configuration newConfig, Configuration amOverrideConfig, int displayId) { + if (activity == null) { + throw new IllegalArgumentException("No activity provided."); + } final IBinder activityToken = activity.getActivityToken(); + if (activityToken == null) { + throw new IllegalArgumentException("Activity token not set. Is the activity attached?"); + } final boolean movedToDifferentDisplay = isDifferentDisplay(activity, displayId); boolean shouldReportChange = false; @@ -5911,8 +5954,20 @@ public final class ActivityThread extends ClientTransactionHandler { * processing any configurations older than {@code overrideConfig}. */ @Override - public void updatePendingActivityConfiguration(ActivityClientRecord r, + public void updatePendingActivityConfiguration(IBinder activityToken, Configuration overrideConfig) { + final ActivityClientRecord r; + synchronized (mResourcesManager) { + r = mActivities.get(activityToken); + } + + if (r == null) { + if (DEBUG_CONFIGURATION) { + Slog.w(TAG, "Not found target activity to update its pending config."); + } + return; + } + synchronized (r) { if (r.mPendingOverrideConfig != null && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) { @@ -5932,14 +5987,21 @@ public final class ActivityThread extends ClientTransactionHandler { * if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been called with * a newer config than {@code overrideConfig}. * - * @param r Target activity record. + * @param activityToken Target activity token. * @param overrideConfig Activity override config. * @param displayId Id of the display where activity was moved to, -1 if there was no move and * value didn't change. */ @Override - public void handleActivityConfigurationChanged(ActivityClientRecord r, + public void handleActivityConfigurationChanged(IBinder activityToken, @NonNull Configuration overrideConfig, int displayId) { + ActivityClientRecord r = mActivities.get(activityToken); + // Check input params. + if (r == null || r.activity == null) { + if (DEBUG_CONFIGURATION) Slog.w(TAG, "Not found target activity to report to: " + r); + return; + } + synchronized (r) { if (overrideConfig.isOtherSeqNewer(r.mPendingOverrideConfig)) { if (DEBUG_CONFIGURATION) { diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index ac50676ff46b..2df756e80fde 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -15,8 +15,6 @@ */ package android.app; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.ClientTransactionItem; import android.app.servertransaction.PendingTransactionActions; @@ -91,38 +89,37 @@ public abstract class ClientTransactionHandler { public abstract Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed(); /** Destroy the activity. */ - public abstract void handleDestroyActivity(@NonNull ActivityClientRecord r, boolean finishing, - int configChanges, boolean getNonConfigInstance, String reason); + public abstract void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, + boolean getNonConfigInstance, String reason); /** Pause the activity. */ - public abstract void handlePauseActivity(@NonNull ActivityClientRecord r, boolean finished, - boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, - String reason); + public abstract void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, + int configChanges, PendingTransactionActions pendingActions, String reason); /** * Resume the activity. - * @param r Target activity record. + * @param token Target activity token. * @param finalStateRequest Flag indicating if this call is handling final lifecycle state * request for a transaction. * @param isForward Flag indicating if next transition is forward. * @param reason Reason for performing this operation. */ - public abstract void handleResumeActivity(@NonNull ActivityClientRecord r, - boolean finalStateRequest, boolean isForward, String reason); + public abstract void handleResumeActivity(IBinder token, boolean finalStateRequest, + boolean isForward, String reason); /** * Notify the activity about top resumed state change. - * @param r Target activity record. + * @param token Target activity token. * @param isTopResumedActivity Current state of the activity, {@code true} if it's the * topmost resumed activity in the system, {@code false} otherwise. * @param reason Reason for performing this operation. */ - public abstract void handleTopResumedActivityChanged(@NonNull ActivityClientRecord r, + public abstract void handleTopResumedActivityChanged(IBinder token, boolean isTopResumedActivity, String reason); /** * Stop the activity. - * @param r Target activity record. + * @param token Target activity token. * @param configChanges Activity configuration changes. * @param pendingActions Pending actions to be used on this or later stages of activity * transaction. @@ -130,40 +127,38 @@ public abstract class ClientTransactionHandler { * request for a transaction. * @param reason Reason for performing this operation. */ - public abstract void handleStopActivity(@NonNull ActivityClientRecord r, int configChanges, + public abstract void handleStopActivity(IBinder token, int configChanges, PendingTransactionActions pendingActions, boolean finalStateRequest, String reason); /** Report that activity was stopped to server. */ public abstract void reportStop(PendingTransactionActions pendingActions); /** Restart the activity after it was stopped. */ - public abstract void performRestartActivity(@NonNull ActivityClientRecord r, boolean start); + public abstract void performRestartActivity(IBinder token, boolean start); /** Set pending activity configuration in case it will be updated by other transaction item. */ - public abstract void updatePendingActivityConfiguration(@NonNull ActivityClientRecord r, + public abstract void updatePendingActivityConfiguration(IBinder activityToken, Configuration overrideConfig); /** Deliver activity (override) configuration change. */ - public abstract void handleActivityConfigurationChanged(@NonNull ActivityClientRecord r, + public abstract void handleActivityConfigurationChanged(IBinder activityToken, Configuration overrideConfig, int displayId); /** Deliver result from another activity. */ - public abstract void handleSendResult( - @NonNull ActivityClientRecord r, List<ResultInfo> results, String reason); + public abstract void handleSendResult(IBinder token, List<ResultInfo> results, String reason); /** Deliver new intent. */ - public abstract void handleNewIntent( - @NonNull ActivityClientRecord r, List<ReferrerIntent> intents); + public abstract void handleNewIntent(IBinder token, List<ReferrerIntent> intents); /** Request that an activity enter picture-in-picture. */ - public abstract void handlePictureInPictureRequested(@NonNull ActivityClientRecord r); + public abstract void handlePictureInPictureRequested(IBinder token); /** Perform activity launch. */ - public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r, + public abstract Activity handleLaunchActivity(ActivityThread.ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent); /** Perform activity start. */ - public abstract void handleStartActivity(@NonNull ActivityClientRecord r, + public abstract void handleStartActivity(IBinder token, PendingTransactionActions pendingActions); /** Get package info. */ @@ -181,7 +176,7 @@ public abstract class ClientTransactionHandler { * Get {@link android.app.ActivityThread.ActivityClientRecord} instance that corresponds to the * provided token. */ - public abstract ActivityClientRecord getActivityClient(IBinder token); + public abstract ActivityThread.ActivityClientRecord getActivityClient(IBinder token); /** * Prepare activity relaunch to update internal bookkeeping. This is used to track multiple @@ -196,7 +191,7 @@ public abstract class ClientTransactionHandler { * @return An initialized instance of {@link ActivityThread.ActivityClientRecord} to use during * relaunch, or {@code null} if relaunch cancelled. */ - public abstract ActivityClientRecord prepareRelaunchActivity(IBinder token, + public abstract ActivityThread.ActivityClientRecord prepareRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, int configChanges, MergedConfiguration config, boolean preserveWindow); @@ -205,15 +200,14 @@ public abstract class ClientTransactionHandler { * @param r Activity client record prepared for relaunch. * @param pendingActions Pending actions to be used on later stages of activity transaction. * */ - public abstract void handleRelaunchActivity(@NonNull ActivityClientRecord r, + public abstract void handleRelaunchActivity(ActivityThread.ActivityClientRecord r, PendingTransactionActions pendingActions); /** * Report that relaunch request was handled. - * @param r Target activity record. + * @param token Target activity token. * @param pendingActions Pending actions initialized on earlier stages of activity transaction. * Used to check if we should report relaunch to WM. * */ - public abstract void reportRelaunch(@NonNull ActivityClientRecord r, - PendingTransactionActions pendingActions); + public abstract void reportRelaunch(IBinder token, PendingTransactionActions pendingActions); } diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index d61c5d5ccd3d..7cdf85e0a6b8 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -49,7 +49,6 @@ public class LocalActivityManager { private static final String TAG = "LocalActivityManager"; private static final boolean localLOGV = false; - // TODO(b/127877792): try to remove this and use {@code ActivityClientRecord} instead. // Internal token for an Activity being managed by LocalActivityManager. private static class LocalActivityRecord extends Binder { LocalActivityRecord(String _id, Intent _intent) { @@ -137,7 +136,7 @@ public class LocalActivityManager { // startActivity() has not yet been called, so nothing to do. return; } - + if (r.curState == INITIALIZING) { // Get the lastNonConfigurationInstance for the activity HashMap<String, Object> lastNonConfigurationInstances = @@ -178,13 +177,12 @@ public class LocalActivityManager { pendingActions = null; } - mActivityThread.handleStartActivity(clientRecord, pendingActions); + mActivityThread.handleStartActivity(r, pendingActions); r.curState = STARTED; if (desiredState == RESUMED) { if (localLOGV) Log.v(TAG, r.id + ": resuming"); - mActivityThread.performResumeActivity(clientRecord, true, - "moveToState-INITIALIZING"); + mActivityThread.performResumeActivity(r, true, "moveToState-INITIALIZING"); r.curState = RESUMED; } @@ -196,21 +194,18 @@ public class LocalActivityManager { // group's state catches up. return; } - - final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r); - + switch (r.curState) { case CREATED: if (desiredState == STARTED) { if (localLOGV) Log.v(TAG, r.id + ": restarting"); - mActivityThread.performRestartActivity(clientRecord, true /* start */); + mActivityThread.performRestartActivity(r, true /* start */); r.curState = STARTED; } if (desiredState == RESUMED) { if (localLOGV) Log.v(TAG, r.id + ": restarting and resuming"); - mActivityThread.performRestartActivity(clientRecord, true /* start */); - mActivityThread.performResumeActivity(clientRecord, true, - "moveToState-CREATED"); + mActivityThread.performRestartActivity(r, true /* start */); + mActivityThread.performResumeActivity(r, true, "moveToState-CREATED"); r.curState = RESUMED; } return; @@ -219,8 +214,7 @@ public class LocalActivityManager { if (desiredState == RESUMED) { // Need to resume it... if (localLOGV) Log.v(TAG, r.id + ": resuming"); - mActivityThread.performResumeActivity(clientRecord, true, - "moveToState-STARTED"); + mActivityThread.performResumeActivity(r, true, "moveToState-STARTED"); r.instanceState = null; r.curState = RESUMED; } @@ -358,8 +352,7 @@ public class LocalActivityManager { ArrayList<ReferrerIntent> intents = new ArrayList<>(1); intents.add(new ReferrerIntent(intent, mParent.getPackageName())); if (localLOGV) Log.v(TAG, r.id + ": new intent"); - final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r); - mActivityThread.handleNewIntent(clientRecord, intents); + mActivityThread.handleNewIntent(r, intents); r.intent = intent; moveToState(r, mCurState); if (mSingleMode) { @@ -406,8 +399,7 @@ public class LocalActivityManager { performPause(r, finish); } if (localLOGV) Log.v(TAG, r.id + ": destroying"); - final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r); - mActivityThread.performDestroyActivity(clientRecord, finish, 0 /* configChanges */, + mActivityThread.performDestroyActivity(r, finish, 0 /* configChanges */, false /* getNonConfigInstance */, "LocalActivityManager::performDestroy"); r.activity = null; r.window = null; @@ -672,8 +664,7 @@ public class LocalActivityManager { for (int i=0; i<N; i++) { LocalActivityRecord r = mActivityArray.get(i); if (localLOGV) Log.v(TAG, r.id + ": destroying"); - final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r); - mActivityThread.performDestroyActivity(clientRecord, finishing, 0 /* configChanges */, + mActivityThread.performDestroyActivity(r, finishing, 0 /* configChanges */, false /* getNonConfigInstance */, "LocalActivityManager::dispatchDestroy"); } mActivities.clear(); diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 54f3f1026050..6c6c04e4e975 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -413,7 +413,7 @@ public abstract class PropertyInvalidatedCache<Query, Result> { public final void disableLocal() { synchronized (mLock) { mDisabled = true; - mCache.clear(); + clear(); } } @@ -463,7 +463,7 @@ public abstract class PropertyInvalidatedCache<Query, Result> { cacheName(), mCache.size(), mLastSeenNonce, currentNonce)); } - mCache.clear(); + clear(); mLastSeenNonce = currentNonce; cachedResult = null; } @@ -728,9 +728,13 @@ public abstract class PropertyInvalidatedCache<Query, Result> { * It's better to use explicit cork and uncork pairs that tighly surround big batches of * invalidations, but it's not always practical to tell where these invalidation batches * might occur. AutoCorker's time-based corking is a decent alternative. + * + * The auto-cork delay is configurable but it should not be too long. The purpose of + * the delay is to minimize the number of times a server writes to the system property + * when invalidating the cache. One write every 50ms does not hurt system performance. */ public static final class AutoCorker { - public static final int DEFAULT_AUTO_CORK_DELAY_MS = 2000; + public static final int DEFAULT_AUTO_CORK_DELAY_MS = 50; private final String mPropertyName; private final int mAutoCorkDelayMs; diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java index 8a4bee98ca87..8b52242a6b6c 100644 --- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java +++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java @@ -20,7 +20,6 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.content.res.Configuration; import android.os.IBinder; @@ -33,24 +32,23 @@ import java.util.Objects; * Activity configuration changed callback. * @hide */ -public class ActivityConfigurationChangeItem extends ActivityTransactionItem { +public class ActivityConfigurationChangeItem extends ClientTransactionItem { private Configuration mConfiguration; @Override public void preExecute(android.app.ClientTransactionHandler client, IBinder token) { - final ActivityClientRecord r = getActivityClientRecord(client, token); // Notify the client of an upcoming change in the token configuration. This ensures that // batches of config change items only process the newest configuration. - client.updatePendingActivityConfiguration(r, mConfiguration); + client.updatePendingActivityConfiguration(token, mConfiguration); } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { // TODO(lifecycler): detect if PIP or multi-window mode changed and report it here. Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged"); - client.handleActivityConfigurationChanged(r, mConfiguration, INVALID_DISPLAY); + client.handleActivityConfigurationChanged(token, mConfiguration, INVALID_DISPLAY); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -95,7 +93,7 @@ public class ActivityConfigurationChangeItem extends ActivityTransactionItem { mConfiguration = in.readTypedObject(Configuration.CREATOR); } - public static final @NonNull Creator<ActivityConfigurationChangeItem> CREATOR = + public static final @android.annotation.NonNull Creator<ActivityConfigurationChangeItem> CREATOR = new Creator<ActivityConfigurationChangeItem>() { public ActivityConfigurationChangeItem createFromParcel(Parcel in) { return new ActivityConfigurationChangeItem(in); diff --git a/core/java/android/app/servertransaction/ActivityLifecycleItem.java b/core/java/android/app/servertransaction/ActivityLifecycleItem.java index cadb6606b1be..c9193a9578e7 100644 --- a/core/java/android/app/servertransaction/ActivityLifecycleItem.java +++ b/core/java/android/app/servertransaction/ActivityLifecycleItem.java @@ -25,7 +25,7 @@ import java.lang.annotation.RetentionPolicy; * Request for lifecycle state that an activity should reach. * @hide */ -public abstract class ActivityLifecycleItem extends ActivityTransactionItem { +public abstract class ActivityLifecycleItem extends ClientTransactionItem { @IntDef(prefix = { "UNDEFINED", "PRE_", "ON_" }, value = { UNDEFINED, diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java index 87ea3f8db39c..9844de7b6e88 100644 --- a/core/java/android/app/servertransaction/ActivityRelaunchItem.java +++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java @@ -18,8 +18,7 @@ package android.app.servertransaction; import static android.app.ActivityThread.DEBUG_ORDER; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; +import android.app.ActivityThread; import android.app.ClientTransactionHandler; import android.app.ResultInfo; import android.os.IBinder; @@ -37,7 +36,7 @@ import java.util.Objects; * Activity relaunch callback. * @hide */ -public class ActivityRelaunchItem extends ActivityTransactionItem { +public class ActivityRelaunchItem extends ClientTransactionItem { private static final String TAG = "ActivityRelaunchItem"; @@ -51,7 +50,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { * A record that was properly configured for relaunch. Execution will be cancelled if not * initialized after {@link #preExecute(ClientTransactionHandler, IBinder)}. */ - private ActivityClientRecord mActivityClientRecord; + private ActivityThread.ActivityClientRecord mActivityClientRecord; @Override public void preExecute(ClientTransactionHandler client, IBinder token) { @@ -60,7 +59,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { if (mActivityClientRecord == null) { if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled"); @@ -74,8 +73,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { @Override public void postExecute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { - final ActivityClientRecord r = getActivityClientRecord(client, token); - client.reportRelaunch(r, pendingActions); + client.reportRelaunch(token, pendingActions); } // ObjectPoolItem implementation @@ -132,16 +130,16 @@ public class ActivityRelaunchItem extends ActivityTransactionItem { mPreserveWindow = in.readBoolean(); } - public static final @NonNull Creator<ActivityRelaunchItem> CREATOR = + public static final @android.annotation.NonNull Creator<ActivityRelaunchItem> CREATOR = new Creator<ActivityRelaunchItem>() { - public ActivityRelaunchItem createFromParcel(Parcel in) { - return new ActivityRelaunchItem(in); - } - - public ActivityRelaunchItem[] newArray(int size) { - return new ActivityRelaunchItem[size]; - } - }; + public ActivityRelaunchItem createFromParcel(Parcel in) { + return new ActivityRelaunchItem(in); + } + + public ActivityRelaunchItem[] newArray(int size) { + return new ActivityRelaunchItem[size]; + } + }; @Override public boolean equals(Object o) { diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java index 47096a8257e9..4e743caccad6 100644 --- a/core/java/android/app/servertransaction/ActivityResultItem.java +++ b/core/java/android/app/servertransaction/ActivityResultItem.java @@ -18,11 +18,10 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.ResultInfo; import android.compat.annotation.UnsupportedAppUsage; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.os.Trace; @@ -34,7 +33,7 @@ import java.util.Objects; * Activity result delivery callback. * @hide */ -public class ActivityResultItem extends ActivityTransactionItem { +public class ActivityResultItem extends ClientTransactionItem { @UnsupportedAppUsage private List<ResultInfo> mResultInfoList; @@ -46,10 +45,10 @@ public class ActivityResultItem extends ActivityTransactionItem { }*/ @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult"); - client.handleSendResult(r, mResultInfoList, "ACTIVITY_RESULT"); + client.handleSendResult(token, mResultInfoList, "ACTIVITY_RESULT"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -89,7 +88,7 @@ public class ActivityResultItem extends ActivityTransactionItem { mResultInfoList = in.createTypedArrayList(ResultInfo.CREATOR); } - public static final @NonNull Parcelable.Creator<ActivityResultItem> CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator<ActivityResultItem> CREATOR = new Parcelable.Creator<ActivityResultItem>() { public ActivityResultItem createFromParcel(Parcel in) { return new ActivityResultItem(in); diff --git a/core/java/android/app/servertransaction/ActivityTransactionItem.java b/core/java/android/app/servertransaction/ActivityTransactionItem.java deleted file mode 100644 index f7d7e9d20ab9..000000000000 --- a/core/java/android/app/servertransaction/ActivityTransactionItem.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app.servertransaction; - -import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; - -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; -import android.app.ClientTransactionHandler; -import android.os.IBinder; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * An activity-targeting callback message to a client that can be scheduled and executed. - * It also provides nullity-free version of - * {@link #execute(ClientTransactionHandler, IBinder, PendingTransactionActions)} for child class - * to inherit. - * - * @see ClientTransaction - * @see ClientTransactionItem - * @see com.android.server.wm.ClientLifecycleManager - * @hide - */ -public abstract class ActivityTransactionItem extends ClientTransactionItem { - @Override - public final void execute(ClientTransactionHandler client, IBinder token, - PendingTransactionActions pendingActions) { - final ActivityClientRecord r = getActivityClientRecord(client, token); - - execute(client, r, pendingActions); - } - - /** - * Like {@link #execute(ClientTransactionHandler, IBinder, PendingTransactionActions)}, - * but take non-null {@link ActivityClientRecord} as a parameter. - */ - @VisibleForTesting(visibility = PACKAGE) - public abstract void execute(@NonNull ClientTransactionHandler client, - @NonNull ActivityClientRecord r, PendingTransactionActions pendingActions); - - @NonNull ActivityClientRecord getActivityClientRecord( - @NonNull ClientTransactionHandler client, IBinder token) { - final ActivityClientRecord r = client.getActivityClient(token); - if (r == null) { - throw new IllegalArgumentException("Activity client record must not be null to execute " - + "transaction item"); - } - if (client.getActivity(token) == null) { - throw new IllegalArgumentException("Activity must not be null to execute " - + "transaction item"); - } - return r; - } -} diff --git a/core/java/android/app/servertransaction/DestroyActivityItem.java b/core/java/android/app/servertransaction/DestroyActivityItem.java index 1611369497e9..3ee761477efd 100644 --- a/core/java/android/app/servertransaction/DestroyActivityItem.java +++ b/core/java/android/app/servertransaction/DestroyActivityItem.java @@ -18,8 +18,6 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; @@ -40,10 +38,10 @@ public class DestroyActivityItem extends ActivityLifecycleItem { } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy"); - client.handleDestroyActivity(r, mFinished, mConfigChanges, + client.handleDestroyActivity(token, mFinished, mConfigChanges, false /* getNonConfigInstance */, "DestroyActivityItem"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -94,7 +92,7 @@ public class DestroyActivityItem extends ActivityLifecycleItem { mConfigChanges = in.readInt(); } - public static final @NonNull Creator<DestroyActivityItem> CREATOR = + public static final @android.annotation.NonNull Creator<DestroyActivityItem> CREATOR = new Creator<DestroyActivityItem>() { public DestroyActivityItem createFromParcel(Parcel in) { return new DestroyActivityItem(in); diff --git a/core/java/android/app/servertransaction/EnterPipRequestedItem.java b/core/java/android/app/servertransaction/EnterPipRequestedItem.java index b7e81a56afad..b2a1276fa178 100644 --- a/core/java/android/app/servertransaction/EnterPipRequestedItem.java +++ b/core/java/android/app/servertransaction/EnterPipRequestedItem.java @@ -16,20 +16,20 @@ package android.app.servertransaction; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; +import android.os.IBinder; import android.os.Parcel; /** * Request an activity to enter picture-in-picture mode. * @hide */ -public final class EnterPipRequestedItem extends ActivityTransactionItem { +public final class EnterPipRequestedItem extends ClientTransactionItem { @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { - client.handlePictureInPictureRequested(r); + client.handlePictureInPictureRequested(token); } // ObjectPoolItem implementation diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 77457af77340..2e7b6262c785 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -18,7 +18,6 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.ProfilerInfo; @@ -164,7 +163,7 @@ public class LaunchActivityItem extends ClientTransactionItem { in.readTypedObject(FixedRotationAdjustments.CREATOR)); } - public static final @NonNull Creator<LaunchActivityItem> CREATOR = + public static final @android.annotation.NonNull Creator<LaunchActivityItem> CREATOR = new Creator<LaunchActivityItem>() { public LaunchActivityItem createFromParcel(Parcel in) { return new LaunchActivityItem(in); diff --git a/core/java/android/app/servertransaction/MoveToDisplayItem.java b/core/java/android/app/servertransaction/MoveToDisplayItem.java index 32de53f189b0..9a457a3aad40 100644 --- a/core/java/android/app/servertransaction/MoveToDisplayItem.java +++ b/core/java/android/app/servertransaction/MoveToDisplayItem.java @@ -19,7 +19,6 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.content.res.Configuration; import android.os.IBinder; @@ -32,24 +31,23 @@ import java.util.Objects; * Activity move to a different display message. * @hide */ -public class MoveToDisplayItem extends ActivityTransactionItem { +public class MoveToDisplayItem extends ClientTransactionItem { private int mTargetDisplayId; private Configuration mConfiguration; @Override public void preExecute(ClientTransactionHandler client, IBinder token) { - final ActivityClientRecord r = getActivityClientRecord(client, token); // Notify the client of an upcoming change in the token configuration. This ensures that // batches of config change items only process the newest configuration. - client.updatePendingActivityConfiguration(r, mConfiguration); + client.updatePendingActivityConfiguration(token, mConfiguration); } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityMovedToDisplay"); - client.handleActivityConfigurationChanged(r, mConfiguration, mTargetDisplayId); + client.handleActivityConfigurationChanged(token, mConfiguration, mTargetDisplayId); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -98,8 +96,7 @@ public class MoveToDisplayItem extends ActivityTransactionItem { mConfiguration = in.readTypedObject(Configuration.CREATOR); } - public static final @NonNull Creator<MoveToDisplayItem> CREATOR = - new Creator<MoveToDisplayItem>() { + public static final @android.annotation.NonNull Creator<MoveToDisplayItem> CREATOR = new Creator<MoveToDisplayItem>() { public MoveToDisplayItem createFromParcel(Parcel in) { return new MoveToDisplayItem(in); } diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java index b4e2a7bfa10f..6a4996da38ca 100644 --- a/core/java/android/app/servertransaction/NewIntentItem.java +++ b/core/java/android/app/servertransaction/NewIntentItem.java @@ -19,10 +19,9 @@ package android.app.servertransaction; import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME; import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.compat.annotation.UnsupportedAppUsage; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.os.Trace; @@ -36,7 +35,7 @@ import java.util.Objects; * New intent message. * @hide */ -public class NewIntentItem extends ActivityTransactionItem { +public class NewIntentItem extends ClientTransactionItem { @UnsupportedAppUsage private List<ReferrerIntent> mIntents; @@ -48,10 +47,10 @@ public class NewIntentItem extends ActivityTransactionItem { } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent"); - client.handleNewIntent(r, mIntents); + client.handleNewIntent(token, mIntents); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } @@ -95,7 +94,7 @@ public class NewIntentItem extends ActivityTransactionItem { mIntents = in.createTypedArrayList(ReferrerIntent.CREATOR); } - public static final @NonNull Parcelable.Creator<NewIntentItem> CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator<NewIntentItem> CREATOR = new Parcelable.Creator<NewIntentItem>() { public NewIntentItem createFromParcel(Parcel in) { return new NewIntentItem(in); diff --git a/core/java/android/app/servertransaction/PauseActivityItem.java b/core/java/android/app/servertransaction/PauseActivityItem.java index cb154e9585e6..f65c843ee76f 100644 --- a/core/java/android/app/servertransaction/PauseActivityItem.java +++ b/core/java/android/app/servertransaction/PauseActivityItem.java @@ -18,9 +18,8 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; +import android.app.ActivityManager; import android.app.ActivityTaskManager; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; @@ -41,10 +40,10 @@ public class PauseActivityItem extends ActivityLifecycleItem { private boolean mDontReport; @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); - client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions, + client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions, "PAUSE_ACTIVITY_ITEM"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -131,7 +130,7 @@ public class PauseActivityItem extends ActivityLifecycleItem { mDontReport = in.readBoolean(); } - public static final @NonNull Creator<PauseActivityItem> CREATOR = + public static final @android.annotation.NonNull Creator<PauseActivityItem> CREATOR = new Creator<PauseActivityItem>() { public PauseActivityItem createFromParcel(Parcel in) { return new PauseActivityItem(in); diff --git a/core/java/android/app/servertransaction/ResumeActivityItem.java b/core/java/android/app/servertransaction/ResumeActivityItem.java index d2a156c37c90..905076b08e69 100644 --- a/core/java/android/app/servertransaction/ResumeActivityItem.java +++ b/core/java/android/app/servertransaction/ResumeActivityItem.java @@ -18,10 +18,8 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; @@ -48,10 +46,10 @@ public class ResumeActivityItem extends ActivityLifecycleItem { } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume"); - client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward, + client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward, "RESUME_ACTIVITY"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -130,7 +128,7 @@ public class ResumeActivityItem extends ActivityLifecycleItem { mIsForward = in.readBoolean(); } - public static final @NonNull Creator<ResumeActivityItem> CREATOR = + public static final @android.annotation.NonNull Creator<ResumeActivityItem> CREATOR = new Creator<ResumeActivityItem>() { public ResumeActivityItem createFromParcel(Parcel in) { return new ResumeActivityItem(in); diff --git a/core/java/android/app/servertransaction/StartActivityItem.java b/core/java/android/app/servertransaction/StartActivityItem.java index ae0bd24218fb..4fbe02b9cf76 100644 --- a/core/java/android/app/servertransaction/StartActivityItem.java +++ b/core/java/android/app/servertransaction/StartActivityItem.java @@ -18,9 +18,8 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; +import android.os.IBinder; import android.os.Parcel; import android.os.Trace; @@ -33,10 +32,10 @@ public class StartActivityItem extends ActivityLifecycleItem { private static final String TAG = "StartActivityItem"; @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "startActivityItem"); - client.handleStartActivity(r, pendingActions); + client.handleStartActivity(token, pendingActions); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -80,7 +79,7 @@ public class StartActivityItem extends ActivityLifecycleItem { // Empty } - public static final @NonNull Creator<StartActivityItem> CREATOR = + public static final @android.annotation.NonNull Creator<StartActivityItem> CREATOR = new Creator<StartActivityItem>() { public StartActivityItem createFromParcel(Parcel in) { return new StartActivityItem(in); diff --git a/core/java/android/app/servertransaction/StopActivityItem.java b/core/java/android/app/servertransaction/StopActivityItem.java index 7708104da16a..8668bd49c8f5 100644 --- a/core/java/android/app/servertransaction/StopActivityItem.java +++ b/core/java/android/app/servertransaction/StopActivityItem.java @@ -18,8 +18,6 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; @@ -36,10 +34,10 @@ public class StopActivityItem extends ActivityLifecycleItem { private int mConfigChanges; @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); - client.handleStopActivity(r, mConfigChanges, pendingActions, + client.handleStopActivity(token, mConfigChanges, pendingActions, true /* finalStateRequest */, "STOP_ACTIVITY_ITEM"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -95,7 +93,7 @@ public class StopActivityItem extends ActivityLifecycleItem { mConfigChanges = in.readInt(); } - public static final @NonNull Creator<StopActivityItem> CREATOR = + public static final @android.annotation.NonNull Creator<StopActivityItem> CREATOR = new Creator<StopActivityItem>() { public StopActivityItem createFromParcel(Parcel in) { return new StopActivityItem(in); diff --git a/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java b/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java index 345c1dd336ab..c7e4c3641631 100644 --- a/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java +++ b/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java @@ -17,9 +17,7 @@ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; -import android.annotation.NonNull; import android.app.ActivityTaskManager; -import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; @@ -30,15 +28,15 @@ import android.os.Trace; * Top resumed activity changed callback. * @hide */ -public class TopResumedActivityChangeItem extends ActivityTransactionItem { +public class TopResumedActivityChangeItem extends ClientTransactionItem { private boolean mOnTop; @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, + public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "topResumedActivityChangeItem"); - client.handleTopResumedActivityChanged(r, mOnTop, "topResumedActivityChangeItem"); + client.handleTopResumedActivityChanged(token, mOnTop, "topResumedActivityChangeItem"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } @@ -99,16 +97,16 @@ public class TopResumedActivityChangeItem extends ActivityTransactionItem { mOnTop = in.readBoolean(); } - public static final @NonNull Creator<TopResumedActivityChangeItem> CREATOR = + public static final @android.annotation.NonNull Creator<TopResumedActivityChangeItem> CREATOR = new Creator<TopResumedActivityChangeItem>() { - public TopResumedActivityChangeItem createFromParcel(Parcel in) { - return new TopResumedActivityChangeItem(in); - } - - public TopResumedActivityChangeItem[] newArray(int size) { - return new TopResumedActivityChangeItem[size]; - } - }; + public TopResumedActivityChangeItem createFromParcel(Parcel in) { + return new TopResumedActivityChangeItem(in); + } + + public TopResumedActivityChangeItem[] newArray(int size) { + return new TopResumedActivityChangeItem[size]; + } + }; @Override public boolean equals(Object o) { diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java index 3dcf2cb5f13e..17fcda587322 100644 --- a/core/java/android/app/servertransaction/TransactionExecutor.java +++ b/core/java/android/app/servertransaction/TransactionExecutor.java @@ -218,29 +218,29 @@ public class TransactionExecutor { null /* customIntent */); break; case ON_START: - mTransactionHandler.handleStartActivity(r, mPendingActions); + mTransactionHandler.handleStartActivity(r.token, mPendingActions); break; case ON_RESUME: - mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */, + mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */, r.isForward, "LIFECYCLER_RESUME_ACTIVITY"); break; case ON_PAUSE: - mTransactionHandler.handlePauseActivity(r, false /* finished */, + mTransactionHandler.handlePauseActivity(r.token, false /* finished */, false /* userLeaving */, 0 /* configChanges */, mPendingActions, "LIFECYCLER_PAUSE_ACTIVITY"); break; case ON_STOP: - mTransactionHandler.handleStopActivity(r, 0 /* configChanges */, + mTransactionHandler.handleStopActivity(r.token, 0 /* configChanges */, mPendingActions, false /* finalStateRequest */, "LIFECYCLER_STOP_ACTIVITY"); break; case ON_DESTROY: - mTransactionHandler.handleDestroyActivity(r, false /* finishing */, + mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */, 0 /* configChanges */, false /* getNonConfigInstance */, "performLifecycleSequence. cycling to:" + path.get(size - 1)); break; case ON_RESTART: - mTransactionHandler.performRestartActivity(r, false /* start */); + mTransactionHandler.performRestartActivity(r.token, false /* start */); break; default: throw new IllegalArgumentException("Unexpected lifecycle state: " + state); diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java index bc418061e1d1..b0437ac7284e 100644 --- a/core/java/android/content/res/ApkAssets.java +++ b/core/java/android/content/res/ApkAssets.java @@ -101,14 +101,11 @@ public final class ApkAssets { public @interface FormatType {} @GuardedBy("this") - private final long mNativePtr; + private long mNativePtr; // final, except cleared in finalizer. @Nullable @GuardedBy("this") - private final StringBlock mStringBlock; - - @GuardedBy("this") - private boolean mOpen = true; + private final StringBlock mStringBlock; // null or closed if mNativePtr = 0. @PropertyFlags private final int mFlags; @@ -380,12 +377,16 @@ public final class ApkAssets { /** @hide */ @Nullable public OverlayableInfo getOverlayableInfo(String overlayableName) throws IOException { - return nativeGetOverlayableInfo(mNativePtr, overlayableName); + synchronized (this) { + return nativeGetOverlayableInfo(mNativePtr, overlayableName); + } } /** @hide */ public boolean definesOverlayable() throws IOException { - return nativeDefinesOverlayable(mNativePtr); + synchronized (this) { + return nativeDefinesOverlayable(mNativePtr); + } } /** @@ -412,12 +413,12 @@ public final class ApkAssets { */ public void close() { synchronized (this) { - if (mOpen) { - mOpen = false; + if (mNativePtr != 0) { if (mStringBlock != null) { mStringBlock.close(); } nativeDestroy(mNativePtr); + mNativePtr = 0; } } } diff --git a/core/java/android/hardware/face/FaceSensorProperties.java b/core/java/android/hardware/face/FaceSensorProperties.java index e3b2fbb6c614..1015724a485d 100644 --- a/core/java/android/hardware/face/FaceSensorProperties.java +++ b/core/java/android/hardware/face/FaceSensorProperties.java @@ -25,20 +25,36 @@ import android.os.Parcelable; */ public class FaceSensorProperties implements Parcelable { + /** + * A statically configured ID representing this sensor. Sensor IDs must be unique across all + * biometrics across the device, starting at 0, and in increments of 1. + */ public final int sensorId; + /** + * True if the sensor is able to perform generic face detection, without running the + * matching algorithm, and without affecting the lockout counter. + */ public final boolean supportsFaceDetection; + /** + * True if the sensor is able to provide self illumination in dark scenarios, without support + * from above the HAL. + */ + public final boolean supportsSelfIllumination; /** * Initializes SensorProperties with specified values */ - public FaceSensorProperties(int sensorId, boolean supportsFaceDetection) { + public FaceSensorProperties(int sensorId, boolean supportsFaceDetection, + boolean supportsSelfIllumination) { this.sensorId = sensorId; this.supportsFaceDetection = supportsFaceDetection; + this.supportsSelfIllumination = supportsSelfIllumination; } protected FaceSensorProperties(Parcel in) { sensorId = in.readInt(); supportsFaceDetection = in.readBoolean(); + supportsSelfIllumination = in.readBoolean(); } public static final Creator<FaceSensorProperties> CREATOR = @@ -63,5 +79,6 @@ public class FaceSensorProperties implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(sensorId); dest.writeBoolean(supportsFaceDetection); + dest.writeBoolean(supportsSelfIllumination); } } diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index a6b869d19867..1eb3fc11df7b 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -64,10 +64,11 @@ public class GraphicsEnvironment { private static final String SYSTEM_DRIVER_NAME = "system"; private static final String SYSTEM_DRIVER_VERSION_NAME = ""; private static final long SYSTEM_DRIVER_VERSION_CODE = 0; - private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; + private static final String PROPERTY_GFX_DRIVER_PRODUCTION = "ro.gfx.driver.0"; private static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1"; private static final String PROPERTY_GFX_DRIVER_BUILD_TIME = "ro.gfx.driver_build_time"; - private static final String METADATA_DRIVER_BUILD_TIME = "com.android.gamedriver.build_time"; + private static final String METADATA_DRIVER_BUILD_TIME = + "com.android.graphics.updatabledriver.build_time"; private static final String METADATA_DEVELOPER_DRIVER_ENABLE = "com.android.graphics.developerdriver.enable"; private static final String METADATA_INJECT_LAYERS_ENABLE = @@ -78,20 +79,20 @@ public class GraphicsEnvironment { private static final String ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE = "android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE"; private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message"; - private static final String GAME_DRIVER_ALLOWLIST_ALL = "*"; - private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; + private static final String UPDATABLE_DRIVER_ALLOWLIST_ALL = "*"; + private static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; private static final int VULKAN_1_0 = 0x00400000; private static final int VULKAN_1_1 = 0x00401000; - // GAME_DRIVER_ALL_APPS + // UPDATABLE_DRIVER_ALL_APPS // 0: Default (Invalid values fallback to default as well) - // 1: All apps use Game Driver - // 2: All apps use Prerelease Driver + // 1: All apps use updatable production driver + // 2: All apps use updatable prerelease driver // 3: All apps use system graphics driver - private static final int GAME_DRIVER_GLOBAL_OPT_IN_DEFAULT = 0; - private static final int GAME_DRIVER_GLOBAL_OPT_IN_GAME_DRIVER = 1; - private static final int GAME_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; - private static final int GAME_DRIVER_GLOBAL_OPT_IN_OFF = 3; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_DEFAULT = 0; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRODUCTION_DRIVER = 1; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3; private ClassLoader mClassLoader; private String mLibrarySearchPaths; @@ -722,14 +723,17 @@ public class GraphicsEnvironment { * Return the driver package name to use. Return null for system driver. */ private static String chooseDriverInternal(Bundle coreSettings, ApplicationInfo ai) { - final String gameDriver = SystemProperties.get(PROPERTY_GFX_DRIVER); - final boolean hasGameDriver = gameDriver != null && !gameDriver.isEmpty(); + final String productionDriver = SystemProperties.get(PROPERTY_GFX_DRIVER_PRODUCTION); + final boolean hasProductionDriver = productionDriver != null && !productionDriver.isEmpty(); final String prereleaseDriver = SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE); final boolean hasPrereleaseDriver = prereleaseDriver != null && !prereleaseDriver.isEmpty(); - if (!hasGameDriver && !hasPrereleaseDriver) { - if (DEBUG) Log.v(TAG, "Neither Game Driver nor prerelease driver is supported."); + if (!hasProductionDriver && !hasPrereleaseDriver) { + if (DEBUG) { + Log.v(TAG, + "Neither updatable production driver nor prerelease driver is supported."); + } return null; } @@ -745,56 +749,59 @@ public class GraphicsEnvironment { (ai.metaData != null && ai.metaData.getBoolean(METADATA_DEVELOPER_DRIVER_ENABLE)) || isDebuggable(); - // Priority for Game Driver settings global on confliction (Higher priority comes first): - // 1. GAME_DRIVER_ALL_APPS - // 2. GAME_DRIVER_OPT_OUT_APPS - // 3. GAME_DRIVER_PRERELEASE_OPT_IN_APPS - // 4. GAME_DRIVER_OPT_IN_APPS - // 5. GAME_DRIVER_DENYLIST - // 6. GAME_DRIVER_ALLOWLIST - switch (coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0)) { - case GAME_DRIVER_GLOBAL_OPT_IN_OFF: - if (DEBUG) Log.v(TAG, "Game Driver is turned off on this device."); + // Priority of updatable driver settings on confliction (Higher priority comes first): + // 1. UPDATABLE_DRIVER_ALL_APPS + // 2. UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS + // 3. UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS + // 4. UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS + // 5. UPDATABLE_DRIVER_PRODUCTION_DENYLIST + // 6. UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST + switch (coreSettings.getInt(Settings.Global.UPDATABLE_DRIVER_ALL_APPS, 0)) { + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF: + if (DEBUG) Log.v(TAG, "updatable driver is turned off on this device."); return null; - case GAME_DRIVER_GLOBAL_OPT_IN_GAME_DRIVER: - if (DEBUG) Log.v(TAG, "All apps opt in to use Game Driver."); - return hasGameDriver ? gameDriver : null; - case GAME_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER: - if (DEBUG) Log.v(TAG, "All apps opt in to use prerelease driver."); + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRODUCTION_DRIVER: + if (DEBUG) Log.v(TAG, "All apps opt in to use updatable production driver."); + return hasProductionDriver ? productionDriver : null; + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER: + if (DEBUG) Log.v(TAG, "All apps opt in to use updatable prerelease driver."); return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null; - case GAME_DRIVER_GLOBAL_OPT_IN_DEFAULT: + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_DEFAULT: default: break; } final String appPackageName = ai.packageName; - if (getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_OPT_OUT_APPS) + if (getGlobalSettingsString(null, coreSettings, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App opts out for Game Driver."); + if (DEBUG) Log.v(TAG, "App opts out for updatable production driver."); return null; } if (getGlobalSettingsString( - null, coreSettings, Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS) + null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App opts in for prerelease Game Driver."); + if (DEBUG) Log.v(TAG, "App opts in for updatable prerelease driver."); return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null; } - // Early return here since the rest logic is only for Game Driver. - if (!hasGameDriver) { - if (DEBUG) Log.v(TAG, "Game Driver is not supported on the device."); + // Early return here since the rest logic is only for updatable production Driver. + if (!hasProductionDriver) { + if (DEBUG) Log.v(TAG, "Updatable production driver is not supported on the device."); return null; } final boolean isOptIn = - getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) + getGlobalSettingsString(null, coreSettings, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS) .contains(appPackageName); final List<String> allowlist = - getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_ALLOWLIST); - if (!isOptIn && allowlist.indexOf(GAME_DRIVER_ALLOWLIST_ALL) != 0 + getGlobalSettingsString(null, coreSettings, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST); + if (!isOptIn && allowlist.indexOf(UPDATABLE_DRIVER_ALLOWLIST_ALL) != 0 && !allowlist.contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App is not on the allowlist for Game Driver."); + if (DEBUG) Log.v(TAG, "App is not on the allowlist for updatable production driver."); return null; } @@ -802,13 +809,13 @@ public class GraphicsEnvironment { // terminate early if it's on the denylist and fallback to system driver. if (!isOptIn && getGlobalSettingsString( - null, coreSettings, Settings.Global.GAME_DRIVER_DENYLIST) + null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App is on the denylist for Game Driver."); + if (DEBUG) Log.v(TAG, "App is on the denylist for updatable production driver."); return null; } - return gameDriver; + return productionDriver; } /** @@ -873,7 +880,7 @@ public class GraphicsEnvironment { final String driverBuildTime = driverAppInfo.metaData.getString(METADATA_DRIVER_BUILD_TIME); if (driverBuildTime == null || driverBuildTime.isEmpty()) { - throw new IllegalArgumentException("com.android.gamedriver.build_time is not set"); + Log.v(TAG, "com.android.graphics.updatabledriver.build_time is not set"); } // driver_build_time in the meta-data is in "L<Unix epoch timestamp>" format. e.g. L123456. // Long.parseLong will throw if the meta-data "driver_build_time" is not set properly. @@ -901,7 +908,7 @@ public class GraphicsEnvironment { final Context driverContext = context.createPackageContext(driverPackageName, Context.CONTEXT_RESTRICTED); final BufferedReader reader = new BufferedReader(new InputStreamReader( - driverContext.getAssets().open(GAME_DRIVER_SPHAL_LIBRARIES_FILENAME))); + driverContext.getAssets().open(UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME))); final ArrayList<String> assetStrings = new ArrayList<>(); for (String assetString; (assetString = reader.readLine()) != null;) { assetStrings.add(assetString); @@ -913,7 +920,7 @@ public class GraphicsEnvironment { } } catch (IOException e) { if (DEBUG) { - Log.w(TAG, "Failed to load '" + GAME_DRIVER_SPHAL_LIBRARIES_FILENAME + "'"); + Log.w(TAG, "Failed to load '" + UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME + "'"); } } return ""; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 857e5dbf4a21..6903a995bf7b 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9037,6 +9037,13 @@ public final class Settings { "accessibility_magnification_capability"; /** + * Whether the Adaptive connectivity option is enabled. + * + * @hide + */ + public static final String ADAPTIVE_CONNECTIVITY_ENABLED = "adaptive_connectivity_enabled"; + + /** * Keys we no longer back up under the current schema, but want to continue to * process when restoring historical backup datasets. * @@ -12362,63 +12369,71 @@ public final class Settings { "show_angle_in_use_dialog_box"; /** - * Game Driver global preference for all Apps. + * Updatable driver global preference for all Apps. * 0 = Default - * 1 = All Apps use Game Driver - * 2 = All Apps use system graphics driver + * 1 = All Apps use updatable production driver + * 2 = All apps use updatable prerelease driver + * 3 = All Apps use system graphics driver * @hide */ - public static final String GAME_DRIVER_ALL_APPS = "game_driver_all_apps"; + public static final String UPDATABLE_DRIVER_ALL_APPS = "updatable_driver_all_apps"; /** - * List of Apps selected to use Game Driver. + * List of Apps selected to use updatable production driver. * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ - public static final String GAME_DRIVER_OPT_IN_APPS = "game_driver_opt_in_apps"; + public static final String UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS = + "updatable_driver_production_opt_in_apps"; /** - * List of Apps selected to use prerelease Game Driver. + * List of Apps selected to use updatable prerelease driver. * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ - public static final String GAME_DRIVER_PRERELEASE_OPT_IN_APPS = - "game_driver_prerelease_opt_in_apps"; + public static final String UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS = + "updatable_driver_prerelease_opt_in_apps"; /** - * List of Apps selected not to use Game Driver. + * List of Apps selected not to use updatable production driver. * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ - public static final String GAME_DRIVER_OPT_OUT_APPS = "game_driver_opt_out_apps"; + public static final String UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS = + "updatable_driver_production_opt_out_apps"; /** - * Apps on the denylist that are forbidden to use Game Driver. + * Apps on the denylist that are forbidden to use updatable production driver. * @hide */ - public static final String GAME_DRIVER_DENYLIST = "game_driver_denylist"; + public static final String UPDATABLE_DRIVER_PRODUCTION_DENYLIST = + "updatable_driver_production_denylist"; /** - * List of denylists, each denylist is a denylist for a specific version of Game Driver. + * List of denylists, each denylist is a denylist for a specific version of + * updatable production driver. * @hide */ - public static final String GAME_DRIVER_DENYLISTS = "game_driver_denylists"; + public static final String UPDATABLE_DRIVER_PRODUCTION_DENYLISTS = + "updatable_driver_production_denylists"; /** - * Apps on the allowlist that are allowed to use Game Driver. + * Apps on the allowlist that are allowed to use updatable production driver. * The string is a list of application package names, seperated by comma. * i.e. <apk1>,<apk2>,...,<apkN> * @hide */ - public static final String GAME_DRIVER_ALLOWLIST = "game_driver_allowlist"; + public static final String UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST = + "updatable_driver_production_allowlist"; /** - * List of libraries in sphal accessible by Game Driver + * List of libraries in sphal accessible by updatable driver * The string is a list of library names, separated by colon. * i.e. <lib1>:<lib2>:...:<libN> * @hide */ - public static final String GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries"; + public static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES = + "updatable_driver_sphal_libraries"; /** * Ordered GPU debug layer list for Vulkan diff --git a/core/java/android/service/autofill/InlinePresentation.java b/core/java/android/service/autofill/InlinePresentation.java index 914169485979..6eb2a15eec44 100644 --- a/core/java/android/service/autofill/InlinePresentation.java +++ b/core/java/android/service/autofill/InlinePresentation.java @@ -40,6 +40,11 @@ public final class InlinePresentation implements Parcelable { /** * Represents the UI content and the action for the inline suggestion. + * + * <p>The Slice should be constructed using the Content builder provided in the androidx + * autofill library e.g. {@code androidx.autofill.inline.v1.InlineSuggestionUi.Content.Builder} + * and then converted to a Slice with + * {@code androidx.autofill.inline.UiVersions.Content#getSlice()}.</p> */ private final @NonNull Slice mSlice; @@ -90,6 +95,11 @@ public final class InlinePresentation implements Parcelable { * * @param slice * Represents the UI content and the action for the inline suggestion. + * + * <p>The Slice should be constructed using the Content builder provided in the androidx + * autofill library e.g. {@code androidx.autofill.inline.v1.InlineSuggestionUi.Content.Builder} + * and then converted to a Slice with + * {@code androidx.autofill.inline.UiVersions.Content#getSlice()}.</p> * @param inlinePresentationSpec * Specifies the UI specification for the inline suggestion. * @param pinned @@ -118,6 +128,11 @@ public final class InlinePresentation implements Parcelable { /** * Represents the UI content and the action for the inline suggestion. + * + * <p>The Slice should be constructed using the Content builder provided in the androidx + * autofill library e.g. {@code androidx.autofill.inline.v1.InlineSuggestionUi.Content.Builder} + * and then converted to a Slice with + * {@code androidx.autofill.inline.UiVersions.Content#getSlice()}.</p> */ @DataClass.Generated.Member public @NonNull Slice getSlice() { @@ -244,7 +259,7 @@ public final class InlinePresentation implements Parcelable { }; @DataClass.Generated( - time = 1593131904745L, + time = 1596484869201L, codegenVersion = "1.0.15", sourceFile = "frameworks/base/core/java/android/service/autofill/InlinePresentation.java", inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final boolean mPinned\npublic @android.annotation.NonNull @android.annotation.Size(min=0L) java.lang.String[] getAutofillHints()\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)") diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 7923ff0991d8..32ee290a0f47 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -534,7 +534,8 @@ public interface WindowManager extends ViewManager { ScreenshotSource.SCREENSHOT_KEY_OTHER, ScreenshotSource.SCREENSHOT_OVERVIEW, ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS, - ScreenshotSource.SCREENSHOT_OTHER}) + ScreenshotSource.SCREENSHOT_OTHER, + ScreenshotSource.SCREENSHOT_VENDOR_GESTURE}) @interface ScreenshotSource { int SCREENSHOT_GLOBAL_ACTIONS = 0; int SCREENSHOT_KEY_CHORD = 1; @@ -542,6 +543,7 @@ public interface WindowManager extends ViewManager { int SCREENSHOT_OVERVIEW = 3; int SCREENSHOT_ACCESSIBILITY_ACTIONS = 4; int SCREENSHOT_OTHER = 5; + int SCREENSHOT_VENDOR_GESTURE = 6; } /** diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 28644858377a..7cc347d25458 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -294,7 +294,7 @@ public final class InputMethodInfo implements Parcelable { */ public InputMethodInfo(String packageName, String className, CharSequence label, String settingsActivity) { - this(buildDummyResolveInfo(packageName, className, label), false /* isAuxIme */, + this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */, settingsActivity, null /* subtypes */, 0 /* isDefaultResId */, false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */, false /* isVrOnly */); @@ -344,7 +344,7 @@ public final class InputMethodInfo implements Parcelable { mIsVrOnly = isVrOnly; } - private static ResolveInfo buildDummyResolveInfo(String packageName, String className, + private static ResolveInfo buildFakeResolveInfo(String packageName, String className, CharSequence label) { ResolveInfo ri = new ResolveInfo(); ServiceInfo si = new ServiceInfo(); diff --git a/core/java/android/widget/inline/InlinePresentationSpec.java b/core/java/android/widget/inline/InlinePresentationSpec.java index 5f924c6ae194..e7727fd9ff1d 100644 --- a/core/java/android/widget/inline/InlinePresentationSpec.java +++ b/core/java/android/widget/inline/InlinePresentationSpec.java @@ -42,8 +42,13 @@ public final class InlinePresentationSpec implements Parcelable { private final Size mMaxSize; /** - * The extras encoding the UI style information. Defaults to {@code Bundle.Empty} in which case - * the default system UI style will be used. + * The extras encoding the UI style information. + * + * <p>The style bundles can be created using the relevant Style classes and their builders in + * the androidx autofill library e.g. {@code androidx.autofill.inline.UiVersions.StylesBuilder}. + * </p> + * + * <p>The style must be set for the suggestion to render properly.</p> * * <p>Note: There should be no remote objects in the bundle, all included remote objects will * be removed from the bundle before transmission.</p> @@ -123,8 +128,13 @@ public final class InlinePresentationSpec implements Parcelable { } /** - * The extras encoding the UI style information. Defaults to {@code Bundle.Empty} in which case - * the default system UI style will be used. + * The extras encoding the UI style information. + * + * <p>The style bundles can be created using the relevant Style classes and their builders in + * the androidx autofill library e.g. {@code androidx.autofill.inline.UiVersions.StylesBuilder}. + * </p> + * + * <p>The style must be set for the suggestion to render properly.</p> * * <p>Note: There should be no remote objects in the bundle, all included remote objects will * be removed from the bundle before transmission.</p> @@ -264,8 +274,13 @@ public final class InlinePresentationSpec implements Parcelable { } /** - * The extras encoding the UI style information. Defaults to {@code Bundle.Empty} in which case - * the default system UI style will be used. + * The extras encoding the UI style information. + * + * <p>The style bundles can be created using the relevant Style classes and their builders in + * the androidx autofill library e.g. {@code androidx.autofill.inline.UiVersions.StylesBuilder}. + * </p> + * + * <p>The style must be set for the suggestion to render properly.</p> * * <p>Note: There should be no remote objects in the bundle, all included remote objects will * be removed from the bundle before transmission.</p> @@ -302,7 +317,7 @@ public final class InlinePresentationSpec implements Parcelable { } @DataClass.Generated( - time = 1588109681295L, + time = 1596485189661L, codegenVersion = "1.0.15", sourceFile = "frameworks/base/core/java/android/widget/inline/InlinePresentationSpec.java", inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.NonNull android.os.Bundle mStyle\nprivate static @android.annotation.NonNull android.os.Bundle defaultStyle()\nprivate boolean styleEquals(android.os.Bundle)\npublic void filterContentTypes()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []") diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 0d65bd1cf9bb..6eb89040998a 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2345,10 +2345,10 @@ enum PageId { // OS: Q ZEN_CUSTOM_SETTINGS_DIALOG = 1612; - // OPEN: Settings > Developer Options > Game Driver Preferences + // OPEN: Settings > Developer Options > Graphics Driver Preferences // CATEGORY: SETTINGS // OS: Q - SETTINGS_GAME_DRIVER_DASHBOARD = 1613; + SETTINGS_GRAPHICS_DRIVER_DASHBOARD = 1613; // OPEN: Settings > Accessibility > Vibration > Ring vibration // CATEGORY: SETTINGS diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index e4a142b3335b..d5619ca96fbd 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -433,35 +433,36 @@ message GlobalSettingsProto { // Ordered GPU debug layer list for GLES // i.e. <layer1>:<layer2>:...:<layerN> optional SettingProto debug_layers_gles = 7; - // Game Driver - global preference for all Apps + // Updatable Driver - global preference for all Apps // 0 = Default - // 1 = All Apps use Game Driver - // 2 = All Apps use system graphics driver - optional SettingProto game_driver_all_apps = 8; - // Game Driver - List of Apps selected to use Game Driver + // 1 = All Apps use updatable production driver + // 2 = All apps use updatable prerelease driver + // 3 = All Apps use system graphics driver + optional SettingProto updatable_driver_all_apps = 8; + // Updatable Driver - List of Apps selected to use updatable production driver // i.e. <pkg1>,<pkg2>,...,<pkgN> - optional SettingProto game_driver_opt_in_apps = 9; - // Game Driver - List of Apps selected not to use Game Driver + optional SettingProto updatable_driver_production_opt_in_apps = 9; + // Updatable Driver - List of Apps selected not to use updatable production driver // i.e. <pkg1>,<pkg2>,...,<pkgN> - optional SettingProto game_driver_opt_out_apps = 10; - // Game Driver - List of Apps that are forbidden to use Game Driver - optional SettingProto game_driver_denylist = 11; - // Game Driver - List of Apps that are allowed to use Game Driver - optional SettingProto game_driver_allowlist = 12; + optional SettingProto updatable_driver_production_opt_out_apps = 10; + // Updatable Driver - List of Apps that are forbidden to use updatable production driver + optional SettingProto updatable_driver_production_denylist = 11; + // Updatable Driver - List of Apps that are allowed to use updatable production driver + optional SettingProto updatable_driver_production_allowlist = 12; // ANGLE - List of Apps that can check ANGLE rules optional SettingProto angle_allowlist = 13; - // Game Driver - List of denylists, each denylist is a denylist for - // a specific Game Driver version - optional SettingProto game_driver_denylists = 14; + // Updatable Driver - List of denylists, each denylist is a denylist for + // a specific updatable production driver version + optional SettingProto updatable_driver_production_denylists = 14; // ANGLE - Show a dialog box when ANGLE is selected for the currently running PKG optional SettingProto show_angle_in_use_dialog = 15; - // Game Driver - List of libraries in sphal accessible by Game Driver - optional SettingProto game_driver_sphal_libraries = 16; + // Updatable Driver - List of libraries in sphal accessible by updatable driver + optional SettingProto updatable_driver_sphal_libraries = 16; // ANGLE - External package containing ANGLE libraries optional SettingProto angle_debug_package = 17; - // Game Driver - List of Apps selected to use prerelease Game Driver + // Updatable Driver - List of Apps selected to use updatable prerelease driver // i.e. <pkg1>,<pkg2>,...,<pkgN> - optional SettingProto game_driver_prerelease_opt_in_apps = 18; + optional SettingProto updatable_driver_prerelease_opt_in_apps = 18; } optional Gpu gpu = 59; diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 541e018d079b..3d12d072eb80 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -181,6 +181,7 @@ message SecureSettingsProto { optional SettingProto cmas_additional_broadcast_pkg = 14 [ (android.privacy).dest = DEST_AUTOMATIC ]; repeated SettingProto completed_categories = 15; optional SettingProto connectivity_release_pending_intent_delay_ms = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto adaptive_connectivity_enabled = 84 [ (android.privacy).dest = DEST_AUTOMATIC ]; message Controls { option (android.msg_privacy).dest = DEST_EXPLICIT; @@ -614,5 +615,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 84; + // Next tag = 85; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 613111d512be..5f2e4f905b1c 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4212,15 +4212,20 @@ </integer-array> <!-- Messages that should not be shown to the user during face authentication, on - BiometricPrompt. This should be used to hide messages that may be too chatty or messages that - the user can't do much about. Entries are defined in - android.hardware.biometrics.face@1.0 types.hal --> + BiometricPrompt. This should be used to hide messages that may be too chatty or messages + that the user can't do much about. Entries are defined in + android.hardware.biometrics.face@1.0 types.hal --> <integer-array name="config_face_acquire_biometricprompt_ignorelist" translatable="false" > </integer-array> <!-- Same as the above, but are defined by vendorCodes --> <integer-array name="config_face_acquire_vendor_biometricprompt_ignorelist" translatable="false" > </integer-array> + <!-- True if the sensor is able to provide self illumination in dark secnarios, without support + from above the HAL. This configuration is only applicable to IBiometricsFace@1.0 and its + minor revisions. --> + <bool name="config_faceAuthSupportsSelfIllumination">true</bool> + <!-- If face auth sends the user directly to home/last open app, or stays on keyguard --> <bool name="config_faceAuthDismissesKeyguard">true</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 781e7cff4470..35ce780d3408 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2514,6 +2514,7 @@ <java-symbol type="array" name="config_face_acquire_vendor_keyguard_ignorelist" /> <java-symbol type="array" name="config_face_acquire_biometricprompt_ignorelist" /> <java-symbol type="array" name="config_face_acquire_vendor_biometricprompt_ignorelist" /> + <java-symbol type="bool" name="config_faceAuthSupportsSelfIllumination" /> <java-symbol type="bool" name="config_faceAuthDismissesKeyguard" /> <!-- Face config --> diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 896a53486311..000e870369db 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -25,14 +25,14 @@ import static android.view.Display.INVALID_DISPLAY; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.testng.Assert.assertFalse; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityThread; -import android.app.ActivityThread.ActivityClientRecord; import android.app.IApplicationThread; import android.app.PictureInPictureParams; import android.app.ResourcesManager; @@ -114,12 +114,11 @@ public class ActivityThreadTest { final ActivityThread activityThread = activity.getActivityThread(); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { activityThread.executeTransaction(newResumeTransaction(activity)); - final ActivityClientRecord r = getActivityClientRecord(activity); - assertFalse(activityThread.performResumeActivity(r, true /* finalStateRequest */, - "test")); + assertNull(activityThread.performResumeActivity(activity.getActivityToken(), + true /* finalStateRequest */, "test")); - assertFalse(activityThread.performResumeActivity(r, false /* finalStateRequest */, - "test")); + assertNull(activityThread.performResumeActivity(activity.getActivityToken(), + false /* finalStateRequest */, "test")); }); } @@ -245,18 +244,20 @@ public class ActivityThreadTest { newerConfig.orientation = orientation == ORIENTATION_LANDSCAPE ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; newerConfig.seq = seq + 2; - final ActivityClientRecord r = getActivityClientRecord(activity); - activityThread.updatePendingActivityConfiguration(r, newerConfig); + activityThread.updatePendingActivityConfiguration(activity.getActivityToken(), + newerConfig); final Configuration olderConfig = new Configuration(); olderConfig.orientation = orientation; olderConfig.seq = seq + 1; - activityThread.handleActivityConfigurationChanged(r, olderConfig, INVALID_DISPLAY); + activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), + olderConfig, INVALID_DISPLAY); assertEquals(numOfConfig, activity.mNumOfConfigChanges); assertEquals(olderConfig.orientation, activity.mConfig.orientation); - activityThread.handleActivityConfigurationChanged(r, newerConfig, INVALID_DISPLAY); + activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), + newerConfig, INVALID_DISPLAY); assertEquals(numOfConfig + 1, activity.mNumOfConfigChanges); assertEquals(newerConfig.orientation, activity.mConfig.orientation); }); @@ -273,7 +274,7 @@ public class ActivityThreadTest { config.seq = BASE_SEQ; config.orientation = ORIENTATION_PORTRAIT; - activityThread.handleActivityConfigurationChanged(getActivityClientRecord(activity), + activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config, INVALID_DISPLAY); }); @@ -334,8 +335,8 @@ public class ActivityThreadTest { config.seq = BASE_SEQ; config.orientation = ORIENTATION_PORTRAIT; - final ActivityClientRecord r = getActivityClientRecord(activity); - activityThread.handleActivityConfigurationChanged(r, config, INVALID_DISPLAY); + activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), + config, INVALID_DISPLAY); }); final int numOfConfig = activity.mNumOfConfigChanges; @@ -512,10 +513,9 @@ public class ActivityThreadTest { startIntent.putExtra(TestActivity.PIP_REQUESTED_OVERRIDE_ENTER, true); final TestActivity activity = mActivityTestRule.launchActivity(startIntent); final ActivityThread activityThread = activity.getActivityThread(); - final ActivityClientRecord r = getActivityClientRecord(activity); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - activityThread.handlePictureInPictureRequested(r); + activityThread.handlePictureInPictureRequested(activity.getActivityToken()); }); assertTrue(activity.pipRequested()); @@ -528,10 +528,9 @@ public class ActivityThreadTest { startIntent.putExtra(TestActivity.PIP_REQUESTED_OVERRIDE_SKIP, true); final TestActivity activity = mActivityTestRule.launchActivity(startIntent); final ActivityThread activityThread = activity.getActivityThread(); - final ActivityClientRecord r = getActivityClientRecord(activity); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - activityThread.handlePictureInPictureRequested(r); + activityThread.handlePictureInPictureRequested(activity.getActivityToken()); }); assertTrue(activity.pipRequested()); @@ -542,10 +541,9 @@ public class ActivityThreadTest { public void testHandlePictureInPictureRequested_notOverridden() { final TestActivity activity = mActivityTestRule.launchActivity(new Intent()); final ActivityThread activityThread = activity.getActivityThread(); - final ActivityClientRecord r = getActivityClientRecord(activity); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - activityThread.handlePictureInPictureRequested(r); + activityThread.handlePictureInPictureRequested(activity.getActivityToken()); }); assertTrue(activity.pipRequested()); @@ -554,9 +552,8 @@ public class ActivityThreadTest { } /** - * Calls {@link ActivityThread#handleActivityConfigurationChanged(ActivityClientRecord, - * Configuration, int)} to try to push activity configuration to the activity for the given - * sequence number. + * Calls {@link ActivityThread#handleActivityConfigurationChanged(IBinder, Configuration, int)} + * to try to push activity configuration to the activity for the given sequence number. * <p> * It uses orientation to push the configuration and it tries a different orientation if the * first attempt doesn't make through, to rule out the possibility that the previous @@ -569,13 +566,13 @@ public class ActivityThreadTest { */ private int applyConfigurationChange(TestActivity activity, int seq) { final ActivityThread activityThread = activity.getActivityThread(); - final ActivityClientRecord r = getActivityClientRecord(activity); final int numOfConfig = activity.mNumOfConfigChanges; Configuration config = new Configuration(); config.orientation = ORIENTATION_PORTRAIT; config.seq = seq; - activityThread.handleActivityConfigurationChanged(r, config, INVALID_DISPLAY); + activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config, + INVALID_DISPLAY); if (activity.mNumOfConfigChanges > numOfConfig) { return config.seq; @@ -584,17 +581,12 @@ public class ActivityThreadTest { config = new Configuration(); config.orientation = ORIENTATION_LANDSCAPE; config.seq = seq + 1; - activityThread.handleActivityConfigurationChanged(r, config, INVALID_DISPLAY); + activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config, + INVALID_DISPLAY); return config.seq; } - private static ActivityClientRecord getActivityClientRecord(Activity activity) { - final ActivityThread thread = activity.getActivityThread(); - final IBinder token = activity.getActivityToken(); - return thread.getActivityClient(token); - } - private static ClientTransaction newRelaunchResumeTransaction(Activity activity) { final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null, null, 0, new MergedConfiguration(), false /* preserveWindow */); diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java index 6a0105cf7ff0..3c32c71cf961 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java @@ -32,12 +32,11 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.Activity; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.servertransaction.ActivityLifecycleItem.LifecycleState; @@ -226,7 +225,6 @@ public class TransactionExecutorTests { when(callback2.getPostExecutionState()).thenReturn(UNDEFINED); ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class); IBinder token = mock(IBinder.class); - when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class)); ClientTransaction transaction = ClientTransaction.obtain(null /* client */, token /* activityToken */); @@ -238,9 +236,9 @@ public class TransactionExecutorTests { mExecutor.execute(transaction); InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2, stateRequest); - inOrder.verify(callback1).execute(eq(mTransactionHandler), eq(token), any()); - inOrder.verify(callback2).execute(eq(mTransactionHandler), eq(token), any()); - inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any()); + inOrder.verify(callback1, times(1)).execute(eq(mTransactionHandler), eq(token), any()); + inOrder.verify(callback2, times(1)).execute(eq(mTransactionHandler), eq(token), any()); + inOrder.verify(stateRequest, times(1)).execute(eq(mTransactionHandler), eq(token), any()); } @Test @@ -275,7 +273,7 @@ public class TransactionExecutorTests { // The launch transaction should not be executed because its token is in the // to-be-destroyed container. - verify(launchItem, never()).execute(any(), any(), any()); + verify(launchItem, times(0)).execute(any(), any(), any()); // After the destroy transaction has been executed, the token should be removed. mExecutor.execute(destroyTransaction); @@ -284,8 +282,6 @@ public class TransactionExecutorTests { @Test public void testActivityResultRequiredStateResolution() { - when(mTransactionHandler.getActivity(any())).thenReturn(mock(Activity.class)); - PostExecItem postExecItem = new PostExecItem(ON_RESUME); IBinder token = mock(IBinder.class); @@ -296,12 +292,12 @@ public class TransactionExecutorTests { // Verify resolution that should get to onPause mClientRecord.setState(ON_RESUME); mExecutor.executeCallbacks(transaction); - verify(mExecutor).cycleToPath(eq(mClientRecord), eq(ON_PAUSE), eq(transaction)); + verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_PAUSE), eq(transaction)); // Verify resolution that should get to onStart mClientRecord.setState(ON_STOP); mExecutor.executeCallbacks(transaction); - verify(mExecutor).cycleToPath(eq(mClientRecord), eq(ON_START), eq(transaction)); + verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_START), eq(transaction)); } @Test @@ -437,38 +433,6 @@ public class TransactionExecutorTests { mExecutorHelper.getClosestPreExecutionState(mClientRecord, ON_RESUME)); } - @Test(expected = IllegalArgumentException.class) - public void testActivityItemNullRecordThrowsException() { - final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class); - when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED); - final IBinder token = mock(IBinder.class); - final ClientTransaction transaction = ClientTransaction.obtain(null /* client */, - token /* activityToken */); - transaction.addCallback(activityItem); - when(mTransactionHandler.getActivityClient(token)).thenReturn(null); - - mExecutor.executeCallbacks(transaction); - } - - @Test - public void testActivityItemExecute() { - final IBinder token = mock(IBinder.class); - final ClientTransaction transaction = ClientTransaction.obtain(null /* client */, - token /* activityToken */); - final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class); - when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED); - transaction.addCallback(activityItem); - final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class); - transaction.setLifecycleStateRequest(stateRequest); - when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class)); - - mExecutor.execute(transaction); - - final InOrder inOrder = inOrder(activityItem, stateRequest); - inOrder.verify(activityItem).execute(eq(mTransactionHandler), eq(mClientRecord), any()); - inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any()); - } - private static int[] shuffledArray(int[] inputArray) { final List<Integer> list = Arrays.stream(inputArray).boxed().collect(Collectors.toList()); Collections.shuffle(list); @@ -525,13 +489,13 @@ public class TransactionExecutorTests { public static final Parcelable.Creator<StubItem> CREATOR = new Parcelable.Creator<StubItem>() { - public StubItem createFromParcel(Parcel in) { - return new StubItem(in); - } - - public StubItem[] newArray(int size) { - return new StubItem[size]; - } - }; + public StubItem createFromParcel(Parcel in) { + return new StubItem(in); + } + + public StubItem[] newArray(int size) { + return new StubItem[size]; + } + }; } } diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java index 01515bd9c6b5..a80f5a03ee4e 100644 --- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java @@ -52,7 +52,9 @@ import android.os.SystemClock; import android.provider.Settings; import android.support.test.uiautomator.UiDevice; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.DebugUtils; +import android.util.KeyValueListParser; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -104,8 +106,6 @@ public class BstatsCpuTimesValidationTest { private static final int WORK_DURATION_MS = 2000; - private static final String DESIRED_PROC_STATE_CPU_TIMES_DELAY = "0"; - private static boolean sBatteryStatsConstsUpdated; private static String sOriginalBatteryStatsConsts; @@ -124,10 +124,12 @@ public class BstatsCpuTimesValidationTest { sContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0); + + final ArrayMap<String, String> desiredConstants = new ArrayMap<>(); + desiredConstants.put(KEY_TRACK_CPU_TIMES_BY_PROC_STATE, Boolean.toString(true)); + desiredConstants.put(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS, Integer.toString(0)); + updateBatteryStatsConstants(desiredConstants); checkCpuTimesAvailability(); - if (sPerProcStateTimesAvailable && sCpuFreqTimesAvailable) { - setDesiredReadyDelay(); - } } @AfterClass @@ -139,26 +141,33 @@ public class BstatsCpuTimesValidationTest { batteryReset(); } - private static void setDesiredReadyDelay() { + private static void updateBatteryStatsConstants(ArrayMap<String, String> desiredConstants) { sOriginalBatteryStatsConsts = Settings.Global.getString(sContext.getContentResolver(), Settings.Global.BATTERY_STATS_CONSTANTS); - String newBatteryStatsConstants; - final String newConstant = KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS - + "=" + DESIRED_PROC_STATE_CPU_TIMES_DELAY; - if (sOriginalBatteryStatsConsts == null || "null".equals(sOriginalBatteryStatsConsts)) { - // battery_stats_constants is initially empty, so just assign the desired value. - newBatteryStatsConstants = newConstant; - } else if (sOriginalBatteryStatsConsts.contains(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS)) { - // battery_stats_constants contains delay duration, so replace it - // with the desired value. - newBatteryStatsConstants = sOriginalBatteryStatsConsts.replaceAll( - KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS + "=\\d+", newConstant); - } else { - // battery_stats_constants didn't contain any delay, so append the desired value. - newBatteryStatsConstants = sOriginalBatteryStatsConsts + "," + newConstant; + final char delimiter = ','; + final KeyValueListParser parser = new KeyValueListParser(delimiter); + parser.setString(sOriginalBatteryStatsConsts); + final StringBuilder sb = new StringBuilder(); + for (int i = 0, size = parser.size(); i < size; ++i) { + final String key = parser.keyAt(i); + final String value = desiredConstants.getOrDefault(key, + parser.getString(key, null)); + if (sb.length() > 0) { + sb.append(delimiter); + } + sb.append(key + "=" + value); + desiredConstants.remove(key); } + desiredConstants.forEach((key, value) -> { + if (sb.length() > 0) { + sb.append(delimiter); + } + sb.append(key + '=' + value); + }); Settings.Global.putString(sContext.getContentResolver(), - Settings.Global.BATTERY_STATS_CONSTANTS, newBatteryStatsConstants); + Settings.Global.BATTERY_STATS_CONSTANTS, sb.toString()); + Log.d(TAG, "Updated value of '" + Settings.Global.BATTERY_STATS_CONSTANTS + "': " + + sb.toString()); sBatteryStatsConstsUpdated = true; } diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index 3f2d0f134443..1cdc75aa1f40 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -176,27 +176,27 @@ public class ActivityThreadClientTest { } private void startActivity(ActivityClientRecord r) { - mThread.handleStartActivity(r, null /* pendingActions */); + mThread.handleStartActivity(r.token, null /* pendingActions */); } private void resumeActivity(ActivityClientRecord r) { - mThread.handleResumeActivity(r, true /* finalStateRequest */, + mThread.handleResumeActivity(r.token, true /* finalStateRequest */, true /* isForward */, "test"); } private void pauseActivity(ActivityClientRecord r) { - mThread.handlePauseActivity(r, false /* finished */, + mThread.handlePauseActivity(r.token, false /* finished */, false /* userLeaving */, 0 /* configChanges */, null /* pendingActions */, "test"); } private void stopActivity(ActivityClientRecord r) { - mThread.handleStopActivity(r, 0 /* configChanges */, + mThread.handleStopActivity(r.token, 0 /* configChanges */, new PendingTransactionActions(), false /* finalStateRequest */, "test"); } private void destroyActivity(ActivityClientRecord r) { - mThread.handleDestroyActivity(r, true /* finishing */, 0 /* configChanges */, + mThread.handleDestroyActivity(r.token, true /* finishing */, 0 /* configChanges */, false /* getNonConfigInstance */, "test"); } diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp index 04007c91817d..d0e688d3efc1 100644 --- a/data/etc/car/Android.bp +++ b/data/etc/car/Android.bp @@ -17,126 +17,126 @@ // Privapp permission whitelist files prebuilt_etc { - name: "privapp_whitelist_android.car.cluster.loggingrenderer", + name: "allowed_privapp_android.car.cluster.loggingrenderer", sub_dir: "permissions", src: "android.car.cluster.loggingrenderer.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_android.car.cluster.sample", + name: "allowed_privapp_android.car.cluster.sample", sub_dir: "permissions", src: "android.car.cluster.sample.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_android.car.cluster", + name: "allowed_privapp_android.car.cluster", sub_dir: "permissions", src: "android.car.cluster.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_android.car.usb.handler", + name: "allowed_privapp_android.car.usb.handler", sub_dir: "permissions", src: "android.car.usb.handler.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.carlauncher", + name: "allowed_privapp_com.android.car.carlauncher", sub_dir: "permissions", src: "com.android.car.carlauncher.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.dialer", + name: "allowed_privapp_com.android.car.dialer", sub_dir: "permissions", src: "com.android.car.dialer.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.hvac", + name: "allowed_privapp_com.android.car.hvac", sub_dir: "permissions", src: "com.android.car.hvac.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.media", + name: "allowed_privapp_com.android.car.media", sub_dir: "permissions", src: "com.android.car.media.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.notification", + name: "allowed_privapp_com.android.car.notification", sub_dir: "permissions", src: "com.android.car.notification.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.radio", + name: "allowed_privapp_com.android.car.radio", sub_dir: "permissions", src: "com.android.car.radio.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.secondaryhome", + name: "allowed_privapp_com.android.car.secondaryhome", sub_dir: "permissions", src: "com.android.car.secondaryhome.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.settings", + name: "allowed_privapp_com.android.car.settings", sub_dir: "permissions", src: "com.android.car.settings.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.themeplayground", + name: "allowed_privapp_com.android.car.themeplayground", sub_dir: "permissions", src: "com.android.car.themeplayground.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car", + name: "allowed_privapp_com.android.car", sub_dir: "permissions", src: "com.android.car.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.bugreport", + name: "allowed_privapp_com.android.car.bugreport", sub_dir: "permissions", src: "com.android.car.bugreport.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.companiondevicesupport", + name: "allowed_privapp_com.android.car.companiondevicesupport", sub_dir: "permissions", src: "com.android.car.companiondevicesupport.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.google.android.car.kitchensink", + name: "allowed_privapp_com.google.android.car.kitchensink", sub_dir: "permissions", src: "com.google.android.car.kitchensink.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.developeroptions", + name: "allowed_privapp_com.android.car.developeroptions", sub_dir: "permissions", src: "com.android.car.developeroptions.xml", filename_from_src: true, @@ -144,14 +144,14 @@ prebuilt_etc { } prebuilt_etc { - name: "privapp_whitelist_com.android.car.floatingcardslauncher", + name: "allowed_privapp_com.android.car.floatingcardslauncher", sub_dir: "permissions", src: "com.android.car.floatingcardslauncher.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.ui.paintbooth", + name: "allowed_privapp_com.android.car.ui.paintbooth", sub_dir: "permissions", src: "com.android.car.ui.paintbooth.xml", filename_from_src: true, diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml index ada8b000a26b..06f1dae30cd3 100644 --- a/data/etc/com.android.systemui.xml +++ b/data/etc/com.android.systemui.xml @@ -35,6 +35,7 @@ <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.MASTER_CLEAR"/> <permission name="android.permission.MEDIA_CONTENT_CONTROL"/> + <permission name="android.permission.MODIFY_AUDIO_ROUTING" /> <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/> <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 28d7911c771f..964640b106b9 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -3111,7 +3111,7 @@ public class Paint { @CriticalNative private static native boolean nGetFillPath(long paintPtr, long src, long dst); @CriticalNative - private static native long nSetShader(long paintPtr, long shader); + private static native void nSetShader(long paintPtr, long shader); @CriticalNative private static native long nSetColorFilter(long paintPtr, long filter); @CriticalNative diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 9ae5ad97ed36..0b13754271b9 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -462,6 +462,13 @@ cc_defaults { "RenderNode.cpp", "RenderProperties.cpp", "RootRenderNode.cpp", + "shader/Shader.cpp", + "shader/BitmapShader.cpp", + "shader/ComposeShader.cpp", + "shader/LinearGradientShader.cpp", + "shader/RadialGradientShader.cpp", + "shader/RuntimeShader.cpp", + "shader/SweepGradientShader.cpp", "SkiaCanvas.cpp", "VectorDrawable.cpp", ], diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 242b8b0d139e..cfba5d4f6aa2 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -42,6 +42,8 @@ #include <SkTextBlob.h> #include <SkVertices.h> +#include <shader/BitmapShader.h> + #include <memory> #include <optional> #include <utility> @@ -49,6 +51,7 @@ namespace android { using uirenderer::PaintUtils; +using uirenderer::BitmapShader; Canvas* Canvas::create_canvas(const SkBitmap& bitmap) { return new SkiaCanvas(bitmap); @@ -681,7 +684,9 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, if (paint) { pnt = *paint; } - pnt.setShader(bitmap.makeImage()->makeShader()); + + pnt.setShader(sk_ref_sp(new BitmapShader( + bitmap.makeImage(), SkTileMode::kClamp, SkTileMode::kClamp, nullptr))); auto v = builder.detach(); apply_looper(&pnt, [&](const SkPaint& p) { mCanvas->drawVertices(v, SkBlendMode::kModulate, p); diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index cd908354aea5..0f566e4b494a 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -23,7 +23,6 @@ #include "PathParser.h" #include "SkColorFilter.h" #include "SkImageInfo.h" -#include "SkShader.h" #include "hwui/Paint.h" #ifdef __ANDROID__ @@ -159,10 +158,10 @@ void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) { // Draw path's fill, if fill color or gradient is valid bool needsFill = false; - SkPaint paint; + Paint paint; if (properties.getFillGradient() != nullptr) { paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha())); - paint.setShader(sk_sp<SkShader>(SkSafeRef(properties.getFillGradient()))); + paint.setShader(sk_sp<Shader>(SkSafeRef(properties.getFillGradient()))); needsFill = true; } else if (properties.getFillColor() != SK_ColorTRANSPARENT) { paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha())); @@ -179,7 +178,7 @@ void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) { bool needsStroke = false; if (properties.getStrokeGradient() != nullptr) { paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha())); - paint.setShader(sk_sp<SkShader>(SkSafeRef(properties.getStrokeGradient()))); + paint.setShader(sk_sp<Shader>(SkSafeRef(properties.getStrokeGradient()))); needsStroke = true; } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) { paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha())); diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index ac7d41e0d600..d4086f1aa622 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -31,8 +31,8 @@ #include <SkPath.h> #include <SkPathMeasure.h> #include <SkRect.h> -#include <SkShader.h> #include <SkSurface.h> +#include <shader/Shader.h> #include <cutils/compiler.h> #include <stddef.h> @@ -227,20 +227,20 @@ public: strokeGradient = prop.strokeGradient; onPropertyChanged(); } - void setFillGradient(SkShader* gradient) { + void setFillGradient(Shader* gradient) { if (fillGradient.get() != gradient) { fillGradient = sk_ref_sp(gradient); onPropertyChanged(); } } - void setStrokeGradient(SkShader* gradient) { + void setStrokeGradient(Shader* gradient) { if (strokeGradient.get() != gradient) { strokeGradient = sk_ref_sp(gradient); onPropertyChanged(); } } - SkShader* getFillGradient() const { return fillGradient.get(); } - SkShader* getStrokeGradient() const { return strokeGradient.get(); } + Shader* getFillGradient() const { return fillGradient.get(); } + Shader* getStrokeGradient() const { return strokeGradient.get(); } float getStrokeWidth() const { return mPrimitiveFields.strokeWidth; } void setStrokeWidth(float strokeWidth) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth); @@ -320,8 +320,8 @@ public: count, }; PrimitiveFields mPrimitiveFields; - sk_sp<SkShader> fillGradient; - sk_sp<SkShader> strokeGradient; + sk_sp<Shader> fillGradient; + sk_sp<Shader> strokeGradient; }; // Called from UI thread diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp index c138a32eacc2..2a377bbb83f2 100644 --- a/libs/hwui/hwui/Canvas.cpp +++ b/libs/hwui/hwui/Canvas.cpp @@ -73,7 +73,7 @@ void Canvas::drawTextDecorations(float x, float y, float length, const Paint& pa static void simplifyPaint(int color, Paint* paint) { paint->setColor(color); - paint->setShader(nullptr); + paint->setShader((sk_sp<uirenderer::Shader>)nullptr); paint->setColorFilter(nullptr); paint->setLooper(nullptr); paint->setStrokeWidth(4 + 0.04 * paint->getSkFont().getSize()); diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h index e75e9e7c6933..0bb689c19079 100644 --- a/libs/hwui/hwui/Paint.h +++ b/libs/hwui/hwui/Paint.h @@ -30,6 +30,8 @@ #include <minikin/FamilyVariant.h> #include <minikin/Hyphenator.h> +#include <shader/Shader.h> + namespace android { class Paint : public SkPaint { @@ -149,8 +151,14 @@ public: // The only respected flags are : [ antialias, dither, filterBitmap ] static uint32_t GetSkPaintJavaFlags(const SkPaint&); static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags); + + void setShader(sk_sp<uirenderer::Shader> shader); private: + + using SkPaint::setShader; + using SkPaint::setImageFilter; + SkFont mFont; sk_sp<SkDrawLooper> mLooper; @@ -169,6 +177,7 @@ private: bool mStrikeThru = false; bool mUnderline = false; bool mDevKern = false; + sk_sp<uirenderer::Shader> mShader; }; } // namespace android diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp index fa2674fc2f5e..21f60fd7b671 100644 --- a/libs/hwui/hwui/PaintImpl.cpp +++ b/libs/hwui/hwui/PaintImpl.cpp @@ -24,7 +24,8 @@ Paint::Paint() , mWordSpacing(0) , mFontFeatureSettings() , mMinikinLocaleListId(0) - , mFamilyVariant(minikin::FamilyVariant::DEFAULT) { + , mFamilyVariant(minikin::FamilyVariant::DEFAULT) + , mShader(nullptr) { // SkPaint::antialiasing defaults to false, but // SkFont::edging defaults to kAntiAlias. To keep them // insync, we manually set the font to kAilas. @@ -45,7 +46,8 @@ Paint::Paint(const Paint& paint) , mAlign(paint.mAlign) , mStrikeThru(paint.mStrikeThru) , mUnderline(paint.mUnderline) - , mDevKern(paint.mDevKern) {} + , mDevKern(paint.mDevKern) + , mShader(paint.mShader){} Paint::~Paint() {} @@ -65,9 +67,30 @@ Paint& Paint::operator=(const Paint& other) { mStrikeThru = other.mStrikeThru; mUnderline = other.mUnderline; mDevKern = other.mDevKern; + mShader = other.mShader; return *this; } +void Paint::setShader(sk_sp<uirenderer::Shader> shader) { + if (shader) { + // If there is an SkShader compatible shader, apply it + sk_sp<SkShader> skShader = shader->asSkShader(); + if (skShader.get()) { + SkPaint::setShader(skShader); + SkPaint::setImageFilter(nullptr); + } else { + // ... otherwise the specified shader can only be represented as an ImageFilter + SkPaint::setShader(nullptr); + SkPaint::setImageFilter(shader->asSkImageFilter()); + } + } else { + // No shader is provided at all, clear out both the SkShader and SkImageFilter slots + SkPaint::setShader(nullptr); + SkPaint::setImageFilter(nullptr); + } + mShader = shader; +} + bool operator==(const Paint& a, const Paint& b) { return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b) && a.mFont == b.mFont && diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp index df8635a8fe5a..554674a331cd 100644 --- a/libs/hwui/jni/Paint.cpp +++ b/libs/hwui/jni/Paint.cpp @@ -47,6 +47,7 @@ #include <minikin/LocaleList.h> #include <minikin/Measurement.h> #include <minikin/MinikinPaint.h> +#include <shader/Shader.h> #include <unicode/utf16.h> #include <cassert> @@ -54,6 +55,8 @@ #include <memory> #include <vector> +using namespace android::uirenderer; + namespace android { struct JMetricsID { @@ -782,11 +785,10 @@ namespace PaintGlue { return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE; } - static jlong setShader(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong shaderHandle) { - Paint* obj = reinterpret_cast<Paint*>(objHandle); - SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); - obj->setShader(sk_ref_sp(shader)); - return reinterpret_cast<jlong>(obj->getShader()); + static void setShader(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong shaderHandle) { + auto* paint = reinterpret_cast<Paint*>(objHandle); + auto* shader = reinterpret_cast<Shader*>(shaderHandle); + paint->setShader(sk_ref_sp(shader)); } static jlong setColorFilter(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong filterHandle) { @@ -1097,7 +1099,7 @@ static const JNINativeMethod methods[] = { {"nGetStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin}, {"nSetStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin}, {"nGetFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath}, - {"nSetShader","(JJ)J", (void*) PaintGlue::setShader}, + {"nSetShader","(JJ)V", (void*) PaintGlue::setShader}, {"nSetColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter}, {"nSetXfermode","(JI)V", (void*) PaintGlue::setXfermode}, {"nSetPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect}, diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp index e76aace601be..9b1972ed664f 100644 --- a/libs/hwui/jni/Shader.cpp +++ b/libs/hwui/jni/Shader.cpp @@ -5,6 +5,13 @@ #include "SkShader.h" #include "SkBlendMode.h" #include "include/effects/SkRuntimeEffect.h" +#include "shader/Shader.h" +#include "shader/BitmapShader.h" +#include "shader/ComposeShader.h" +#include "shader/LinearGradientShader.h" +#include "shader/RadialGradientShader.h" +#include "shader/RuntimeShader.h" +#include "shader/SweepGradientShader.h" #include <vector> @@ -50,7 +57,7 @@ static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvAr /////////////////////////////////////////////////////////////////////////////////////////////// -static void Shader_safeUnref(SkShader* shader) { +static void Shader_safeUnref(Shader* shader) { SkSafeUnref(shader); } @@ -74,15 +81,15 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j SkBitmap bitmap; image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode); } - sk_sp<SkShader> shader = image->makeShader( - (SkTileMode)tileModeX, (SkTileMode)tileModeY); - ThrowIAE_IfNull(env, shader.get()); - if (matrix) { - shader = shader->makeWithLocalMatrix(*matrix); - } + auto* shader = new BitmapShader( + image, + static_cast<SkTileMode>(tileModeX), + static_cast<SkTileMode>(tileModeY), + matrix + ); - return reinterpret_cast<jlong>(shader.release()); + return reinterpret_cast<jlong>(shader); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -118,17 +125,18 @@ static jlong LinearGradient_create(JNIEnv* env, jobject, jlong matrixPtr, #error Need to convert float array to SkScalar array before calling the following function. #endif - sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0], - GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), - static_cast<SkTileMode>(tileMode), sGradientShaderFlags, nullptr)); - ThrowIAE_IfNull(env, shader); - - const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - if (matrix) { - shader = shader->makeWithLocalMatrix(*matrix); - } + auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); + auto* shader = new LinearGradientShader( + pts, + colors, + GraphicsJNI::getNativeColorSpace(colorSpaceHandle), + pos, + static_cast<SkTileMode>(tileMode), + sGradientShaderFlags, + matrix + ); - return reinterpret_cast<jlong>(shader.release()); + return reinterpret_cast<jlong>(shader); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -148,17 +156,20 @@ static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat #error Need to convert float array to SkScalar array before calling the following function. #endif - sk_sp<SkShader> shader = SkGradientShader::MakeRadial(center, radius, &colors[0], - GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), - static_cast<SkTileMode>(tileMode), sGradientShaderFlags, nullptr); - ThrowIAE_IfNull(env, shader); + auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - if (matrix) { - shader = shader->makeWithLocalMatrix(*matrix); - } + auto* shader = new RadialGradientShader( + center, + radius, + colors, + GraphicsJNI::getNativeColorSpace(colorSpaceHandle), + pos, + static_cast<SkTileMode>(tileMode), + sGradientShaderFlags, + matrix + ); - return reinterpret_cast<jlong>(shader.release()); + return reinterpret_cast<jlong>(shader); } /////////////////////////////////////////////////////////////////////////////// @@ -174,54 +185,58 @@ static jlong SweepGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat #error Need to convert float array to SkScalar array before calling the following function. #endif - sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0], - GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), - sGradientShaderFlags, nullptr); - ThrowIAE_IfNull(env, shader); + auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - if (matrix) { - shader = shader->makeWithLocalMatrix(*matrix); - } + auto* shader = new SweepGradientShader( + x, + y, + colors, + GraphicsJNI::getNativeColorSpace(colorSpaceHandle), + pos, + sGradientShaderFlags, + matrix + ); - return reinterpret_cast<jlong>(shader.release()); + return reinterpret_cast<jlong>(shader); } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong ComposeShader_create(JNIEnv* env, jobject o, jlong matrixPtr, jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle) { - const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle); - SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle); - SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle); - sk_sp<SkShader> baseShader(SkShaders::Blend(mode, - sk_ref_sp(shaderA), sk_ref_sp(shaderB))); - - SkShader* shader; - - if (matrix) { - shader = baseShader->makeWithLocalMatrix(*matrix).release(); - } else { - shader = baseShader.release(); - } - return reinterpret_cast<jlong>(shader); + auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); + auto* shaderA = reinterpret_cast<Shader*>(shaderAHandle); + auto* shaderB = reinterpret_cast<Shader*>(shaderBHandle); + + auto mode = static_cast<SkBlendMode>(xfermodeHandle); + + auto* composeShader = new ComposeShader( + *shaderA, + *shaderB, + mode, + matrix + ); + + return reinterpret_cast<jlong>(composeShader); } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr, jbyteArray inputs, jlong colorSpaceHandle, jboolean isOpaque) { - SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory); + auto* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory); AutoJavaByteArray arInputs(env, inputs); - sk_sp<SkData> fData; - fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length()); - const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - sk_sp<SkShader> shader = effect->makeShader(fData, nullptr, 0, matrix, isOpaque == JNI_TRUE); - ThrowIAE_IfNull(env, shader); + auto data = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length()); + auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - return reinterpret_cast<jlong>(shader.release()); + auto* shader = new RuntimeShader( + *effect, + std::move(data), + isOpaque == JNI_TRUE, + matrix + ); + return reinterpret_cast<jlong>(shader); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -239,12 +254,8 @@ static jlong RuntimeShader_createShaderFactory(JNIEnv* env, jobject, jstring sks /////////////////////////////////////////////////////////////////////////////////////////////// -static void Effect_safeUnref(SkRuntimeEffect* effect) { - SkSafeUnref(effect); -} - static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) { - return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Effect_safeUnref)); + return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref)); } /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp index 9cffceb308c8..a1adcb30e80d 100644 --- a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp +++ b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp @@ -143,13 +143,13 @@ static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong full static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) { VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr); - SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr); + auto* fillShader = reinterpret_cast<Shader*>(fillGradientPtr); path->mutateStagingProperties()->setFillGradient(fillShader); } static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) { VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr); - SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr); + auto* strokeShader = reinterpret_cast<Shader*>(strokeGradientPtr); path->mutateStagingProperties()->setStrokeGradient(strokeShader); } diff --git a/libs/hwui/shader/BitmapShader.cpp b/libs/hwui/shader/BitmapShader.cpp new file mode 100644 index 000000000000..fe653e85a021 --- /dev/null +++ b/libs/hwui/shader/BitmapShader.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 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 "BitmapShader.h" + +#include "SkImagePriv.h" + +namespace android::uirenderer { +BitmapShader::BitmapShader(const sk_sp<SkImage>& image, const SkTileMode tileModeX, + const SkTileMode tileModeY, const SkMatrix* matrix) + : Shader(matrix), skShader(image->makeShader(tileModeX, tileModeY)) {} + +sk_sp<SkShader> BitmapShader::makeSkShader() { + return skShader; +} + +BitmapShader::~BitmapShader() {} +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/BitmapShader.h b/libs/hwui/shader/BitmapShader.h new file mode 100644 index 000000000000..ed6a6e6802d1 --- /dev/null +++ b/libs/hwui/shader/BitmapShader.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Shader.h" +#include "SkShader.h" + +namespace android::uirenderer { + +/** + * Shader implementation that renders a Bitmap as either a SkShader or SkImageFilter + */ +class BitmapShader : public Shader { +public: + BitmapShader(const sk_sp<SkImage>& image, const SkTileMode tileModeX, + const SkTileMode tileModeY, const SkMatrix* matrix); + ~BitmapShader() override; + +protected: + sk_sp<SkShader> makeSkShader() override; + +private: + sk_sp<SkShader> skShader; +}; +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/ComposeShader.cpp b/libs/hwui/shader/ComposeShader.cpp new file mode 100644 index 000000000000..3765489e7431 --- /dev/null +++ b/libs/hwui/shader/ComposeShader.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 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 "ComposeShader.h" + +#include "SkImageFilters.h" +#include "SkShader.h" + +namespace android::uirenderer { + +ComposeShader::ComposeShader(Shader& shaderA, Shader& shaderB, const SkBlendMode blendMode, + const SkMatrix* matrix) + : Shader(matrix) { + // If both Shaders can be represented as SkShaders then use those, if not + // create an SkImageFilter from both Shaders and create the equivalent SkImageFilter + sk_sp<SkShader> skShaderA = shaderA.asSkShader(); + sk_sp<SkShader> skShaderB = shaderB.asSkShader(); + if (skShaderA.get() && skShaderB.get()) { + skShader = SkShaders::Blend(blendMode, skShaderA, skShaderB); + skImageFilter = nullptr; + } else { + sk_sp<SkImageFilter> skImageFilterA = shaderA.asSkImageFilter(); + sk_sp<SkImageFilter> skImageFilterB = shaderB.asSkImageFilter(); + skShader = nullptr; + skImageFilter = SkImageFilters::Xfermode(blendMode, skImageFilterA, skImageFilterB); + } +} + +sk_sp<SkShader> ComposeShader::makeSkShader() { + return skShader; +} + +sk_sp<SkImageFilter> ComposeShader::makeSkImageFilter() { + return skImageFilter; +} + +ComposeShader::~ComposeShader() {} +} // namespace android::uirenderer diff --git a/libs/hwui/shader/ComposeShader.h b/libs/hwui/shader/ComposeShader.h new file mode 100644 index 000000000000..a246b520d46a --- /dev/null +++ b/libs/hwui/shader/ComposeShader.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Shader.h" +#include "SkShader.h" + +namespace android::uirenderer { + +/** + * Shader implementation that can composite 2 Shaders together with the specified blend mode. + * This implementation can appropriately convert the composed result to either an SkShader or + * SkImageFilter depending on the inputs + */ +class ComposeShader : public Shader { +public: + ComposeShader(Shader& shaderA, Shader& shaderB, const SkBlendMode blendMode, + const SkMatrix* matrix); + ~ComposeShader() override; + +protected: + sk_sp<SkShader> makeSkShader() override; + sk_sp<SkImageFilter> makeSkImageFilter() override; + +private: + sk_sp<SkShader> skShader; + sk_sp<SkImageFilter> skImageFilter; +}; +} // namespace android::uirenderer diff --git a/libs/hwui/shader/LinearGradientShader.cpp b/libs/hwui/shader/LinearGradientShader.cpp new file mode 100644 index 000000000000..868fa44fb4b7 --- /dev/null +++ b/libs/hwui/shader/LinearGradientShader.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 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 "LinearGradientShader.h" + +#include <vector> + +#include "SkGradientShader.h" + +namespace android::uirenderer { + +LinearGradientShader::LinearGradientShader(const SkPoint pts[2], + const std::vector<SkColor4f>& colors, + sk_sp<SkColorSpace> colorspace, const SkScalar pos[], + const SkTileMode tileMode, const uint32_t shaderFlags, + const SkMatrix* matrix) + : Shader(matrix) + , skShader(SkGradientShader::MakeLinear(pts, colors.data(), colorspace, pos, colors.size(), + tileMode, shaderFlags, nullptr)) {} + +sk_sp<SkShader> LinearGradientShader::makeSkShader() { + return skShader; +} + +LinearGradientShader::~LinearGradientShader() {} +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/LinearGradientShader.h b/libs/hwui/shader/LinearGradientShader.h new file mode 100644 index 000000000000..596f4e009448 --- /dev/null +++ b/libs/hwui/shader/LinearGradientShader.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Shader.h" +#include "SkShader.h" + +namespace android::uirenderer { + +/** + * Shader implementation that renders a color ramp of colors to either as either SkShader or + * SkImageFilter + */ +class LinearGradientShader : public Shader { +public: + LinearGradientShader(const SkPoint pts[2], const std::vector<SkColor4f>& colors, + sk_sp<SkColorSpace> colorspace, const SkScalar pos[], + const SkTileMode tileMode, const uint32_t shaderFlags, + const SkMatrix* matrix); + ~LinearGradientShader() override; + +protected: + sk_sp<SkShader> makeSkShader() override; + +private: + sk_sp<SkShader> skShader; +}; +} // namespace android::uirenderer diff --git a/libs/hwui/shader/RadialGradientShader.cpp b/libs/hwui/shader/RadialGradientShader.cpp new file mode 100644 index 000000000000..21ff56fee2f8 --- /dev/null +++ b/libs/hwui/shader/RadialGradientShader.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 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 "RadialGradientShader.h" + +#include <vector> + +#include "SkGradientShader.h" + +namespace android::uirenderer { + +RadialGradientShader::RadialGradientShader(const SkPoint& center, const float radius, + const std::vector<SkColor4f>& colors, + sk_sp<SkColorSpace> colorspace, const SkScalar pos[], + const SkTileMode tileMode, const uint32_t shaderFlags, + const SkMatrix* matrix) + : Shader(matrix) + , skShader(SkGradientShader::MakeRadial(center, radius, colors.data(), colorspace, pos, + colors.size(), tileMode, shaderFlags, nullptr)) {} + +sk_sp<SkShader> RadialGradientShader::makeSkShader() { + return skShader; +} + +RadialGradientShader::~RadialGradientShader() {} +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/RadialGradientShader.h b/libs/hwui/shader/RadialGradientShader.h new file mode 100644 index 000000000000..9a2ff139aedb --- /dev/null +++ b/libs/hwui/shader/RadialGradientShader.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Shader.h" +#include "SkShader.h" + +namespace android::uirenderer { + +/** + * Shader implementation that renders a color ramp from the center outward to either as either + * a SkShader or SkImageFilter + */ +class RadialGradientShader : public Shader { +public: + RadialGradientShader(const SkPoint& center, const float radius, + const std::vector<SkColor4f>& colors, sk_sp<SkColorSpace> colorSpace, + const SkScalar pos[], const SkTileMode tileMode, const uint32_t shaderFlags, + const SkMatrix* matrix); + ~RadialGradientShader() override; + +protected: + sk_sp<SkShader> makeSkShader() override; + +private: + sk_sp<SkShader> skShader; +}; +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/RuntimeShader.cpp b/libs/hwui/shader/RuntimeShader.cpp new file mode 100644 index 000000000000..dd0b6980841a --- /dev/null +++ b/libs/hwui/shader/RuntimeShader.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 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 "RuntimeShader.h" + +#include "SkShader.h" +#include "include/effects/SkRuntimeEffect.h" + +namespace android::uirenderer { + +RuntimeShader::RuntimeShader(SkRuntimeEffect& effect, sk_sp<SkData> data, bool isOpaque, + const SkMatrix* matrix) + : Shader(nullptr) + , // Explicitly passing null as RuntimeShader is created with the + // matrix directly + skShader(effect.makeShader(std::move(data), nullptr, 0, matrix, isOpaque)) {} + +sk_sp<SkShader> RuntimeShader::makeSkShader() { + return skShader; +} + +RuntimeShader::~RuntimeShader() {} +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/RuntimeShader.h b/libs/hwui/shader/RuntimeShader.h new file mode 100644 index 000000000000..7fe0b0206467 --- /dev/null +++ b/libs/hwui/shader/RuntimeShader.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Shader.h" +#include "SkShader.h" +#include "include/effects/SkRuntimeEffect.h" + +namespace android::uirenderer { + +/** + * RuntimeShader implementation that can map to either a SkShader or SkImageFilter + */ +class RuntimeShader : public Shader { +public: + RuntimeShader(SkRuntimeEffect& effect, sk_sp<SkData> data, bool isOpaque, + const SkMatrix* matrix); + ~RuntimeShader() override; + +protected: + sk_sp<SkShader> makeSkShader() override; + +private: + sk_sp<SkShader> skShader; +}; +} // namespace android::uirenderer diff --git a/libs/hwui/shader/Shader.cpp b/libs/hwui/shader/Shader.cpp new file mode 100644 index 000000000000..45123dd55002 --- /dev/null +++ b/libs/hwui/shader/Shader.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2020 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 "Shader.h" + +#include "SkImageFilters.h" +#include "SkPaint.h" +#include "SkRefCnt.h" + +namespace android::uirenderer { + +Shader::Shader(const SkMatrix* matrix) + : localMatrix(matrix ? *matrix : SkMatrix::I()) + , skShader(nullptr) + , skImageFilter(nullptr) {} + +Shader::~Shader() {} + +sk_sp<SkShader> Shader::asSkShader() { + // If we already have created a shader with these parameters just return the existing + // shader we have already created + if (!this->skShader.get()) { + this->skShader = makeSkShader(); + if (this->skShader.get()) { + if (!localMatrix.isIdentity()) { + this->skShader = this->skShader->makeWithLocalMatrix(localMatrix); + } + } + } + return this->skShader; +} + +/** + * By default return null as we cannot convert all visual effects to SkShader instances + */ +sk_sp<SkShader> Shader::makeSkShader() { + return nullptr; +} + +sk_sp<SkImageFilter> Shader::asSkImageFilter() { + // If we already have created an ImageFilter with these parameters just return the existing + // ImageFilter we have already created + if (!this->skImageFilter.get()) { + // Attempt to create an SkImageFilter from the current Shader implementation + this->skImageFilter = makeSkImageFilter(); + if (this->skImageFilter) { + if (!localMatrix.isIdentity()) { + // If we have created an SkImageFilter and we have a transformation, wrap + // the created SkImageFilter to apply the given matrix + this->skImageFilter = SkImageFilters::MatrixTransform( + localMatrix, kMedium_SkFilterQuality, this->skImageFilter); + } + } else { + // Otherwise if no SkImageFilter implementation is provided, create one from + // the result of asSkShader. Note the matrix is already applied to the shader in + // this case so just convert it to an SkImageFilter using SkImageFilters::Paint + SkPaint paint; + paint.setShader(asSkShader()); + sk_sp<SkImageFilter> paintFilter = SkImageFilters::Paint(paint); + this->skImageFilter = SkImageFilters::Xfermode(SkBlendMode::kDstIn, + std::move(paintFilter)); + } + } + return this->skImageFilter; +} + +/** + * By default return null for subclasses to implement. If there is not a direct SkImageFilter + * conversion + */ +sk_sp<SkImageFilter> Shader::makeSkImageFilter() { + return nullptr; +} +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/Shader.h b/libs/hwui/shader/Shader.h new file mode 100644 index 000000000000..3c0cdaae8253 --- /dev/null +++ b/libs/hwui/shader/Shader.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "SkImageFilter.h" +#include "SkShader.h" +#include "SkPaint.h" +#include "SkRefCnt.h" + +class SkMatrix; + +namespace android::uirenderer { + +/** + * Shader class that can optionally wrap an SkShader or SkImageFilter depending + * on the implementation + */ +class Shader: public SkRefCnt { +public: + /** + * Creates a Shader instance with an optional transformation matrix + * @param matrix Optional matrix to transform the underlying SkShader or SkImageFilter + */ + Shader(const SkMatrix* matrix); + virtual ~Shader(); + + /** + * Create an SkShader from the current Shader instance or return a previously + * created instance. This can be null if no SkShader could be created from this + * Shader instance. + */ + sk_sp<SkShader> asSkShader(); + + /** + * Create an SkImageFilter from the current Shader instance or return a previously + * created instance. Unlike asSkShader, this method cannot return null. + */ + sk_sp<SkImageFilter> asSkImageFilter(); + +protected: + /** + * Create a new SkShader instance based on this Shader instance + */ + virtual sk_sp<SkShader> makeSkShader(); + + /** + * Create a new SkImageFilter instance based on this Shader instance. If no SkImageFilter + * can be created then return nullptr + */ + virtual sk_sp<SkImageFilter> makeSkImageFilter(); + +private: + /** + * Optional matrix transform + */ + const SkMatrix localMatrix; + + /** + * Cached SkShader instance to be returned on subsequent queries + */ + sk_sp<SkShader> skShader; + + /** + * Cached SkImageFilter instance to be returned on subsequent queries + */ + sk_sp<SkImageFilter> skImageFilter; +}; +} // namespace android::uirenderer diff --git a/libs/hwui/shader/SweepGradientShader.cpp b/libs/hwui/shader/SweepGradientShader.cpp new file mode 100644 index 000000000000..3b1f37f8b051 --- /dev/null +++ b/libs/hwui/shader/SweepGradientShader.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 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 "SweepGradientShader.h" + +#include <vector> + +#include "SkGradientShader.h" +#include "SkImageFilters.h" + +namespace android::uirenderer { + +SweepGradientShader::SweepGradientShader(float x, float y, const std::vector<SkColor4f>& colors, + const sk_sp<SkColorSpace>& colorspace, const SkScalar pos[], + const uint32_t shaderFlags, const SkMatrix* matrix) + : Shader(matrix) + , skShader(SkGradientShader::MakeSweep(x, y, colors.data(), colorspace, pos, colors.size(), + shaderFlags, nullptr)) {} + +sk_sp<SkShader> SweepGradientShader::makeSkShader() { + return skShader; +} + +SweepGradientShader::~SweepGradientShader() {} +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/shader/SweepGradientShader.h b/libs/hwui/shader/SweepGradientShader.h new file mode 100644 index 000000000000..dad3ef0ffad4 --- /dev/null +++ b/libs/hwui/shader/SweepGradientShader.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Shader.h" +#include "SkShader.h" + +namespace android::uirenderer { + +/** + * Shader implementation that renders a color ramp clockwise such that the start and end colors + * are visible at 3 o'clock. This handles converting to either an SkShader or SkImageFilter + */ +class SweepGradientShader : public Shader { +public: + SweepGradientShader(float x, float y, const std::vector<SkColor4f>& colors, + const sk_sp<SkColorSpace>& colorspace, const SkScalar pos[], + const uint32_t shaderFlags, const SkMatrix* matrix); + virtual ~SweepGradientShader() override; + +protected: + virtual sk_sp<SkShader> makeSkShader() override; + +private: + sk_sp<SkShader> skShader; +}; +} // namespace android::uirenderer diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp index c4067af388e3..e2c1651d823a 100644 --- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp +++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp @@ -18,6 +18,7 @@ #include "hwui/Paint.h" #include "TestSceneBase.h" #include "tests/common/BitmapAllocationTestUtils.h" +#include <shader/BitmapShader.h> #include "utils/Color.h" class BitmapShaders; @@ -45,15 +46,24 @@ public: }); Paint paint; + sk_sp<BitmapShader> bitmapShader = sk_make_sp<BitmapShader>( + hwuiBitmap->makeImage(), + SkTileMode::kRepeat, + SkTileMode::kRepeat, + nullptr + ); + sk_sp<SkImage> image = hwuiBitmap->makeImage(); - sk_sp<SkShader> repeatShader = - image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat); - paint.setShader(std::move(repeatShader)); + paint.setShader(std::move(bitmapShader)); canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint); - sk_sp<SkShader> mirrorShader = - image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror); - paint.setShader(std::move(mirrorShader)); + sk_sp<BitmapShader> mirrorBitmapShader = sk_make_sp<BitmapShader>( + image, + SkTileMode::kMirror, + SkTileMode::kMirror, + nullptr + ); + paint.setShader(std::move(mirrorBitmapShader)); canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint); } diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp index 5886ea39acce..d37bc3c7d37c 100644 --- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp +++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp @@ -20,6 +20,10 @@ #include <SkGradientShader.h> #include <SkImagePriv.h> #include <ui/PixelFormat.h> +#include <shader/BitmapShader.h> +#include <shader/LinearGradientShader.h> +#include <shader/RadialGradientShader.h> +#include <shader/ComposeShader.h> class HwBitmapInCompositeShader; @@ -50,20 +54,41 @@ public: pixels[4000 + 4 * i + 3] = 255; } buffer->unlock(); - sk_sp<Bitmap> hardwareBitmap(Bitmap::createFrom(buffer->toAHardwareBuffer(), - SkColorSpace::MakeSRGB())); - sk_sp<SkShader> hardwareShader(createBitmapShader(*hardwareBitmap)); + + sk_sp<BitmapShader> bitmapShader = sk_make_sp<BitmapShader>( + Bitmap::createFrom( + buffer->toAHardwareBuffer(), + SkColorSpace::MakeSRGB() + )->makeImage(), + SkTileMode::kClamp, + SkTileMode::kClamp, + nullptr + ); SkPoint center; center.set(50, 50); - SkColor colors[2]; - colors[0] = Color::Black; - colors[1] = Color::White; - sk_sp<SkShader> gradientShader = SkGradientShader::MakeRadial( - center, 50, colors, nullptr, 2, SkTileMode::kRepeat); - - sk_sp<SkShader> compositeShader( - SkShaders::Blend(SkBlendMode::kDstATop, hardwareShader, gradientShader)); + + std::vector<SkColor4f> vColors(2); + vColors[0] = SkColors::kBlack; + vColors[1] = SkColors::kWhite; + + sk_sp<RadialGradientShader> radialShader = sk_make_sp<RadialGradientShader>( + center, + 50, + vColors, + SkColorSpace::MakeSRGB(), + nullptr, + SkTileMode::kRepeat, + 0, + nullptr + ); + + sk_sp<ComposeShader> compositeShader = sk_make_sp<ComposeShader>( + *bitmapShader.get(), + *radialShader.get(), + SkBlendMode::kDstATop, + nullptr + ); Paint paint; paint.setShader(std::move(compositeShader)); diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp index a9449b62a1f8..76e39deedd9a 100644 --- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp +++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp @@ -17,7 +17,8 @@ #include "TestSceneBase.h" #include "tests/common/TestListViewSceneBase.h" #include "hwui/Paint.h" -#include <SkGradientShader.h> +#include "SkColor.h" +#include <shader/LinearGradientShader.h> class ListOfFadedTextAnimation; @@ -42,15 +43,26 @@ class ListOfFadedTextAnimation : public TestListViewSceneBase { pts[0].set(0, 0); pts[1].set(0, 1); - SkColor colors[2] = {Color::Black, Color::Transparent}; - sk_sp<SkShader> s( - SkGradientShader::MakeLinear(pts, colors, NULL, 2, SkTileMode::kClamp)); - SkMatrix matrix; matrix.setScale(1, length); matrix.postRotate(-90); + + std::vector<SkColor4f> vColors(2); + vColors[0] = SkColors::kBlack; + vColors[1] = SkColors::kTransparent; + + sk_sp<LinearGradientShader> linearGradientShader = sk_make_sp<LinearGradientShader>( + pts, + vColors, + SkColorSpace::MakeSRGB(), + nullptr, + SkTileMode::kClamp, + 0, + &matrix + ); + Paint fadingPaint; - fadingPaint.setShader(s->makeWithLocalMatrix(matrix)); + fadingPaint.setShader(linearGradientShader); fadingPaint.setBlendMode(SkBlendMode::kDstOut); canvas.drawRect(0, 0, length, itemHeight, fadingPaint); canvas.restore(); diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp index a0bc5aa245d5..bdc157f85264 100644 --- a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp +++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp @@ -17,7 +17,7 @@ #include "TestSceneBase.h" #include <SkColorMatrixFilter.h> -#include <SkGradientShader.h> +#include <shader/LinearGradientShader.h> class SimpleColorMatrixAnimation; @@ -65,9 +65,12 @@ private: // enough renderer might apply it directly to the paint color) float pos[] = {0, 1}; SkPoint pts[] = {SkPoint::Make(0, 0), SkPoint::Make(width, height)}; - SkColor colors[2] = {Color::DeepPurple_500, Color::DeepOrange_500}; - paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, - SkTileMode::kClamp)); + std::vector<SkColor4f> colors(2); + colors[0] = SkColor4f::FromColor(Color::DeepPurple_500); + colors[1] = SkColor4f::FromColor(Color::DeepOrange_500); + paint.setShader(sk_make_sp<LinearGradientShader>( + pts, colors, SkColorSpace::MakeSRGB(), pos, SkTileMode::kClamp, + 0, nullptr)); // overdraw several times to emphasize shader cost for (int i = 0; i < 10; i++) { diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp index 57a260c8d234..9a15c9d370a4 100644 --- a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp +++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp @@ -17,6 +17,7 @@ #include "TestSceneBase.h" #include <SkGradientShader.h> +#include <shader/LinearGradientShader.h> class SimpleGradientAnimation; @@ -55,9 +56,24 @@ private: // overdraw several times to emphasize shader cost for (int i = 0; i < 10; i++) { // use i%2 start position to pick 2 color combo with black in it - SkColor colors[3] = {Color::Transparent, Color::Black, Color::Cyan_500}; - paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2, - SkTileMode::kClamp)); + std::vector<SkColor4f> vColors(2); + vColors[0] = ((i % 2) == 0) ? + SkColor4f::FromColor(Color::Transparent) : + SkColor4f::FromColor(Color::Black); + vColors[1] = (((i + 1) % 2) == 0) ? + SkColor4f::FromColor(Color::Black) : + SkColor4f::FromColor(Color::Cyan_500); + + sk_sp<LinearGradientShader> gradient = sk_make_sp<LinearGradientShader>( + pts, + vColors, + SkColorSpace::MakeSRGB(), + pos, + SkTileMode::kClamp, + 0, + nullptr + ); + paint.setShader(gradient); canvas.drawRect(i, i, width, height, paint); } }); diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp index 6d4c57413f00..5e56b26f46f0 100644 --- a/libs/hwui/tests/unit/VectorDrawableTests.cpp +++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp @@ -17,9 +17,14 @@ #include <gtest/gtest.h> #include "PathParser.h" +#include "GraphicsJNI.h" +#include "SkGradientShader.h" +#include "SkShader.h" #include "VectorDrawable.h" #include "utils/MathUtils.h" #include "utils/VectorDrawableUtils.h" +#include <shader/Shader.h> +#include <shader/LinearGradientShader.h> #include <functional> @@ -395,7 +400,21 @@ TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) { bitmap.allocN32Pixels(5, 5, false); SkCanvas canvas(bitmap); - sk_sp<SkShader> shader = SkShaders::Color(SK_ColorBLACK); + SkPoint pts[2]; + pts[0].set(0, 0); + pts[1].set(0, 0); + + std::vector<SkColor4f> colors(2); + colors[0] = SkColors::kBlack; + colors[1] = SkColors::kBlack; + + sk_sp<LinearGradientShader> shader = sk_sp(new LinearGradientShader(pts, + colors, + SkColorSpace::MakeSRGB(), + nullptr, + SkTileMode::kClamp, + SkGradientShader::kInterpolateColorsInPremul_Flag, + nullptr)); // Initial ref count is 1 EXPECT_TRUE(shader->unique()); diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 6976a3569655..20006934ee46 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -523,7 +523,8 @@ public final class MediaSessionManager { * @param keyEvent The KeyEvent to send. * @hide */ - public void dispatchMediaKeyEventAsSystemService(KeyEvent keyEvent) { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void dispatchMediaKeyEventAsSystemService(@NonNull KeyEvent keyEvent) { dispatchMediaKeyEventInternal(true, keyEvent, false); } @@ -548,6 +549,7 @@ public final class MediaSessionManager { * @return {@code true} if the event was sent to the session, {@code false} otherwise * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public boolean dispatchMediaKeyEventAsSystemService(@NonNull MediaSession.Token sessionToken, @NonNull KeyEvent keyEvent) { if (sessionToken == null) { @@ -586,10 +588,15 @@ public final class MediaSessionManager { * Should be only called by the {@link com.android.internal.policy.PhoneWindow} or * {@link android.view.FallbackEventHandler} when the foreground activity didn't consume the key * from the hardware devices. + * <p> + * Valid stream types include {@link AudioManager.PublicStreamTypes} and + * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}. * - * @param keyEvent The KeyEvent to send. + * @param keyEvent volume key event + * @param streamType type of stream * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public void dispatchVolumeKeyEventAsSystemService(@NonNull KeyEvent keyEvent, int streamType) { dispatchVolumeKeyEventInternal(true, keyEvent, streamType, false); } @@ -614,6 +621,7 @@ public final class MediaSessionManager { * @param keyEvent volume key event * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public void dispatchVolumeKeyEventAsSystemService(@NonNull MediaSession.Token sessionToken, @NonNull KeyEvent keyEvent) { if (sessionToken == null) { diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index f9d0d14c7335..e90fbd4dead8 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -45137,7 +45137,7 @@ package android.telephony { method public long getNci(); method @IntRange(from=0, to=3279165) public int getNrarfcn(); method @IntRange(from=0, to=1007) public int getPci(); - method @IntRange(from=0, to=65535) public int getTac(); + method @IntRange(from=0, to=16777215) public int getTac(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR; } diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt index 617a83f05791..8892a2954afb 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/non-updatable-api/module-lib-current.txt @@ -46,6 +46,13 @@ package android.media.session { field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000 } + public final class MediaSessionManager { + method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent); + method public boolean dispatchMediaKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent); + method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int); + method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent); + } + } package android.os { diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index dbf9e9fb4ae5..3fd0ee1c8011 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -11037,6 +11037,7 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); + field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43 field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java index adc8b4d24cd8..290700fad147 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java @@ -22,7 +22,6 @@ import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME; import android.content.Context; import android.os.Handler; import android.os.PowerManager; -import android.view.IWindowManager; import com.android.keyguard.KeyguardViewController; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -40,8 +39,6 @@ import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerImpl; import com.android.systemui.doze.DozeHost; -import com.android.systemui.pip.phone.PipMenuActivity; -import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.power.EnhancedEstimates; @@ -68,11 +65,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.volume.VolumeDialogComponent; -import com.android.systemui.wm.DisplaySystemBarsController; -import com.android.wm.shell.common.DisplayController; -import com.android.wm.shell.common.DisplayImeController; -import com.android.wm.shell.common.SystemWindows; -import com.android.wm.shell.common.TransactionPool; +import com.android.systemui.wmshell.CarWMShellModule; import javax.inject.Named; @@ -83,7 +76,8 @@ import dagger.Provides; @Module( includes = { DividerModule.class, - QSModule.class + QSModule.class, + CarWMShellModule.class }) abstract class CarSystemUIModule { @@ -120,42 +114,6 @@ abstract class CarSystemUIModule { return new Recents(context, recentsImplementation, commandQueue); } - @SysUISingleton - @Provides - static TransactionPool provideTransactionPool() { - return new TransactionPool(); - } - - @SysUISingleton - @Provides - static DisplayController providerDisplayController(Context context, @Main Handler handler, - IWindowManager wmService) { - return new DisplayController(context, handler, wmService); - } - - @SysUISingleton - @Provides - static SystemWindows provideSystemWindows(DisplayController displayController, - IWindowManager wmService) { - return new SystemWindows(displayController, wmService); - } - - @SysUISingleton - @Provides - static DisplayImeController provideDisplayImeController(Context context, - IWindowManager wmService, DisplayController displayController, - @Main Handler mainHandler, TransactionPool transactionPool) { - return new DisplaySystemBarsController.Builder(context, wmService, displayController, - mainHandler, transactionPool).build(); - } - - @SysUISingleton - @PipMenuActivityClass - @Provides - static Class<?> providePipMenuActivityClass() { - return PipMenuActivity.class; - } - @Binds abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone); diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java new file mode 100644 index 000000000000..2324c3d59155 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 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.wmshell; + +import android.content.Context; +import android.os.Handler; +import android.view.IWindowManager; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.pip.phone.PipMenuActivity; +import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; +import com.android.systemui.wm.DisplaySystemBarsController; +import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.common.TransactionPool; + +import dagger.Module; +import dagger.Provides; + +/** Provides dependencies from {@link com.android.wm.shell} for CarSystemUI. */ +@Module(includes = WMShellBaseModule.class) +public class CarWMShellModule { + @SysUISingleton + @Provides + DisplayImeController provideDisplayImeController(Context context, + IWindowManager wmService, DisplayController displayController, + @Main Handler mainHandler, TransactionPool transactionPool) { + return new DisplaySystemBarsController.Builder(context, wmService, displayController, + mainHandler, transactionPool).build(); + } + + /** TODO(b/150319024): PipMenuActivity will move to a Window */ + @SysUISingleton + @PipMenuActivityClass + @Provides + Class<?> providePipMenuActivityClass() { + return PipMenuActivity.class; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index 9d06c8467e41..72a6074ff89c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -465,7 +465,16 @@ public class LocalMediaManager implements BluetoothCallback { synchronized (mMediaDevicesLock) { mMediaDevices.clear(); mMediaDevices.addAll(devices); - mMediaDevices.addAll(buildDisconnectedBluetoothDevice()); + // Add disconnected bluetooth devices only when phone output device is available. + for (MediaDevice device : devices) { + final int type = device.getDeviceType(); + if (type == MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE + || type == MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE + || type == MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE) { + mMediaDevices.addAll(buildDisconnectedBluetoothDevice()); + break; + } + } } final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice(); 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 a654fd47ea12..8e850b25159c 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 @@ -585,6 +585,7 @@ public class LocalMediaManagerTest { when(device1.getId()).thenReturn(TEST_DEVICE_ID_1); when(device2.getId()).thenReturn(TEST_DEVICE_ID_2); when(device3.getId()).thenReturn(TEST_DEVICE_ID_3); + when(device1.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE); when(mLocalMediaManager.mPhoneDevice.getId()).thenReturn("test_phone_id"); assertThat(mLocalMediaManager.mMediaDevices).hasSize(2); @@ -683,6 +684,7 @@ public class LocalMediaManagerTest { when(device1.getId()).thenReturn(TEST_DEVICE_ID_1); when(device2.getId()).thenReturn(TEST_DEVICE_ID_2); when(device3.getId()).thenReturn(TEST_DEVICE_ID_3); + when(device1.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE); when(mLocalMediaManager.mPhoneDevice.getId()).thenReturn("test_phone_id"); assertThat(mLocalMediaManager.mMediaDevices).hasSize(2); diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index bdf00e38ce94..bcd2ff71b57f 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -175,5 +175,6 @@ public class SecureSettings { Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, Settings.Secure.PANIC_GESTURE_ENABLED, Settings.Secure.PANIC_SOUND_ENABLED, + Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 4ea7f3a23c10..3630f257f583 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -263,5 +263,6 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.PANIC_GESTURE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.PANIC_SOUND_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ADAPTIVE_CONNECTIVITY_ENABLED, BOOLEAN_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 5c0662e2a8ee..66be8dd68283 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -773,29 +773,29 @@ class SettingsProtoDumpUtil { Settings.Global.GPU_DEBUG_LAYERS_GLES, GlobalSettingsProto.Gpu.DEBUG_LAYERS_GLES); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_ALL_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_ALL_APPS); + Settings.Global.UPDATABLE_DRIVER_ALL_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_ALL_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_OPT_IN_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_IN_APPS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_PRERELEASE_OPT_IN_APPS); + Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_OPT_OUT_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_OUT_APPS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_DENYLIST, - GlobalSettingsProto.Gpu.GAME_DRIVER_DENYLIST); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_DENYLIST); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_ALLOWLIST, - GlobalSettingsProto.Gpu.GAME_DRIVER_ALLOWLIST); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_DENYLISTS, - GlobalSettingsProto.Gpu.GAME_DRIVER_DENYLISTS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, - GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES); + Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_SPHAL_LIBRARIES); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); @@ -1976,6 +1976,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS); + dumpSetting(s, p, + Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED, + SecureSettingsProto.ADAPTIVE_CONNECTIVITY_ENABLED); final long controlsToken = p.start(SecureSettingsProto.CONTROLS); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 4bb8f45f331f..0ac3355c4952 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -504,14 +504,14 @@ public class SettingsBackupTest { Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST, - Settings.Global.GAME_DRIVER_ALL_APPS, - Settings.Global.GAME_DRIVER_OPT_IN_APPS, - Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, - Settings.Global.GAME_DRIVER_OPT_OUT_APPS, - Settings.Global.GAME_DRIVER_DENYLISTS, - Settings.Global.GAME_DRIVER_DENYLIST, - Settings.Global.GAME_DRIVER_ALLOWLIST, - Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, + Settings.Global.UPDATABLE_DRIVER_ALL_APPS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, + Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, + Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, Settings.Global.GPU_DEBUG_LAYER_APP, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 98d3553287d1..4ce9f5a9edc6 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -240,6 +240,8 @@ <!-- Listen app op changes --> <uses-permission android:name="android.permission.WATCH_APPOPS" /> <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" /> + <!-- For handling silent audio recordings --> + <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" /> <!-- to read and change hvac values in a car --> <uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" /> @@ -267,6 +269,7 @@ <!-- Permission to make accessibility service access Bubbles --> <uses-permission android:name="android.permission.ADD_TRUSTED_DISPLAY" /> + <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java index 0d960f0c21be..6c5c4ef94921 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java @@ -39,6 +39,10 @@ public interface StatusBarStateController { */ boolean isDozing(); + /** + * Is the status bar panel expanded. + */ + boolean isExpanded(); /** * Is device pulsing. @@ -113,5 +117,10 @@ public interface StatusBarStateController { * Callback to be notified when the pulsing state changes */ default void onPulsingChanged(boolean pulsing) {} + + /** + * Callback to be notified when the expanded state of the status bar changes + */ + default void onExpandedChanged(boolean isExpanded) {} } } diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index 887384d78f29..b42d71abaa6d 100644 --- a/packages/SystemUI/proguard.flags +++ b/packages/SystemUI/proguard.flags @@ -44,4 +44,5 @@ -keep class com.android.wm.shell.* -keep class com.android.systemui.dagger.GlobalRootComponent { *; } --keep class com.android.systemui.dagger.GlobalRootComponent$SysUIComponentImpl { *; }
\ No newline at end of file +-keep class com.android.systemui.dagger.GlobalRootComponent$SysUIComponentImpl { *; } +-keep class com.android.systemui.dagger.Dagger** { *; }
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml index 46396e3e62b4..4b3534b1cbc8 100644 --- a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml +++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml @@ -32,6 +32,7 @@ android:gravity="center"> <ImageView android:id="@+id/screenshot_action_chip_icon" + android:tint="@*android:color/accent_device_default" android:layout_width="@dimen/screenshot_action_chip_icon_size" android:layout_height="@dimen/screenshot_action_chip_icon_size" android:layout_marginStart="@dimen/screenshot_action_chip_padding_start" diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml index 732758a2ded2..31a33fbfc308 100644 --- a/packages/SystemUI/res/layout/udfps_view.xml +++ b/packages/SystemUI/res/layout/udfps_view.xml @@ -5,6 +5,6 @@ android:id="@+id/udfps_view" android:layout_width="match_parent" android:layout_height="match_parent" - systemui:sensorRadius="140px" - systemui:sensorMarginBottom="630px" + systemui:sensorRadius="130px" + systemui:sensorCenterY="1636px" systemui:sensorTouchAreaCoefficient="0.5"/> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 84dbd60b799d..a62502965dd2 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -159,7 +159,7 @@ <declare-styleable name="UdfpsView"> <attr name="sensorRadius" format="dimension"/> - <attr name="sensorMarginBottom" format="dimension"/> + <attr name="sensorCenterY" format="dimension"/> <attr name="sensorPressureCoefficient" format="float"/> <attr name="sensorTouchAreaCoefficient" format="float"/> </declare-styleable> diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index de47c68166ff..748a9c9448c5 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -78,7 +78,7 @@ import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment; import com.android.systemui.statusbar.notification.NotificationFilter; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 7023e477f4ed..f5c364947a2f 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -27,24 +27,15 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.bubbles.BubbleController; import com.android.systemui.dagger.DaggerGlobalRootComponent; import com.android.systemui.dagger.GlobalRootComponent; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.WMComponent; -import com.android.systemui.demomode.DemoModeController; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider; -import com.android.systemui.statusbar.NotificationListener; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.util.concurrent.Executor; @@ -151,19 +142,4 @@ public class SystemUIFactory { Dependency.get(KeyguardUpdateMonitor.class), bypassController, new Handler(Looper.getMainLooper())); } - - public NotificationIconAreaController createNotificationIconAreaController(Context context, - StatusBar statusBar, - NotificationWakeUpCoordinator wakeUpCoordinator, - KeyguardBypassController keyguardBypassController, - StatusBarStateController statusBarStateController, - DemoModeController demoModeController) { - return new NotificationIconAreaController(context, statusBar, statusBarStateController, - wakeUpCoordinator, keyguardBypassController, - Dependency.get(NotificationMediaManager.class), - Dependency.get(NotificationListener.class), - Dependency.get(DozeParameters.class), - Dependency.get(BubbleController.class), - demoModeController); - } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java index 36353fa96956..d7e91384f049 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java @@ -53,12 +53,10 @@ public class UdfpsView extends View implements DozeReceiver, private final Paint mScrimPaint; private final Paint mDebugTextPaint; - private float mSensorX; - private float mSensorY; private final RectF mSensorRect; private final Paint mSensorPaint; private final float mSensorRadius; - private final float mSensorMarginBottom; + private final float mSensorCenterY; private final float mSensorTouchAreaCoefficient; private final int mMaxBurnInOffsetX; private final int mMaxBurnInOffsetY; @@ -66,6 +64,10 @@ public class UdfpsView extends View implements DozeReceiver, private final Rect mTouchableRegion; private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener; + // This is calculated from the screen's dimensions at runtime, as opposed to mSensorCenterY, + // which is defined in layout.xml + private float mSensorCenterX; + // AOD anti-burn-in offsets private float mInterpolatedDarkAmount; private float mBurnInOffsetX; @@ -84,7 +86,7 @@ public class UdfpsView extends View implements DozeReceiver, if (!a.hasValue(R.styleable.UdfpsView_sensorRadius)) { throw new IllegalArgumentException("UdfpsView must contain sensorRadius"); } - if (!a.hasValue(R.styleable.UdfpsView_sensorMarginBottom)) { + if (!a.hasValue(R.styleable.UdfpsView_sensorCenterY)) { throw new IllegalArgumentException("UdfpsView must contain sensorMarginBottom"); } if (!a.hasValue(R.styleable.UdfpsView_sensorTouchAreaCoefficient)) { @@ -92,7 +94,7 @@ public class UdfpsView extends View implements DozeReceiver, "UdfpsView must contain sensorTouchAreaCoefficient"); } mSensorRadius = a.getDimension(R.styleable.UdfpsView_sensorRadius, 0f); - mSensorMarginBottom = a.getDimension(R.styleable.UdfpsView_sensorMarginBottom, 0f); + mSensorCenterY = a.getDimension(R.styleable.UdfpsView_sensorCenterY, 0f); mSensorTouchAreaCoefficient = a.getFloat( R.styleable.UdfpsView_sensorTouchAreaCoefficient, 0f); } finally { @@ -163,10 +165,9 @@ public class UdfpsView extends View implements DozeReceiver, final int h = getLayoutParams().height; final int w = getLayoutParams().width; mScrimRect.set(0 /* left */, 0 /* top */, w, h); - mSensorX = w / 2f; - mSensorY = h - mSensorMarginBottom - mSensorRadius; - mSensorRect.set(mSensorX - mSensorRadius, mSensorY - mSensorRadius, - mSensorX + mSensorRadius, mSensorY + mSensorRadius); + mSensorCenterX = w / 2f; + mSensorRect.set(mSensorCenterX - mSensorRadius, mSensorCenterY - mSensorRadius, + mSensorCenterX + mSensorRadius, mSensorCenterY + mSensorRadius); // Sets mTouchableRegion with rounded up values from mSensorRect. mSensorRect.roundOut(mTouchableRegion); @@ -210,10 +211,10 @@ public class UdfpsView extends View implements DozeReceiver, } boolean isValidTouch(float x, float y, float pressure) { - return x > (mSensorX - mSensorRadius * mSensorTouchAreaCoefficient) - && x < (mSensorX + mSensorRadius * mSensorTouchAreaCoefficient) - && y > (mSensorY - mSensorRadius * mSensorTouchAreaCoefficient) - && y < (mSensorY + mSensorRadius * mSensorTouchAreaCoefficient); + return x > (mSensorCenterX - mSensorRadius * mSensorTouchAreaCoefficient) + && x < (mSensorCenterX + mSensorRadius * mSensorTouchAreaCoefficient) + && y > (mSensorCenterY - mSensorRadius * mSensorTouchAreaCoefficient) + && y < (mSensorCenterY + mSensorRadius * mSensorTouchAreaCoefficient); } void setScrimAlpha(int alpha) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java index 43d7d7f22e6f..3b225d5313c1 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java @@ -62,7 +62,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; -import com.android.systemui.wmshell.WindowManagerShellModule; +import com.android.systemui.wmshell.WMShellModule; import javax.inject.Named; @@ -77,7 +77,7 @@ import dagger.Provides; @Module(includes = { DividerModule.class, QSModule.class, - WindowManagerShellModule.class + WMShellModule.class }) public abstract class SystemUIDefaultModule { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index b2e8cb04c739..a003d8365810 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -17,7 +17,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PageIndicator -import com.android.systemui.statusbar.notification.VisualStabilityManager +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.Utils import com.android.systemui.util.animation.UniqueObjectHostView @@ -155,6 +155,7 @@ class MediaCarouselController @Inject constructor( inflateSettingsButton() mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) configurationController.addCallback(configListener) + // TODO (b/162832756): remove visual stability manager when migrating to new pipeline visualStabilityCallback = VisualStabilityManager.Callback { if (needsReordering) { needsReordering = 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 e2aa09c862f3..facb3966f78c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -233,7 +233,10 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio @Override public void onAspectRatioChanged(float aspectRatio) { - mHandler.post(() -> mPipBoundsHandler.onAspectRatioChanged(aspectRatio)); + mHandler.post(() -> { + mPipBoundsHandler.onAspectRatioChanged(aspectRatio); + mTouchHandler.onAspectRatioChanged(); + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java index 9c42f8bff378..2800bb938149 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java @@ -364,6 +364,10 @@ public class PipResizeGestureHandler { mUserResizeBounds.set(bounds); } + void invalidateUserResizeBounds() { + mUserResizeBounds.setEmpty(); + } + Rect getUserResizeBounds() { return mUserResizeBounds; } 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 b20ea4e5c836..ecd315b336f2 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -426,8 +426,21 @@ public class PipTouchHandler { } } + /** + * Responds to IPinnedStackListener on resetting aspect ratio for the pinned window. + */ + public void onAspectRatioChanged() { + mPipResizeGestureHandler.invalidateUserResizeBounds(); + } + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect curBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) { + // Set the user resized bounds equal to the new normal bounds in case they were + // invalidated (e.g. by an aspect ratio change). + if (mPipResizeGestureHandler.getUserResizeBounds().isEmpty()) { + mPipResizeGestureHandler.setUserResizeBounds(normalBounds); + } + final int bottomOffset = mIsImeShowing ? mImeHeight : 0; final boolean fromDisplayRotationChanged = (mDisplayRotation != displayRotation); if (fromDisplayRotationChanged) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java index b5209bbbdd21..a48870240384 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java @@ -65,10 +65,10 @@ public class ScreenshotActionChip extends FrameLayout { } void setIcon(Icon icon, boolean tint) { - if (tint) { - icon.setTint(mIconColor); - } mIcon.setImageIcon(icon); + if (!tint) { + mIcon.setImageTintList(null); + } } void setText(CharSequence text) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index f272be477f51..1cd1b60ac1ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -21,7 +21,6 @@ import android.content.res.Resources; import android.os.Handler; import android.os.Trace; import android.os.UserHandle; -import android.service.notification.NotificationListenerService.Ranking; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -35,9 +34,9 @@ import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index e0352671e204..e9442499a8ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -103,6 +103,11 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll private boolean mIsDozing; /** + * If the status bar is currently expanded or not. + */ + private boolean mIsExpanded; + + /** * Current {@link #mDozeAmount} animator. */ private ValueAnimator mDarkAnimator; @@ -190,6 +195,26 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll } @Override + public boolean isExpanded() { + return mIsExpanded; + } + + @Override + public boolean setPanelExpanded(boolean expanded) { + if (mIsExpanded == expanded) { + return false; + } + mIsExpanded = expanded; + String tag = getClass().getSimpleName() + "#setIsExpanded"; + DejankUtils.startDetectingBlockingIpcs(tag); + for (RankedListener rl : new ArrayList<>(mListeners)) { + rl.mListener.onExpandedChanged(mIsExpanded); + } + DejankUtils.stopDetectingBlockingIpcs(tag); + return true; + } + + @Override public float getInterpolatedDozeAmount() { return mDozeInterpolator.getInterpolation(mDozeAmount); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java index 07b35502478f..9f8fe35dfbc9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java @@ -75,6 +75,14 @@ public interface SysuiStatusBarStateController extends StatusBarStateController */ void setDozeAmount(float dozeAmount, boolean animated); + + /** + * Update the expanded state from {@link StatusBar}'s perspective + * @param expanded are we expanded? + * @return {@code true} if the state changed, else {@code false} + */ + boolean setPanelExpanded(boolean expanded); + /** * Sets whether to leave status bar open when hiding keyguard */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index 5b073cec9764..44550b72e521 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -41,8 +41,8 @@ import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java index 19637bbd54df..9482c17a8769 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification; +import android.annotation.Nullable; import android.util.ArraySet; import com.android.systemui.dagger.SysUISingleton; @@ -36,11 +37,11 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac private final KeyguardStateController mKeyguardStateController; private final NotificationLockscreenUserManager mLockscreenUserManager; private final StatusBarStateController mStateController; - private ArraySet<Listener> mListeners = new ArraySet<>(); + private final ArraySet<Listener> mListeners = new ArraySet<>(); private boolean mLastDynamicUnlocked; private boolean mCacheInvalid; - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + @Nullable private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @Inject DynamicPrivacyController(NotificationLockscreenUserManager notificationLockscreenUserManager, @@ -96,8 +97,7 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac * contents aren't revealed yet? */ public boolean isInLockedDownShade() { - if (!mStatusBarKeyguardViewManager.isShowing() - || !mKeyguardStateController.isMethodSecure()) { + if (!isStatusBarKeyguardShowing() || !mKeyguardStateController.isMethodSecure()) { return false; } int state = mStateController.getState(); @@ -110,6 +110,10 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac return true; } + private boolean isStatusBarKeyguardShowing() { + return mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isShowing(); + } + public void setStatusBarKeyguardViewManager( StatusBarKeyguardViewManager statusBarKeyguardViewManager) { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; 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 e1ff872456eb..b5f1c7ff9b62 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index 54e545352e53..1326d920fe42 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -27,7 +27,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.NotificationIconAreaController import com.android.systemui.statusbar.phone.PanelExpansionListener import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener @@ -98,7 +97,6 @@ class NotificationWakeUpCoordinator @Inject constructor( } private var collapsedEnoughToHide: Boolean = false - lateinit var iconAreaController: NotificationIconAreaController var pulsing: Boolean = false set(value) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt index 57f8a6a3abef..17e62890aadd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt @@ -46,7 +46,14 @@ data class ListAttachState private constructor( /** * The [NotifPromoter] promoting this entry to top-level, if any. Always null for [GroupEntry]s. */ - var promoter: NotifPromoter? + var promoter: NotifPromoter?, + + /** + * If the [VisualStabilityManager] is suppressing group or section changes for this entry, + * suppressedChanges will contain the new parent or section that we would have assigned to + * the entry had it not been suppressed by the VisualStabilityManager. + */ + var suppressedChanges: SuppressedAttachState ) { /** Copies the state of another instance. */ @@ -56,6 +63,7 @@ data class ListAttachState private constructor( sectionIndex = other.sectionIndex excludingFilter = other.excludingFilter promoter = other.promoter + suppressedChanges.clone(other.suppressedChanges) } /** Resets back to a "clean" state (the same as created by the factory method) */ @@ -65,6 +73,7 @@ data class ListAttachState private constructor( sectionIndex = -1 excludingFilter = null promoter = null + suppressedChanges.reset() } companion object { @@ -75,7 +84,8 @@ data class ListAttachState private constructor( null, -1, null, - null) + null, + SuppressedAttachState.create()) } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java index 3a0520115d67..786c97d03712 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java @@ -167,6 +167,23 @@ public class ListDumper { .append(" "); } + if (notifEntry.getAttachState().getSuppressedChanges().getParent() != null) { + rksb.append("suppressedParent=") + .append(notifEntry.getAttachState().getSuppressedChanges() + .getParent().getKey()) + .append(" "); + } + + if (notifEntry.getAttachState().getSuppressedChanges().getSection() != null) { + rksb.append("suppressedSectionIndex=") + .append(notifEntry.getAttachState().getSuppressedChanges() + .getSectionIndex()) + .append(" sectionName=") + .append(notifEntry.getAttachState().getSuppressedChanges() + .getSection().getName()) + .append(" "); + } + if (hasBeenInteractedWith) { rksb.append("interacted=yes "); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java index 7d269177a961..05dd4df1f2ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java @@ -25,6 +25,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; @@ -161,6 +162,14 @@ public class NotifPipeline implements CommonNotifCollection { } /** + * StabilityManager that is used to determine whether to suppress group and section changes. + * This should only be set once. + */ + public void setVisualStabilityManager(NotifStabilityManager notifStabilityManager) { + mShadeListBuilder.setNotifStabilityManager(notifStabilityManager); + } + + /** * Comparators that are used to sort top-level entries that share the same section. The * comparators are executed in order until one of them returns a non-zero result. If all return * zero, the pipeline falls back to sorting by rank (and, failing that, Notification.when). diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index c3ed5b9d77fc..6cbebf803511 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.collection.listbuilder import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZE_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING; +import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUP_STABILIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_IDLE; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_GROUP_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_RESETTING; @@ -48,6 +49,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable; import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener; import com.android.systemui.util.Assert; @@ -90,6 +92,7 @@ public class ShadeListBuilder implements Dumpable { private final List<NotifFilter> mNotifFinalizeFilters = new ArrayList<>(); private final List<NotifComparator> mNotifComparators = new ArrayList<>(); private final List<NotifSection> mNotifSections = new ArrayList<>(); + @Nullable private NotifStabilityManager mNotifStabilityManager; private final List<OnBeforeTransformGroupsListener> mOnBeforeTransformGroupsListeners = new ArrayList<>(); @@ -109,7 +112,8 @@ public class ShadeListBuilder implements Dumpable { SystemClock systemClock, ShadeListBuilderLogger logger, DumpManager dumpManager, - NotificationInteractionTracker interactionTracker) { + NotificationInteractionTracker interactionTracker + ) { Assert.isMainThread(); mSystemClock = systemClock; mLogger = logger; @@ -200,6 +204,22 @@ public class ShadeListBuilder implements Dumpable { } } + void setNotifStabilityManager(NotifStabilityManager notifStabilityManager) { + Assert.isMainThread(); + mPipelineState.requireState(STATE_IDLE); + + if (mNotifStabilityManager != null) { + throw new IllegalStateException( + "Attempting to set the NotifStabilityManager more than once. There should " + + "only be one visual stability manager. Manager is being set by " + + mNotifStabilityManager.getName() + " and " + + notifStabilityManager.getName()); + } + + mNotifStabilityManager = notifStabilityManager; + mNotifStabilityManager.setInvalidationListener(this::onReorderingAllowedInvalidated); + } + void setComparators(List<NotifComparator> comparators) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); @@ -237,6 +257,16 @@ public class ShadeListBuilder implements Dumpable { rebuildListIfBefore(STATE_PRE_GROUP_FILTERING); } + private void onReorderingAllowedInvalidated(NotifStabilityManager stabilityManager) { + Assert.isMainThread(); + + mLogger.logReorderingAllowedInvalidated( + stabilityManager.getName(), + mPipelineState.getState()); + + rebuildListIfBefore(STATE_GROUPING); + } + private void onPromoterInvalidated(NotifPromoter promoter) { Assert.isMainThread(); @@ -285,6 +315,7 @@ public class ShadeListBuilder implements Dumpable { // Step 1: Reset notification states mPipelineState.incrementTo(STATE_RESETTING); resetNotifs(); + onBeginRun(); // Step 2: Filter out any notifications that shouldn't be shown right now mPipelineState.incrementTo(STATE_PRE_GROUP_FILTERING); @@ -303,6 +334,10 @@ public class ShadeListBuilder implements Dumpable { promoteNotifs(mNotifList); pruneIncompleteGroups(mNotifList); + // Step 4.5: Reassign/revert any groups to maintain visual stability + mPipelineState.incrementTo(STATE_GROUP_STABILIZING); + stabilizeGroupingNotifs(mNotifList); + // Step 5: Sort // Assign each top-level entry a section, then sort the list by section and then within // section by our list of custom comparators @@ -472,6 +507,28 @@ public class ShadeListBuilder implements Dumpable { } } + private void stabilizeGroupingNotifs(List<ListEntry> list) { + if (mNotifStabilityManager == null) { + return; + } + + for (int i = 0; i < list.size(); i++) { + final ListEntry tle = list.get(i); + if (tle.getPreviousAttachState().getParent() == null) { + continue; // new entries are allowed + } + + final GroupEntry prevParent = tle.getPreviousAttachState().getParent(); + final GroupEntry assignedParent = tle.getParent(); + if (prevParent != assignedParent) { + if (!mNotifStabilityManager.isGroupChangeAllowed(tle.getRepresentativeEntry())) { + tle.getAttachState().getSuppressedChanges().setParent(assignedParent); + tle.setParent(prevParent); + } + } + } + } + private void promoteNotifs(List<ListEntry> list) { for (int i = 0; i < list.size(); i++) { final ListEntry tle = list.get(i); @@ -650,9 +707,18 @@ public class ShadeListBuilder implements Dumpable { mLogger.logParentChanged(mIterationCount, prev.getParent(), curr.getParent()); } + if (curr.getSuppressedChanges().getParent() != null) { + mLogger.logParentChangeSuppressed( + mIterationCount, + curr.getSuppressedChanges().getParent(), + curr.getParent()); + } + if (curr.getExcludingFilter() != prev.getExcludingFilter()) { mLogger.logFilterChanged( - mIterationCount, prev.getExcludingFilter(), curr.getExcludingFilter()); + mIterationCount, + prev.getExcludingFilter(), + curr.getExcludingFilter()); } // When something gets detached, its promoter and section are always set to null, so @@ -661,7 +727,9 @@ public class ShadeListBuilder implements Dumpable { if (!wasDetached && curr.getPromoter() != prev.getPromoter()) { mLogger.logPromoterChanged( - mIterationCount, prev.getPromoter(), curr.getPromoter()); + mIterationCount, + prev.getPromoter(), + curr.getPromoter()); } if (!wasDetached && curr.getSection() != prev.getSection()) { @@ -672,6 +740,20 @@ public class ShadeListBuilder implements Dumpable { curr.getSection(), curr.getSectionIndex()); } + + if (curr.getSuppressedChanges().getSection() != null) { + mLogger.logSectionChangeSuppressed( + mIterationCount, + curr.getSuppressedChanges().getSection(), + curr.getSuppressedChanges().getSectionIndex(), + curr.getSection()); + } + } + } + + private void onBeginRun() { + if (mNotifStabilityManager != null) { + mNotifStabilityManager.onBeginRun(); } } @@ -681,6 +763,10 @@ public class ShadeListBuilder implements Dumpable { callOnCleanup(mNotifFinalizeFilters); callOnCleanup(mNotifComparators); callOnCleanup(mNotifSections); + + if (mNotifStabilityManager != null) { + callOnCleanup(List.of(mNotifStabilityManager)); + } } private void callOnCleanup(List<? extends Pluggable<?>> pluggables) { @@ -770,12 +856,32 @@ public class ShadeListBuilder implements Dumpable { } private Pair<NotifSection, Integer> applySections(ListEntry entry) { - final Pair<NotifSection, Integer> sectionWithIndex = findSection(entry); - final NotifSection section = sectionWithIndex.first; - final Integer sectionIndex = sectionWithIndex.second; + Pair<NotifSection, Integer> sectionWithIndex = findSection(entry); + final ListAttachState prevAttachState = entry.getPreviousAttachState(); + + // are we changing sections of this entry? + if (mNotifStabilityManager != null + && prevAttachState.getParent() != null + && (sectionWithIndex.first != prevAttachState.getSection() + || sectionWithIndex.second != prevAttachState.getSectionIndex())) { + + // are section changes allowed? + if (!mNotifStabilityManager.isSectionChangeAllowed( + entry.getRepresentativeEntry())) { + entry.getAttachState().getSuppressedChanges().setSection( + sectionWithIndex.first); + entry.getAttachState().getSuppressedChanges().setSectionIndex( + sectionWithIndex.second); + + // keep the previous section + sectionWithIndex = new Pair( + prevAttachState.getSection(), + prevAttachState.getSectionIndex()); + } + } - entry.getAttachState().setSection(section); - entry.getAttachState().setSectionIndex(sectionIndex); + entry.getAttachState().setSection(sectionWithIndex.first); + entry.getAttachState().setSectionIndex(sectionWithIndex.second); return sectionWithIndex; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt new file mode 100644 index 000000000000..52612365712e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 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.notification.collection + +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection + +/** + * Stores the suppressed state that [ShadeListBuilder] assigned to this [ListEntry] before the + * VisualStabilityManager suppressed group and section changes. + */ +data class SuppressedAttachState private constructor( + /** + * Null if not attached to the current shade list. If top-level, then the shade list root. If + * part of a group, then that group's GroupEntry. + */ + var parent: GroupEntry?, + + /** + * The assigned section for this ListEntry. If the child of the group, this will be the + * parent's section. Null if not attached to the list. + */ + var section: NotifSection?, + var sectionIndex: Int +) { + + /** Copies the state of another instance. */ + fun clone(other: SuppressedAttachState) { + parent = other.parent + section = other.section + sectionIndex = other.sectionIndex + } + + /** Resets back to a "clean" state (the same as created by the factory method) */ + fun reset() { + parent = null + section = null + sectionIndex = -1 + } + + companion object { + @JvmStatic + fun create(): SuppressedAttachState { + return SuppressedAttachState( + null, + null, + -1) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java index f2444d5f1cb3..87ca717982f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java @@ -42,6 +42,7 @@ public class NotifCoordinators implements Dumpable { private static final String TAG = "NotifCoordinators"; private final List<Coordinator> mCoordinators = new ArrayList<>(); private final List<NotifSection> mOrderedSections = new ArrayList<>(); + /** * Creates all the coordinators. */ @@ -58,7 +59,8 @@ public class NotifCoordinators implements Dumpable { HeadsUpCoordinator headsUpCoordinator, ConversationCoordinator conversationCoordinator, PreparationCoordinator preparationCoordinator, - MediaCoordinator mediaCoordinator) { + MediaCoordinator mediaCoordinator, + VisualStabilityCoordinator visualStabilityCoordinator) { dumpManager.registerDumpable(TAG, this); mCoordinators.add(new HideLocallyDismissedNotifsCoordinator()); @@ -70,6 +72,7 @@ public class NotifCoordinators implements Dumpable { mCoordinators.add(bubbleCoordinator); mCoordinators.add(mediaCoordinator); mCoordinators.add(conversationCoordinator); + mCoordinators.add(visualStabilityCoordinator); if (featureFlags.isNewNotifPipelineRenderingEnabled()) { mCoordinators.add(headsUpCoordinator); mCoordinators.add(preparationCoordinator); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java new file mode 100644 index 000000000000..08030f8201a2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2020 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.notification.collection.coordinator; + +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; + +import android.annotation.NonNull; + +import androidx.annotation.VisibleForTesting; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.NotificationViewHierarchyManager; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +/** + * Ensures that notifications are visually stable if the user is looking at the notifications. + * Group and section changes are re-allowed when the notification entries are no longer being + * viewed. + * + * Previously this was implemented in the view-layer {@link NotificationViewHierarchyManager} by + * {@link com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager}. + * This is now integrated in the data-layer via + * {@link com.android.systemui.statusbar.notification.collection.ShadeListBuilder}. + */ +@SysUISingleton +public class VisualStabilityCoordinator implements Coordinator { + private final DelayableExecutor mDelayableExecutor; + private final WakefulnessLifecycle mWakefulnessLifecycle; + private final StatusBarStateController mStatusBarStateController; + private final HeadsUpManager mHeadsUpManager; + + private boolean mScreenOn; + private boolean mPanelExpanded; + private boolean mPulsing; + + private boolean mReorderingAllowed; + private boolean mIsSuppressingGroupChange = false; + private final Set<String> mEntriesWithSuppressedSectionChange = new HashSet<>(); + + // key: notification key that can temporarily change its section + // value: runnable that when run removes its associated RemoveOverrideSuppressionRunnable + // from the DelayableExecutor's queue + private Map<String, Runnable> mEntriesThatCanChangeSection = new HashMap<>(); + + @VisibleForTesting + protected static final long ALLOW_SECTION_CHANGE_TIMEOUT = 500; + + @Inject + public VisualStabilityCoordinator( + HeadsUpManager headsUpManager, + WakefulnessLifecycle wakefulnessLifecycle, + StatusBarStateController statusBarStateController, + DelayableExecutor delayableExecutor + ) { + mHeadsUpManager = headsUpManager; + mWakefulnessLifecycle = wakefulnessLifecycle; + mStatusBarStateController = statusBarStateController; + mDelayableExecutor = delayableExecutor; + } + + @Override + public void attach(NotifPipeline pipeline) { + mWakefulnessLifecycle.addObserver(mWakefulnessObserver); + mScreenOn = mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING; + + mStatusBarStateController.addCallback(mStatusBarStateControllerListener); + mPulsing = mStatusBarStateController.isPulsing(); + + pipeline.setVisualStabilityManager(mNotifStabilityManager); + } + + private final NotifStabilityManager mNotifStabilityManager = + new NotifStabilityManager("VisualStabilityCoordinator") { + @Override + public void onBeginRun() { + mIsSuppressingGroupChange = false; + mEntriesWithSuppressedSectionChange.clear(); + } + + @Override + public boolean isGroupChangeAllowed(NotificationEntry entry) { + final boolean isGroupChangeAllowedForEntry = + mReorderingAllowed || mHeadsUpManager.isAlerting(entry.getKey()); + mIsSuppressingGroupChange |= isGroupChangeAllowedForEntry; + return isGroupChangeAllowedForEntry; + } + + @Override + public boolean isSectionChangeAllowed(NotificationEntry entry) { + final boolean isSectionChangeAllowedForEntry = + mReorderingAllowed + || mHeadsUpManager.isAlerting(entry.getKey()) + || mEntriesThatCanChangeSection.containsKey(entry.getKey()); + if (isSectionChangeAllowedForEntry) { + mEntriesWithSuppressedSectionChange.add(entry.getKey()); + } + return isSectionChangeAllowedForEntry; + } + }; + + private void updateAllowedStates() { + mReorderingAllowed = isReorderingAllowed(); + if (mReorderingAllowed && (mIsSuppressingGroupChange || isSuppressingSectionChange())) { + mNotifStabilityManager.invalidateList(); + } + } + + private boolean isSuppressingSectionChange() { + return !mEntriesWithSuppressedSectionChange.isEmpty(); + } + + private boolean isReorderingAllowed() { + return (!mScreenOn || !mPanelExpanded) && !mPulsing; + } + + /** + * Allows this notification entry to be re-ordered in the notification list temporarily until + * the timeout has passed. + * + * Typically this is allowed because the user has directly changed something about the + * notification and we are reordering based on the user's change. + * + * @param entry notification entry that can change sections even if isReorderingAllowed is false + * @param now current time SystemClock.uptimeMillis + */ + public void temporarilyAllowSectionChanges(@NonNull NotificationEntry entry, long now) { + final String entryKey = entry.getKey(); + final boolean wasSectionChangeAllowed = + mNotifStabilityManager.isSectionChangeAllowed(entry); + + // If it exists, cancel previous timeout + if (mEntriesThatCanChangeSection.containsKey(entryKey)) { + mEntriesThatCanChangeSection.get(entryKey).run(); + } + + // Schedule & store new timeout cancellable + mEntriesThatCanChangeSection.put( + entryKey, + mDelayableExecutor.executeAtTime( + () -> mEntriesThatCanChangeSection.remove(entryKey), + now + ALLOW_SECTION_CHANGE_TIMEOUT)); + + if (!wasSectionChangeAllowed) { + mNotifStabilityManager.invalidateList(); + } + } + + final StatusBarStateController.StateListener mStatusBarStateControllerListener = + new StatusBarStateController.StateListener() { + @Override + public void onPulsingChanged(boolean pulsing) { + mPulsing = pulsing; + updateAllowedStates(); + } + + @Override + public void onExpandedChanged(boolean expanded) { + mPanelExpanded = expanded; + updateAllowedStates(); + } + }; + + final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedGoingToSleep() { + mScreenOn = false; + updateAllowedStates(); + } + + @Override + public void onStartedWakingUp() { + mScreenOn = true; + updateAllowedStates(); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java index 36adf9b87674..19a356b89f18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; +import android.os.SystemClock; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationStats; @@ -26,35 +27,43 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpManager; /** - * Callback used when a user: - * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. - * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. - * {@see StatusBarNotificationActivityStarter} + * Callback for when a user interacts with a {@see ExpandableNotificationRow}. Sends relevant + * information about the interaction to the notification pipeline. */ -public class OnDismissCallbackImpl implements OnDismissCallback { +public class OnUserInteractionCallbackImpl implements OnUserInteractionCallback { private final NotifPipeline mNotifPipeline; private final NotifCollection mNotifCollection; private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; + private final VisualStabilityCoordinator mVisualStabilityCoordinator; - public OnDismissCallbackImpl( + public OnUserInteractionCallbackImpl( NotifPipeline notifPipeline, NotifCollection notifCollection, HeadsUpManager headsUpManager, - StatusBarStateController statusBarStateController + StatusBarStateController statusBarStateController, + VisualStabilityCoordinator visualStabilityCoordinator ) { mNotifPipeline = notifPipeline; mNotifCollection = notifCollection; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; + mVisualStabilityCoordinator = visualStabilityCoordinator; } + /** + * Callback triggered when a user: + * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. + * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. + * {@see StatusBarNotificationActivityStarter} + */ @Override public void onDismiss( NotificationEntry entry, @@ -80,4 +89,11 @@ public class OnDismissCallbackImpl implements OnDismissCallback { NotificationLogger.getNotificationLocation(entry))) ); } + + @Override + public void onImportanceChanged(NotificationEntry entry) { + mVisualStabilityCoordinator.temporarilyAllowSectionChanges( + entry, + SystemClock.uptimeMillis()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java index 94ffa8f8c5ed..cce8cdc64d30 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java @@ -27,30 +27,36 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpManager; /** - * Callback used when a user: - * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. - * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. - * {@see StatusBarNotificationActivityStarter} + * Callback for when a user interacts with a {@see ExpandableNotificationRow}. */ -public class OnDismissCallbackImpl implements OnDismissCallback { +public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCallback { private final NotificationEntryManager mNotificationEntryManager; private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; + private final VisualStabilityManager mVisualStabilityManager; - public OnDismissCallbackImpl( + public OnUserInteractionCallbackImplLegacy( NotificationEntryManager notificationEntryManager, HeadsUpManager headsUpManager, - StatusBarStateController statusBarStateController + StatusBarStateController statusBarStateController, + VisualStabilityManager visualStabilityManager ) { mNotificationEntryManager = notificationEntryManager; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; + mVisualStabilityManager = visualStabilityManager; } + /** + * Callback triggered when a user: + * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. + * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. + * {@see StatusBarNotificationActivityStarter} + */ @Override public void onDismiss( NotificationEntry entry, @@ -77,5 +83,10 @@ public class OnDismissCallbackImpl implements OnDismissCallback { cancellationReason ); } + + @Override + public void onImportanceChanged(NotificationEntry entry) { + mVisualStabilityManager.temporarilyAllowReordering(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java index 8341c02b6b63..165df30b457d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java @@ -11,10 +11,10 @@ * 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 + * limitations under the License. */ -package com.android.systemui.statusbar.notification; +package com.android.systemui.statusbar.notification.collection.legacy; import android.os.Handler; import android.os.SystemClock; @@ -24,7 +24,11 @@ import androidx.collection.ArraySet; import com.android.systemui.Dumpable; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.NotificationEntryListener; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.VisibilityLocationProvider; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -65,24 +69,44 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl */ public VisualStabilityManager( NotificationEntryManager notificationEntryManager, - @Main Handler handler) { + @Main Handler handler, + StatusBarStateController statusBarStateController, + WakefulnessLifecycle wakefulnessLifecycle) { mHandler = handler; - notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { - @Override - public void onPreEntryUpdated(NotificationEntry entry) { - final boolean ambientStateHasChanged = - entry.isAmbient() != entry.getRow().isLowPriority(); - if (ambientStateHasChanged) { - // note: entries are removed in onReorderingFinished - mLowPriorityReorderingViews.add(entry); + if (notificationEntryManager != null) { + notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { + @Override + public void onPreEntryUpdated(NotificationEntry entry) { + final boolean ambientStateHasChanged = + entry.isAmbient() != entry.getRow().isLowPriority(); + if (ambientStateHasChanged) { + // note: entries are removed in onReorderingFinished + mLowPriorityReorderingViews.add(entry); + } } - } - }); - } + }); + } + + if (statusBarStateController != null) { + setPulsing(statusBarStateController.isPulsing()); + statusBarStateController.addCallback(new StatusBarStateController.StateListener() { + @Override + public void onPulsingChanged(boolean pulsing) { + setPulsing(pulsing); + } + + @Override + public void onExpandedChanged(boolean expanded) { + setPanelExpanded(expanded); + } + }); + } - public void setUpWithPresenter(NotificationPresenter presenter) { + if (wakefulnessLifecycle != null) { + wakefulnessLifecycle.addObserver(mWakefulnessObserver); + } } /** @@ -120,25 +144,25 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl } /** - * Set the panel to be expanded. + * @param screenOn whether the screen is on */ - public void setPanelExpanded(boolean expanded) { - mPanelExpanded = expanded; + private void setScreenOn(boolean screenOn) { + mScreenOn = screenOn; updateAllowedStates(); } /** - * @param screenOn whether the screen is on + * Set the panel to be expanded. */ - public void setScreenOn(boolean screenOn) { - mScreenOn = screenOn; + private void setPanelExpanded(boolean expanded) { + mPanelExpanded = expanded; updateAllowedStates(); } /** * @param pulsing whether we are currently pulsing for ambient display. */ - public void setPulsing(boolean pulsing) { + private void setPulsing(boolean pulsing) { if (mPulsing == pulsing) { return; } @@ -215,6 +239,10 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl mVisibilityLocationProvider = visibilityLocationProvider; } + /** + * Notifications have been reordered, so reset all the allowed list of views that are allowed + * to reorder. + */ public void onReorderingFinished() { mAllowedReorderViews.clear(); mAddedChildren.clear(); @@ -271,11 +299,27 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl pw.println(); } + final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedGoingToSleep() { + setScreenOn(false); + } + + @Override + public void onStartedWakingUp() { + setScreenOn(true); + } + }; + + + /** + * See {@link Callback#onChangeAllowed()} + */ public interface Callback { + /** * Called when changing is allowed again. */ void onChangeAllowed(); } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java index f1f7d632b6f8..798bfe7f39d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java @@ -81,9 +81,10 @@ public class PipelineState { public static final int STATE_PRE_GROUP_FILTERING = 3; public static final int STATE_GROUPING = 4; public static final int STATE_TRANSFORMING = 5; - public static final int STATE_SORTING = 6; - public static final int STATE_FINALIZE_FILTERING = 7; - public static final int STATE_FINALIZING = 8; + public static final int STATE_GROUP_STABILIZING = 6; + public static final int STATE_SORTING = 7; + public static final int STATE_FINALIZE_FILTERING = 8; + public static final int STATE_FINALIZING = 9; @IntDef(prefix = { "STATE_" }, value = { STATE_IDLE, @@ -92,6 +93,7 @@ public class PipelineState { STATE_PRE_GROUP_FILTERING, STATE_GROUPING, STATE_TRANSFORMING, + STATE_GROUP_STABILIZING, STATE_SORTING, STATE_FINALIZE_FILTERING, STATE_FINALIZING, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt index 67f8bfeaf141..f7bfeb7234f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt @@ -57,6 +57,15 @@ class ShadeListBuilderLogger @Inject constructor( }) } + fun logReorderingAllowedInvalidated(name: String, pipelineState: Int) { + buffer.log(TAG, DEBUG, { + str1 = name + int1 = pipelineState + }, { + """ReorderingNowAllowed "$str1" invalidated; pipeline state is $int1""" + }) + } + fun logPromoterInvalidated(name: String, pipelineState: Int) { buffer.log(TAG, DEBUG, { str1 = name @@ -156,6 +165,21 @@ class ShadeListBuilderLogger @Inject constructor( }) } + fun logParentChangeSuppressed( + buildId: Int, + suppressedParent: GroupEntry?, + keepingParent: GroupEntry? + ) { + buffer.log(TAG, INFO, { + int1 = buildId + str1 = suppressedParent?.key + str2 = keepingParent?.key + }, { + "(Build $long1) Change of parent to '$str1' suppressed; " + + "keeping parent '$str2'" + }) + } + fun logFilterChanged( buildId: Int, prevFilter: NotifFilter?, @@ -206,6 +230,23 @@ class ShadeListBuilderLogger @Inject constructor( }) } + fun logSectionChangeSuppressed( + buildId: Int, + suppressedSection: NotifSection?, + suppressedSectionIndex: Int, + assignedSection: NotifSection? + ) { + buffer.log(TAG, INFO, { + long1 = buildId.toLong() + str1 = suppressedSection?.name + int1 = suppressedSectionIndex + str2 = assignedSection?.name + }, { + "(Build $long1) Section change suppressed: '$str1' (#$int1). " + + "Keeping section: '$str2'" + }) + } + fun logFinalList(entries: List<ListEntry>) { if (entries.isEmpty()) { buffer.log(TAG, DEBUG, {}, { "(empty list)" }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.java new file mode 100644 index 000000000000..58d4b97f69b5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 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.notification.collection.listbuilder.pluggable; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +/** + * Pluggable for participating in notif stabilization. In particular, suppressing group and + * section changes. + * + * The stability manager should be invalidated when previously suppressed a group or + * section change is now allowed. + */ +public abstract class NotifStabilityManager extends Pluggable<NotifStabilityManager> { + + protected NotifStabilityManager(String name) { + super(name); + } + + /** + * Called at the beginning of every pipeline run to perform any necessary cleanup from the + * previous run. + */ + public abstract void onBeginRun(); + + /** + * Returns whether this notification can currently change groups/parents. + * Per iteration of the notification pipeline, locally stores this information until the next + * run of the pipeline. When this method returns true, it's expected that a group change for + * this entry is being suppressed. + */ + public abstract boolean isGroupChangeAllowed(NotificationEntry entry); + + /** + * Returns whether this notification entry can currently change sections. + * Per iteration of the notification pipeline, locally stores this information until the next + * run of the pipeline. When this method returns true, it's expected that a section change is + * being suppressed. + */ + public abstract boolean isSectionChangeAllowed(NotificationEntry entry); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 201be59d80b4..118ff4a9fbb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -21,6 +21,7 @@ import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.ShadeListBuilder import com.android.systemui.statusbar.notification.stack.NotificationListContainer +import com.android.systemui.statusbar.phone.NotificationIconAreaController import java.lang.RuntimeException import javax.inject.Inject @@ -31,7 +32,8 @@ import javax.inject.Inject class ShadeViewManager constructor( listContainer: NotificationListContainer, logger: ShadeViewDifferLogger, - private val viewBarn: NotifViewBarn + private val viewBarn: NotifViewBarn, + private val notificationIconAreaController: NotificationIconAreaController ) { private val rootController = RootNodeController(listContainer) private val viewDiffer = ShadeViewDiffer(rootController, logger) @@ -52,6 +54,7 @@ class ShadeViewManager constructor( root.children.add(buildNotifNode(entry, root)) } + notificationIconAreaController.updateNotificationIcons(notifList) return root } @@ -80,9 +83,10 @@ class ShadeViewManager constructor( class ShadeViewManagerFactory @Inject constructor( private val logger: ShadeViewDifferLogger, - private val viewBarn: NotifViewBarn + private val viewBarn: NotifViewBarn, + private val notificationIconAreaController: NotificationIconAreaController ) { fun create(listContainer: NotificationListContainer): ShadeViewManager { - return ShadeViewManager(listContainer, logger, viewBarn) + return ShadeViewManager(listContainer, logger, viewBarn, notificationIconAreaController) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index 0573156b4804..6d01324f1b7b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -32,6 +32,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.settings.CurrentUserContextTracker; import com.android.systemui.statusbar.FeatureFlags; @@ -41,14 +42,16 @@ import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; +import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; -import com.android.systemui.statusbar.notification.collection.inflation.OnDismissCallbackImpl; +import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl; +import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.init.NotificationsController; @@ -62,7 +65,7 @@ import com.android.systemui.statusbar.notification.logging.NotificationPanelLogg import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; @@ -115,7 +118,6 @@ public interface NotificationsModule { @Provides static NotificationGutsManager provideNotificationGutsManager( Context context, - VisualStabilityManager visualStabilityManager, Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler, @Background Handler bgHandler, @@ -129,10 +131,10 @@ public interface NotificationsModule { Provider<PriorityOnboardingDialogController.Builder> builderProvider, AssistantFeedbackController assistantFeedbackController, BubbleController bubbleController, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, + OnUserInteractionCallback onUserInteractionCallback) { return new NotificationGutsManager( context, - visualStabilityManager, statusBarLazy, mainHandler, bgHandler, @@ -146,15 +148,24 @@ public interface NotificationsModule { builderProvider, assistantFeedbackController, bubbleController, - uiEventLogger); + uiEventLogger, + onUserInteractionCallback); } /** Provides an instance of {@link VisualStabilityManager} */ @SysUISingleton @Provides static VisualStabilityManager provideVisualStabilityManager( - NotificationEntryManager notificationEntryManager, Handler handler) { - return new VisualStabilityManager(notificationEntryManager, handler); + FeatureFlags featureFlags, + NotificationEntryManager notificationEntryManager, + Handler handler, + StatusBarStateController statusBarStateController, + WakefulnessLifecycle wakefulnessLifecycle) { + return new VisualStabilityManager( + notificationEntryManager, + handler, + statusBarStateController, + wakefulnessLifecycle); } /** Provides an instance of {@link NotificationLogger} */ @@ -227,20 +238,27 @@ public interface NotificationsModule { */ @Provides @SysUISingleton - static OnDismissCallback provideOnDismissCallback( + static OnUserInteractionCallback provideOnUserInteractionCallback( FeatureFlags featureFlags, HeadsUpManager headsUpManager, StatusBarStateController statusBarStateController, Lazy<NotifPipeline> pipeline, Lazy<NotifCollection> notifCollection, - NotificationEntryManager entryManager) { + Lazy<VisualStabilityCoordinator> visualStabilityCoordinator, + NotificationEntryManager entryManager, + VisualStabilityManager visualStabilityManager) { return featureFlags.isNewNotifPipelineRenderingEnabled() - ? new OnDismissCallbackImpl( - pipeline.get(), notifCollection.get(), headsUpManager, - statusBarStateController) - : new com.android.systemui.statusbar.notification.collection - .legacy.OnDismissCallbackImpl( - entryManager, headsUpManager, statusBarStateController); + ? new OnUserInteractionCallbackImpl( + pipeline.get(), + notifCollection.get(), + headsUpManager, + statusBarStateController, + visualStabilityCoordinator.get()) + : new OnUserInteractionCallbackImplLegacy( + entryManager, + headsUpManager, + statusBarStateController, + visualStabilityManager); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java index dbdb42204867..4d56e6013d71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java @@ -29,8 +29,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index d7fa54f0091d..9c09cba5e137 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -84,8 +84,8 @@ import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.NotificationUtils; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationCounters; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; @@ -323,7 +323,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private View mGroupParentWhenDismissed; private boolean mShelfIconVisible; private boolean mAboveShelf; - private OnDismissCallback mOnDismissCallback; + private OnUserInteractionCallback mOnUserInteractionCallback; private boolean mIsLowPriority; private boolean mIsColorized; private boolean mUseIncreasedCollapsedHeight; @@ -1445,8 +1445,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } dismiss(fromAccessibility); if (mEntry.isClearable()) { - if (mOnDismissCallback != null) { - mOnDismissCallback.onDismiss(mEntry, REASON_CANCEL); + if (mOnUserInteractionCallback != null) { + mOnUserInteractionCallback.onDismiss(mEntry, REASON_CANCEL); } } } @@ -1463,10 +1463,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mIsBlockingHelperShowing && mNotificationTranslationFinished; } - void setOnDismissCallback(OnDismissCallback onDismissCallback) { - mOnDismissCallback = onDismissCallback; - } - @Override public View getShelfTransformationTarget() { if (mIsSummaryWithChildren && !shouldShowPublic()) { @@ -1600,7 +1596,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView CoordinateOnClickListener onFeedbackClickListener, FalsingManager falsingManager, StatusBarStateController statusBarStateController, - PeopleNotificationIdentifier peopleNotificationIdentifier) { + PeopleNotificationIdentifier peopleNotificationIdentifier, + OnUserInteractionCallback onUserInteractionCallback) { mAppName = appName; if (mMenuRow == null) { mMenuRow = new NotificationMenuRow(mContext, peopleNotificationIdentifier); @@ -1624,6 +1621,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView for (NotificationContentView l : mLayouts) { l.setPeopleNotificationIdentifier(mPeopleNotificationIdentifier); } + mOnUserInteractionCallback = onUserInteractionCallback; } private void initDimens() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index 690dce915cf3..f8bc2bebf93b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -71,7 +71,7 @@ public class ExpandableNotificationRowController implements NodeController { this::logNotificationExpansion; private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener; private final NotificationGutsManager mNotificationGutsManager; - private final OnDismissCallback mOnDismissCallback; + private final OnUserInteractionCallback mOnUserInteractionCallback; private final FalsingManager mFalsingManager; private final boolean mAllowLongPress; private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; @@ -90,7 +90,7 @@ public class ExpandableNotificationRowController implements NodeController { StatusBarStateController statusBarStateController, NotificationGutsManager notificationGutsManager, @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, - OnDismissCallback onDismissCallback, FalsingManager falsingManager, + OnUserInteractionCallback onUserInteractionCallback, FalsingManager falsingManager, PeopleNotificationIdentifier peopleNotificationIdentifier) { mView = view; mListContainer = listContainer; @@ -108,7 +108,7 @@ public class ExpandableNotificationRowController implements NodeController { mOnExpandClickListener = onExpandClickListener; mStatusBarStateController = statusBarStateController; mNotificationGutsManager = notificationGutsManager; - mOnDismissCallback = onDismissCallback; + mOnUserInteractionCallback = onUserInteractionCallback; mOnFeedbackClickListener = mNotificationGutsManager::openGuts; mAllowLongPress = allowLongPress; mFalsingManager = falsingManager; @@ -133,9 +133,9 @@ public class ExpandableNotificationRowController implements NodeController { mOnFeedbackClickListener, mFalsingManager, mStatusBarStateController, - mPeopleNotificationIdentifier + mPeopleNotificationIdentifier, + mOnUserInteractionCallback ); - mView.setOnDismissCallback(mOnDismissCallback); mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); if (mAllowLongPress) { mView.setLongPressListener((v, x, y, item) -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index f543db74d91a..7c7bb5c83762 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -69,7 +69,6 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.notification.NotificationChannelHelper; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; @@ -89,7 +88,7 @@ public class NotificationConversationInfo extends LinearLayout implements private ShortcutManager mShortcutManager; private PackageManager mPm; private ConversationIconFactory mIconFactory; - private VisualStabilityManager mVisualStabilityManager; + private OnUserInteractionCallback mOnUserInteractionCallback; private Handler mMainHandler; private Handler mBgHandler; private BubbleController mBubbleController; @@ -207,7 +206,7 @@ public class NotificationConversationInfo extends LinearLayout implements ShortcutManager shortcutManager, PackageManager pm, INotificationManager iNotificationManager, - VisualStabilityManager visualStabilityManager, + OnUserInteractionCallback onUserInteractionCallback, String pkg, NotificationChannel notificationChannel, NotificationEntry entry, @@ -224,7 +223,7 @@ public class NotificationConversationInfo extends LinearLayout implements BubbleController bubbleController) { mSelectedAction = -1; mINotificationManager = iNotificationManager; - mVisualStabilityManager = visualStabilityManager; + mOnUserInteractionCallback = onUserInteractionCallback; mPackageName = pkg; mEntry = entry; mSbn = entry.getSbn(); @@ -513,7 +512,7 @@ public class NotificationConversationInfo extends LinearLayout implements mAppUid, mSelectedAction, mNotificationChannel)); mEntry.markForUserTriggeredMovement(true); mMainHandler.postDelayed( - mVisualStabilityManager::temporarilyAllowReordering, + () -> mOnUserInteractionCallback.onImportanceChanged(mEntry), StackStateAnimator.ANIMATION_DURATION_STANDARD); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 05d44f6eb406..60074f608969 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -60,7 +60,6 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; @@ -88,10 +87,10 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); private final Context mContext; - private final VisualStabilityManager mVisualStabilityManager; private final AccessibilityManager mAccessibilityManager; private final HighPriorityProvider mHighPriorityProvider; private final ChannelEditorDialogController mChannelEditorDialogController; + private final OnUserInteractionCallback mOnUserInteractionCallback; // Dependencies: private final NotificationLockscreenUserManager mLockscreenUserManager = @@ -129,8 +128,10 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx /** * Injected constructor. See {@link NotificationsModule}. */ - public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager, - Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler, @Background Handler bgHandler, + public NotificationGutsManager(Context context, + Lazy<StatusBar> statusBarLazy, + @Main Handler mainHandler, + @Background Handler bgHandler, AccessibilityManager accessibilityManager, HighPriorityProvider highPriorityProvider, INotificationManager notificationManager, @@ -141,9 +142,9 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx Provider<PriorityOnboardingDialogController.Builder> builderProvider, AssistantFeedbackController assistantFeedbackController, BubbleController bubbleController, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, + OnUserInteractionCallback onUserInteractionCallback) { mContext = context; - mVisualStabilityManager = visualStabilityManager; mStatusBarLazy = statusBarLazy; mMainHandler = mainHandler; mBgHandler = bgHandler; @@ -158,6 +159,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mAssistantFeedbackController = assistantFeedbackController; mBubbleController = bubbleController; mUiEventLogger = uiEventLogger; + mOnUserInteractionCallback = onUserInteractionCallback; } public void setUpWithPresenter(NotificationPresenter presenter, @@ -363,7 +365,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx notificationInfoView.bindNotification( pmUser, mNotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, packageName, row.getEntry().getChannel(), @@ -474,7 +476,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mShortcutManager, pmUser, mNotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, packageName, entry.getChannel(), entry, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java index a6ba85fc8bdf..7a976ac82223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java @@ -60,7 +60,6 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.lang.annotation.Retention; @@ -93,9 +92,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private TextView mAutomaticDescriptionView; private INotificationManager mINotificationManager; + private OnUserInteractionCallback mOnUserInteractionCallback; private PackageManager mPm; private MetricsLogger mMetricsLogger; - private VisualStabilityManager mVisualStabilityManager; private ChannelEditorDialogController mChannelEditorDialogController; private String mPackageName; @@ -119,6 +118,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private boolean mIsAutomaticChosen; private boolean mIsSingleDefaultChannel; private boolean mIsNonblockable; + private NotificationEntry mEntry; private StatusBarNotification mSbn; private boolean mIsDeviceProvisioned; @@ -188,7 +188,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G public void bindNotification( PackageManager pm, INotificationManager iNotificationManager, - VisualStabilityManager visualStabilityManager, + OnUserInteractionCallback onUserInteractionCallback, ChannelEditorDialogController channelEditorDialogController, String pkg, NotificationChannel notificationChannel, @@ -204,11 +204,12 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G throws RemoteException { mINotificationManager = iNotificationManager; mMetricsLogger = Dependency.get(MetricsLogger.class); - mVisualStabilityManager = visualStabilityManager; + mOnUserInteractionCallback = onUserInteractionCallback; mChannelEditorDialogController = channelEditorDialogController; mPackageName = pkg; mUniqueChannelsInRow = uniqueChannelsInRow; mNumUniqueChannelsInRow = uniqueChannelsInRow.size(); + mEntry = entry; mSbn = entry.getSbn(); mPm = pm; mAppSettingsClickListener = onAppSettingsClick; @@ -438,7 +439,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid, mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null, mStartingChannelImportance, newImportance, mIsAutomaticChosen)); - mVisualStabilityManager.temporarilyAllowReordering(); + mOnUserInteractionCallback.onImportanceChanged(mEntry); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java index f1aed899e060..0c3f553825d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java @@ -21,15 +21,21 @@ import android.service.notification.NotificationListenerService; import com.android.systemui.statusbar.notification.collection.NotificationEntry; /** - * Callback when a user clicks on an auto-cancelled notification or manually swipes to dismiss the - * notification. + * Callbacks for when a user interacts with an {@link ExpandableNotificationRow}. */ -public interface OnDismissCallback { +public interface OnUserInteractionCallback { /** - * Handle a user interaction that triggers a notification dismissal. + * Handle a user interaction that triggers a notification dismissal. Called when a user clicks + * on an auto-cancelled notification or manually swipes to dismiss the notification. */ void onDismiss( NotificationEntry entry, @NotificationListenerService.NotificationCancelReason int cancellationReason); + + /** + * Triggered after a user has changed the importance of the notification via its + * {@link NotificationGuts}. + */ + void onImportanceChanged(NotificationEntry entry); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index 7e4266c7cd28..a396305a49b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -22,7 +22,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; import android.service.notification.StatusBarNotification; -import android.util.ArraySet; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.NotificationHeaderView; @@ -36,7 +35,7 @@ import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.NotificationHeaderUtil; import com.android.systemui.statusbar.notification.NotificationUtils; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.HybridGroupManager; import com.android.systemui.statusbar.notification.row.HybridNotificationView; 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 d2f8a39cc8fb..d4c270f45ceb 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 @@ -125,10 +125,10 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.ShadeViewRefactor; import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -150,7 +150,6 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; @@ -179,8 +178,7 @@ import javax.inject.Named; /** * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack. */ -public class NotificationStackScrollLayout extends ViewGroup implements ScrollAdapter, - ConfigurationListener, Dumpable, DynamicPrivacyController.Listener { +public class NotificationStackScrollLayout extends ViewGroup implements ScrollAdapter, Dumpable { public static final float BACKGROUND_ALPHA_DIMMED = 0.7f; private static final String TAG = "StackScroller"; @@ -500,7 +498,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>(); private int mHeadsUpInset; private HeadsUpAppearanceController mHeadsUpAppearanceController; - private NotificationIconAreaController mIconAreaController; private final NotificationLockscreenUserManager mLockscreenUserManager; private final Rect mTmpRect = new Rect(); private final FeatureFlags mFeatureFlags; @@ -669,7 +666,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd }); } - dynamicPrivacyController.addListener(this); mDynamicPrivacyController = dynamicPrivacyController; mStatusbarStateController = statusBarStateController; initializeForegroundServiceSection(fgsFeatureController); @@ -732,36 +728,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return 0f; } - @Override - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void onDensityOrFontScaleChanged() { - reinflateViews(); - } - - private void reinflateViews() { + void reinflateViews() { inflateFooterView(); inflateEmptyShadeView(); updateFooter(); mSectionsManager.reinflateViews(LayoutInflater.from(mContext)); } - @Override - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void onThemeChanged() { - updateFooter(); - } - - @Override - public void onOverlayChanged() { - int newRadius = mContext.getResources().getDimensionPixelSize( - Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius)); - if (mCornerRadius != newRadius) { - mCornerRadius = newRadius; - invalidate(); - } - reinflateViews(); - } - @VisibleForTesting @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void updateFooter() { @@ -827,7 +800,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd super.onAttachedToWindow(); ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class)) .addCallback(mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER); - Dependency.get(ConfigurationController.class).addCallback(this); } @Override @@ -835,7 +807,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); - Dependency.get(ConfigurationController.class).removeCallback(this); } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @@ -843,9 +814,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return mSwipeHelper; } - @Override - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void onUiModeChanged() { + void updateBgColor() { mBgColor = mContext.getColor(R.color.notification_shade_background_color); updateBackgroundDimming(); mShelf.onUiModeChanged(); @@ -1078,6 +1047,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd R.dimen.heads_up_status_bar_padding); } + void updateCornerRadius() { + int newRadius = getResources().getDimensionPixelSize( + Utils.getThemeAttr(getContext(), android.R.attr.dialogCornerRadius)); + if (mCornerRadius != newRadius) { + mCornerRadius = newRadius; + invalidate(); + } + } + @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void notifyHeightChangeListener(ExpandableView view) { notifyHeightChangeListener(view, false /* needsAnimation */); @@ -3355,8 +3333,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.COORDINATOR) void onViewAddedInternal(ExpandableView child) { - child.setOnHeightChangedListener(mOnChildHeightChangedListener); updateHideSensitiveForChild(child); + child.setOnHeightChangedListener(mOnChildHeightChangedListener); generateAddAnimation(child, false /* fromMoreCard */); updateAnimationState(child); updateChronometerForChild(child); @@ -4854,7 +4832,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd * @param lightTheme True if light theme should be used. */ @ShadeViewRefactor(RefactorComponent.DECORATOR) - private void updateDecorViews(boolean lightTheme) { + void updateDecorViews(boolean lightTheme) { if (lightTheme == mUsingLightTheme) { return; } @@ -5596,11 +5574,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void setIconAreaController(NotificationIconAreaController controller) { - mIconAreaController = controller; - } - - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @VisibleForTesting void clearNotifications( @SelectedRows int selection, @@ -5790,10 +5763,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mNotificationPanelController = notificationPanelViewController; } - public void updateIconAreaViews() { - mIconAreaController.updateNotificationIcons(); - } - /** * Set how far the wake up is when waking up from pulsing. This is a height and will adjust the * notification positions accordingly. @@ -5852,17 +5821,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mDimmedNeedsAnimation = true; } - @Override - public void onDynamicPrivacyChanged() { - if (mIsExpanded) { - // The bottom might change because we're using the final actual height of the view - mAnimateBottomOnLayout = true; - } - // Let's update the footer once the notifications have been updated (in the next frame) - post(() -> { - updateFooter(); - updateSectionBoundaries("dynamic privacy changed"); - }); + void setAnimateBottomOnLayout(boolean animateBottomOnLayout) { + mAnimateBottomOnLayout = animateBottomOnLayout; } public void setOnPulseHeightChangedListener(Runnable listener) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 53d3b7586f7e..7c29ee2b5483 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; -import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY; import android.graphics.PointF; import android.provider.Settings; @@ -27,10 +26,12 @@ import android.view.ViewGroup; import android.view.WindowInsets; import android.widget.FrameLayout; +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -42,11 +43,12 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.tuner.TunerService; import java.util.function.BiConsumer; @@ -64,22 +66,78 @@ public class NotificationStackScrollLayoutController { private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationRoundnessManager mNotificationRoundnessManager; private final TunerService mTunerService; + private final DynamicPrivacyController mDynamicPrivacyController; + private final ConfigurationController mConfigurationController; private final NotificationListContainerImpl mNotificationListContainer = new NotificationListContainerImpl(); private NotificationStackScrollLayout mView; + @VisibleForTesting + final View.OnAttachStateChangeListener mOnAttachStateChangeListener = + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + mConfigurationController.addCallback(mConfigurationListener); + } + + @Override + public void onViewDetachedFromWindow(View v) { + mConfigurationController.removeCallback(mConfigurationListener); + } + }; + + private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> { + if (mView.isExpanded()) { + // The bottom might change because we're using the final actual height of the view + mView.setAnimateBottomOnLayout(true); + } + // Let's update the footer once the notifications have been updated (in the next frame) + mView.post(() -> { + updateFooter(); + updateSectionBoundaries("dynamic privacy changed"); + }); + }; + + @VisibleForTesting + final ConfigurationListener mConfigurationListener = new ConfigurationListener() { + @Override + public void onDensityOrFontScaleChanged() { + mView.reinflateViews(); + } + + @Override + public void onOverlayChanged() { + mView.updateCornerRadius(); + mView.reinflateViews(); + } + + @Override + public void onUiModeChanged() { + mView.updateBgColor(); + } + + @Override + public void onThemeChanged() { + updateFooter(); + } + }; + @Inject public NotificationStackScrollLayoutController( @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, NotificationGutsManager notificationGutsManager, HeadsUpManagerPhone headsUpManager, NotificationRoundnessManager notificationRoundnessManager, - TunerService tunerService) { + TunerService tunerService, + DynamicPrivacyController dynamicPrivacyController, + ConfigurationController configurationController) { mAllowLongPress = allowLongPress; mNotificationGutsManager = notificationGutsManager; mHeadsUpManager = headsUpManager; mNotificationRoundnessManager = notificationRoundnessManager; mTunerService = tunerService; + mDynamicPrivacyController = dynamicPrivacyController; + mConfigurationController = configurationController; } public void attach(NotificationStackScrollLayout view) { @@ -91,15 +149,26 @@ public class NotificationStackScrollLayoutController { } mHeadsUpManager.addListener(mNotificationRoundnessManager); // TODO: why is this here? + mDynamicPrivacyController.addListener(mDynamicPrivacyControllerListener); mNotificationRoundnessManager.setOnRoundingChangedCallback(mView::invalidate); mView.addOnExpandedHeightChangedListener(mNotificationRoundnessManager::setExpanded); - mTunerService.addTunable((key, newValue) -> { - if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) { - mView.updateDismissRtlSetting("1".equals(newValue)); - } - }, HIGH_PRIORITY, Settings.Secure.NOTIFICATION_DISMISS_RTL); + mTunerService.addTunable( + (key, newValue) -> { + if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) { + mView.updateDismissRtlSetting("1".equals(newValue)); + } else if (key.equals(Settings.Secure.NOTIFICATION_HISTORY_ENABLED)) { + updateFooter(); + } + }, + Settings.Secure.NOTIFICATION_DISMISS_RTL, + Settings.Secure.NOTIFICATION_HISTORY_ENABLED); + + if (mView.isAttachedToWindow()) { + mOnAttachStateChangeListener.onViewAttachedToWindow(mView); + } + mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener); } public void addOnExpandedHeightChangedListener(BiConsumer<Float, Float> listener) { @@ -479,10 +548,6 @@ public class NotificationStackScrollLayoutController { mView.updateFooter(); } - public void updateIconAreaViews() { - mView.updateIconAreaViews(); - } - public void onUpdateRowStates() { mView.onUpdateRowStates(); } @@ -504,10 +569,6 @@ public class NotificationStackScrollLayoutController { mView.setNotificationPanelController(notificationPanelViewController); } - public void setIconAreaController(NotificationIconAreaController controller) { - mView.setIconAreaController(controller); - } - public void setStatusBar(StatusBar statusBar) { mView.setStatusBar(statusBar); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index 952583034ff8..efb24693beff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -43,7 +43,6 @@ 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; @@ -83,7 +82,6 @@ public final class DozeServiceHost implements DozeHost { private final Lazy<AssistManager> mAssistManagerLazy; private final DozeScrimController mDozeScrimController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final VisualStabilityManager mVisualStabilityManager; private final PulseExpansionHandler mPulseExpansionHandler; private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; @@ -108,12 +106,12 @@ public final class DozeServiceHost implements DozeHost { KeyguardViewMediator keyguardViewMediator, Lazy<AssistManager> assistManagerLazy, DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, - VisualStabilityManager visualStabilityManager, PulseExpansionHandler pulseExpansionHandler, NotificationShadeWindowController notificationShadeWindowController, NotificationWakeUpCoordinator notificationWakeUpCoordinator, LockscreenLockIconController lockscreenLockIconController, - AuthController authController) { + AuthController authController, + NotificationIconAreaController notificationIconAreaController) { super(); mDozeLog = dozeLog; mPowerManager = powerManager; @@ -128,12 +126,12 @@ public final class DozeServiceHost implements DozeHost { mAssistManagerLazy = assistManagerLazy; mDozeScrimController = dozeScrimController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mVisualStabilityManager = visualStabilityManager; mPulseExpansionHandler = pulseExpansionHandler; mNotificationShadeWindowController = notificationShadeWindowController; mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; mLockscreenLockIconController = lockscreenLockIconController; mAuthController = authController; + mNotificationIconAreaController = notificationIconAreaController; } // TODO: we should try to not pass status bar in here if we can avoid it. @@ -141,13 +139,13 @@ public final class DozeServiceHost implements DozeHost { /** * Initialize instance with objects only available later during execution. */ - public void initialize(StatusBar statusBar, - NotificationIconAreaController notificationIconAreaController, + public void initialize( + StatusBar statusBar, StatusBarKeyguardViewManager statusBarKeyguardViewManager, NotificationShadeWindowViewController notificationShadeWindowViewController, - NotificationPanelViewController notificationPanel, View ambientIndicationContainer) { + NotificationPanelViewController notificationPanel, + View ambientIndicationContainer) { mStatusBar = statusBar; - mNotificationIconAreaController = notificationIconAreaController; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mNotificationPanel = notificationPanel; mNotificationShadeWindowViewController = notificationShadeWindowViewController; @@ -259,11 +257,10 @@ public final class DozeServiceHost implements DozeHost { } private void setPulsing(boolean pulsing) { - mStatusBarStateController.setPulsing(pulsing); mStatusBarKeyguardViewManager.setPulsing(pulsing); mKeyguardViewMediator.setPulsing(pulsing); mNotificationPanel.setPulsing(pulsing); - mVisualStabilityManager.setPulsing(pulsing); + mStatusBarStateController.setPulsing(pulsing); mIgnoreTouchWhilePulsing = false; if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) { mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 1d82e0808332..8092cb910b07 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -31,8 +31,8 @@ import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -58,6 +58,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private final NotificationGroupManager mGroupManager; private final List<OnHeadsUpPhoneListenerChange> mHeadsUpPhoneListeners = new ArrayList<>(); private final int mAutoHeadsUpNotificationDecay; + // TODO (b/162832756): remove visual stability manager when migrating to new pipeline private VisualStabilityManager mVisualStabilityManager; private boolean mReleaseOnExpandFinish; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java index 0e413fba0ad5..bda35fb0a48e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -8,7 +8,6 @@ import android.graphics.Rect; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.NonNull; @@ -21,6 +20,7 @@ import com.android.settingslib.Utils; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.demomode.DemoMode; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.plugins.DarkIconDispatcher; @@ -34,19 +34,23 @@ import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Function; +import javax.inject.Inject; + /** * A controller for the space in the status bar to the left of the system icons. This area is * normally reserved for notifications. */ -public class NotificationIconAreaController implements DarkReceiver, +@SysUISingleton +public class NotificationIconAreaController implements + DarkReceiver, StatusBarStateController.StateListener, NotificationWakeUpCoordinator.WakeUpListener, DemoMode { @@ -62,13 +66,14 @@ public class NotificationIconAreaController implements DarkReceiver, private final KeyguardBypassController mBypassController; private final DozeParameters mDozeParameters; private final BubbleController mBubbleController; + private final StatusBarWindowController mStatusBarWindowController; private int mIconSize; private int mIconHPadding; private int mIconTint = Color.WHITE; private int mCenteredIconTint = Color.WHITE; - private StatusBar mStatusBar; + private List<ListEntry> mNotificationEntries = List.of(); protected View mNotificationIconArea; private NotificationIconContainer mNotificationIcons; private NotificationIconContainer mShelfIcons; @@ -77,8 +82,8 @@ public class NotificationIconAreaController implements DarkReceiver, private NotificationIconContainer mAodIcons; private StatusBarIconView mCenteredIconView; private final Rect mTintArea = new Rect(); - private ViewGroup mNotificationScrollLayout; private Context mContext; + private final DemoModeController mDemoModeController; private int mAodIconAppearTranslation; @@ -95,16 +100,14 @@ public class NotificationIconAreaController implements DarkReceiver, new NotificationListener.NotificationSettingsListener() { @Override public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { - mShowLowPriority = !hideSilentStatusIcons; - if (mNotificationScrollLayout != null) { - updateStatusBarIcons(); - } + mShowLowPriority = !hideSilentStatusIcons; + updateStatusBarIcons(); } }; + @Inject public NotificationIconAreaController( Context context, - StatusBar statusBar, StatusBarStateController statusBarStateController, NotificationWakeUpCoordinator wakeUpCoordinator, KeyguardBypassController keyguardBypassController, @@ -112,8 +115,9 @@ public class NotificationIconAreaController implements DarkReceiver, NotificationListener notificationListener, DozeParameters dozeParameters, BubbleController bubbleController, - DemoModeController demoModeController) { - mStatusBar = statusBar; + DemoModeController demoModeController, + DarkIconDispatcher darkIconDispatcher, + StatusBarWindowController statusBarWindowController) { mContrastColorUtil = ContrastColorUtil.getInstance(context); mContext = context; mStatusBarStateController = statusBarStateController; @@ -124,12 +128,14 @@ public class NotificationIconAreaController implements DarkReceiver, wakeUpCoordinator.addListener(this); mBypassController = keyguardBypassController; mBubbleController = bubbleController; - notificationListener.addNotificationSettingsListener(mSettingsListener); mDemoModeController = demoModeController; mDemoModeController.addCallback(this); + mStatusBarWindowController = statusBarWindowController; + notificationListener.addNotificationSettingsListener(mSettingsListener); initializeNotificationAreaViews(context); reloadAodColor(); + darkIconDispatcher.addDarkReceiver(this); } protected View inflateIconArea(LayoutInflater inflater) { @@ -146,22 +152,21 @@ public class NotificationIconAreaController implements DarkReceiver, mNotificationIconArea = inflateIconArea(layoutInflater); mNotificationIcons = mNotificationIconArea.findViewById(R.id.notificationIcons); - mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout(); - mCenteredIconArea = layoutInflater.inflate(R.layout.center_icon_area, null); mCenteredIcon = mCenteredIconArea.findViewById(R.id.centeredIcon); - - initAodIcons(); } - public void initAodIcons() { + /** + * Called by the StatusBar. The StatusBar passes the NotificationIconContainer which holds + * the aod icons. + */ + void setupAodIcons(@NonNull NotificationIconContainer aodIcons) { boolean changed = mAodIcons != null; if (changed) { mAodIcons.setAnimationsEnabled(false); mAodIcons.removeAllViews(); } - mAodIcons = mStatusBar.getNotificationShadeWindowView().findViewById( - R.id.clock_notification_icon_container); + mAodIcons = aodIcons; mAodIcons.setOnLockScreen(true); updateAodIconsVisibility(false /* animate */); updateAnimations(); @@ -199,7 +204,7 @@ public class NotificationIconAreaController implements DarkReceiver, @NonNull private FrameLayout.LayoutParams generateIconLayoutParams() { return new FrameLayout.LayoutParams( - mIconSize + 2 * mIconHPadding, getHeight()); + mIconSize + 2 * mIconHPadding, mStatusBarWindowController.getStatusBarHeight()); } private void reloadDimens(Context context) { @@ -238,29 +243,17 @@ public class NotificationIconAreaController implements DarkReceiver, mTintArea.set(tintArea); } - if (mNotificationIconArea != null) { - if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) { - mIconTint = iconTint; - } - } else { + if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) { mIconTint = iconTint; } - if (mCenteredIconArea != null) { - if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) { - mCenteredIconTint = iconTint; - } - } else { + if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) { mCenteredIconTint = iconTint; } applyNotificationIconsTint(); } - protected int getHeight() { - return mStatusBar.getStatusBarHeight(); - } - protected boolean shouldShowNotificationIcon(NotificationEntry entry, boolean showAmbient, boolean showLowPriority, boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon, @@ -310,11 +303,15 @@ public class NotificationIconAreaController implements DarkReceiver, } return true; } - /** * Updates the notifications with the given list of notifications to display. */ - public void updateNotificationIcons() { + public void updateNotificationIcons(List<ListEntry> entries) { + mNotificationEntries = entries; + updateNotificationIcons(); + } + + private void updateNotificationIcons() { updateStatusBarIcons(); updateShelfIcons(); updateCenterIcon(); @@ -391,18 +388,15 @@ public class NotificationIconAreaController implements DarkReceiver, NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority, boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) { - ArrayList<StatusBarIconView> toShow = new ArrayList<>( - mNotificationScrollLayout.getChildCount()); - + ArrayList<StatusBarIconView> toShow = new ArrayList<>(mNotificationEntries.size()); // Filter out ambient notifications and notification children. - for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) { - View view = mNotificationScrollLayout.getChildAt(i); - if (view instanceof ExpandableNotificationRow) { - NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry(); - if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed, + for (int i = 0; i < mNotificationEntries.size(); i++) { + NotificationEntry entry = mNotificationEntries.get(i).getRepresentativeEntry(); + if (entry != null && entry.getRow() != null) { + if (shouldShowNotificationIcon(entry, showAmbient, showLowPriority, hideDismissed, hideRepliedMessages, hideCurrentMedia, hideCenteredIcon, hidePulsing, onlyShowCenteredIcon)) { - StatusBarIconView iconView = function.apply(ent); + StatusBarIconView iconView = function.apply(entry); if (iconView != null) { toShow.add(iconView); } @@ -607,13 +601,16 @@ public class NotificationIconAreaController implements DarkReceiver, mAodIconTint = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor); } + private void updateAodIconColors() { - for (int i = 0; i < mAodIcons.getChildCount(); i++) { - final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i); - if (iv.getWidth() != 0) { - updateTintForIcon(iv, mAodIconTint); - } else { - iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint)); + if (mAodIcons != null) { + for (int i = 0; i < mAodIcons.getChildCount(); i++) { + final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i); + if (iv.getWidth() != 0) { + updateTintForIcon(iv, mAodIconTint); + } else { + iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint)); + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 42fbe5967d42..5974a53fc86d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -100,6 +100,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.ViewGroupFadeHelper; +import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -177,6 +178,7 @@ public class NotificationPanelViewController extends PanelViewController { private final ConfigurationController mConfigurationController; private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder; private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController; + private final NotificationIconAreaController mNotificationIconAreaController; // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is // changed. @@ -502,7 +504,8 @@ public class NotificationPanelViewController extends PanelViewController { BiometricUnlockController biometricUnlockController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider, - NotificationStackScrollLayoutController notificationStackScrollLayoutController) { + NotificationStackScrollLayoutController notificationStackScrollLayoutController, + NotificationIconAreaController notificationIconAreaController) { super(view, falsingManager, dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, vibratorHelper, latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager); @@ -516,6 +519,7 @@ public class NotificationPanelViewController extends PanelViewController { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardClockSwitchControllerProvider = keyguardClockSwitchControllerProvider; mNotificationStackScrollLayoutController = notificationStackScrollLayoutController; + mNotificationIconAreaController = notificationIconAreaController; mView.setWillNotDraw(!DEBUG); mInjectionInflationController = injectionInflationController; mFalsingManager = falsingManager; @@ -3066,7 +3070,19 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.updateSpeedBumpIndex(); mNotificationStackScrollLayoutController.updateFooter(); updateShowEmptyShadeView(); - mNotificationStackScrollLayoutController.updateIconAreaViews(); + mNotificationIconAreaController.updateNotificationIcons(createVisibleEntriesList()); + } + + private List<ListEntry> createVisibleEntriesList() { + List<ListEntry> entries = new ArrayList<>( + mNotificationStackScrollLayoutController.getChildCount()); + for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) { + View view = mNotificationStackScrollLayoutController.getChildAt(i); + if (view instanceof ExpandableNotificationRow) { + entries.add(((ExpandableNotificationRow) view).getEntry()); + } + } + return entries; } public void onUpdateRowStates() { @@ -3094,15 +3110,17 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.setScrollingEnabled(b); } - public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager, + /** + * Initialize objects instead of injecting to avoid circular dependencies. + */ + public void initDependencies( + StatusBar statusBar, + NotificationGroupManager groupManager, NotificationShelfController notificationShelfController, - NotificationIconAreaController notificationIconAreaController, ScrimController scrimController) { setStatusBar(statusBar); setGroupManager(mGroupManager); mNotificationStackScrollLayoutController.setNotificationPanelController(this); - mNotificationStackScrollLayoutController - .setIconAreaController(notificationIconAreaController); mNotificationStackScrollLayoutController.setStatusBar(statusBar); mNotificationStackScrollLayoutController.setGroupManager(groupManager); mNotificationStackScrollLayoutController.setShelfController(notificationShelfController); 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 5b251befb028..6e37f90f9d94 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -144,7 +144,6 @@ import com.android.systemui.InitController; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.SystemUI; -import com.android.systemui.SystemUIFactory; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; @@ -204,8 +203,8 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; 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.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; @@ -396,7 +395,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final SuperStatusBarViewFactory mSuperStatusBarViewFactory; private final LightsOutNotifController mLightsOutNotifController; private final InitController mInitController; - private final DarkIconDispatcher mDarkIconDispatcher; + private final PluginDependencyProvider mPluginDependencyProvider; private final KeyguardDismissUtil mKeyguardDismissUtil; private final ExtensionController mExtensionController; @@ -609,7 +608,7 @@ public class StatusBar extends SystemUI implements DemoMode, private UiModeManager mUiModeManager; protected boolean mIsKeyguard; private LogMaker mStatusBarStateLog; - protected NotificationIconAreaController mNotificationIconAreaController; + protected final NotificationIconAreaController mNotificationIconAreaController; @Nullable private View mAmbientIndicationContainer; private final SysuiColorExtractor mColorExtractor; private final ScreenLifecycle mScreenLifecycle; @@ -731,7 +730,6 @@ public class StatusBar extends SystemUI implements DemoMode, StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, InitController initController, - DarkIconDispatcher darkIconDispatcher, @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, PluginDependencyProvider pluginDependencyProvider, KeyguardDismissUtil keyguardDismissUtil, @@ -742,7 +740,8 @@ public class StatusBar extends SystemUI implements DemoMode, DismissCallbackRegistry dismissCallbackRegistry, DemoModeController demoModeController, Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy, - StatusBarTouchableRegionManager statusBarTouchableRegionManager) { + StatusBarTouchableRegionManager statusBarTouchableRegionManager, + NotificationIconAreaController notificationIconAreaController) { super(context); mNotificationsController = notificationsController; mLightBarController = lightBarController; @@ -812,7 +811,6 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardViewMediatorCallback = viewMediatorCallback; mInitController = initController; - mDarkIconDispatcher = darkIconDispatcher; mPluginDependencyProvider = pluginDependencyProvider; mKeyguardDismissUtil = keyguardDismissUtil; mExtensionController = extensionController; @@ -820,6 +818,7 @@ public class StatusBar extends SystemUI implements DemoMode, mIconPolicy = phoneStatusBarPolicy; mDismissCallbackRegistry = dismissCallbackRegistry; mDemoModeController = demoModeController; + mNotificationIconAreaController = notificationIconAreaController; mBubbleExpandListener = (isExpanding, key) -> { @@ -953,9 +952,12 @@ public class StatusBar extends SystemUI implements DemoMode, startKeyguard(); mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); - mDozeServiceHost.initialize(this, mNotificationIconAreaController, - mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController, - mNotificationPanelViewController, mAmbientIndicationContainer); + mDozeServiceHost.initialize( + this, + mStatusBarKeyguardViewManager, + mNotificationShadeWindowViewController, + mNotificationPanelViewController, + mAmbientIndicationContainer); mConfigurationController.addCallback(this); @@ -1037,20 +1039,12 @@ public class StatusBar extends SystemUI implements DemoMode, mStackScrollerController.getNotificationListContainer(); mNotificationLogger.setUpWithContainer(notifListContainer); - // TODO: make this injectable. Currently that would create a circular dependency between - // NotificationIconAreaController and StatusBar. - mNotificationIconAreaController = SystemUIFactory.getInstance() - .createNotificationIconAreaController(context, this, - mWakeUpCoordinator, mKeyguardBypassController, - mStatusBarStateController, mDemoModeController); - mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController); + updateAodIconArea(); inflateShelf(); mNotificationIconAreaController.setupShelf(mNotificationShelfController); - mNotificationPanelViewController.setOnReinflationListener( - mNotificationIconAreaController::initAodIcons); + mNotificationPanelViewController.setOnReinflationListener(this::updateAodIconArea); mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator); - mDarkIconDispatcher.addDarkReceiver(mNotificationIconAreaController); // Allow plugins to reference DarkIconDispatcher and StatusBarStateController mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class); mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class); @@ -1163,9 +1157,11 @@ public class StatusBar extends SystemUI implements DemoMode, }); mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble); - mNotificationPanelViewController.initDependencies(this, mGroupManager, + mNotificationPanelViewController.initDependencies( + this, + mGroupManager, mNotificationShelfController, - mNotificationIconAreaController, mScrimController); + mScrimController); BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), @@ -1279,6 +1275,12 @@ public class StatusBar extends SystemUI implements DemoMode, ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); } + private void updateAodIconArea() { + mNotificationIconAreaController.setupAodIcons( + getNotificationShadeWindowView() + .findViewById(R.id.clock_notification_icon_container)); + } + @NonNull @Override public Lifecycle getLifecycle() { @@ -1847,7 +1849,7 @@ public class StatusBar extends SystemUI implements DemoMode, mPanelExpanded = isExpanded; updateHideIconsForBouncer(false /* animate */); mNotificationShadeWindowController.setPanelExpanded(isExpanded); - mVisualStabilityManager.setPanelExpanded(isExpanded); + mStatusBarStateController.setPanelExpanded(isExpanded); if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) { if (DEBUG) { Log.v(TAG, "clearing notification effects from setExpandedHeight"); @@ -2068,7 +2070,7 @@ public class StatusBar extends SystemUI implements DemoMode, mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); } mNotificationPanelViewController.expand(true /* animate */); - ((NotificationListContainer) mStackScroller).setWillExpand(true); + mStackScroller.setWillExpand(true); mHeadsUpManager.unpinAll(true /* userUnpinned */); mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1); } else if (!mNotificationPanelViewController.isInSettings() @@ -3785,7 +3787,6 @@ public class StatusBar extends SystemUI implements DemoMode, mDeviceInteractive = false; mWakeUpComingFromTouch = false; mWakeUpTouchLocation = null; - mVisualStabilityManager.setScreenOn(false); updateVisibleToUser(); updateNotificationPanelTouchState(); @@ -3822,7 +3823,6 @@ public class StatusBar extends SystemUI implements DemoMode, if (!mKeyguardBypassController.getBypassEnabled()) { mHeadsUpManager.releaseAllImmediately(); } - mVisualStabilityManager.setScreenOn(true); updateVisibleToUser(); updateIsKeyguard(); mDozeServiceHost.stopDozing(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index f1e2f774a954..de11c9023200 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -73,7 +73,7 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -124,7 +124,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final NotificationPresenter mPresenter; private final NotificationPanelViewController mNotificationPanel; private final ActivityLaunchAnimator mActivityLaunchAnimator; - private final OnDismissCallback mOnDismissCallback; + private final OnUserInteractionCallback mOnUserInteractionCallback; private boolean mIsCollapsingToShowActivityOverLockscreen; @@ -158,7 +158,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit FeatureFlags featureFlags, MetricsLogger metricsLogger, StatusBarNotificationActivityStarterLogger logger, - OnDismissCallback onDismissCallback, + OnUserInteractionCallback onUserInteractionCallback, StatusBar statusBar, NotificationPresenter presenter, @@ -193,7 +193,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mFeatureFlags = featureFlags; mMetricsLogger = metricsLogger; mLogger = logger; - mOnDismissCallback = onDismissCallback; + mOnUserInteractionCallback = onUserInteractionCallback; // TODO: use KeyguardStateController#isOccluded to remove this dependency mStatusBar = statusBar; @@ -575,10 +575,10 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit // To avoid lags we're only performing the remove // after the shade was collapsed mShadeController.addPostCollapseAction( - () -> mOnDismissCallback.onDismiss(entry, REASON_CLICK) + () -> mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK) ); } else { - mOnDismissCallback.onDismiss(entry, REASON_CLICK); + mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK); } }); } @@ -628,7 +628,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final FeatureFlags mFeatureFlags; private final MetricsLogger mMetricsLogger; private final StatusBarNotificationActivityStarterLogger mLogger; - private final OnDismissCallback mOnDismissCallback; + private final OnUserInteractionCallback mOnUserInteractionCallback; private StatusBar mStatusBar; private NotificationPresenter mNotificationPresenter; @@ -666,7 +666,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit FeatureFlags featureFlags, MetricsLogger metricsLogger, StatusBarNotificationActivityStarterLogger logger, - OnDismissCallback onDismissCallback) { + OnUserInteractionCallback onUserInteractionCallback) { mContext = context; mCommandQueue = commandQueue; @@ -697,7 +697,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mFeatureFlags = featureFlags; mMetricsLogger = metricsLogger; mLogger = logger; - mOnDismissCallback = onDismissCallback; + mOnUserInteractionCallback = onUserInteractionCallback; } /** Sets the status bar to use as {@link StatusBar}. */ @@ -754,7 +754,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mFeatureFlags, mMetricsLogger, mLogger, - mOnDismissCallback, + mOnUserInteractionCallback, mStatusBar, mNotificationPresenter, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index 0ec22b4a415f..67adaaae402e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -61,9 +61,9 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; @@ -217,7 +217,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor); mLockscreenUserManager.setUpWithPresenter(this); mMediaManager.setUpWithPresenter(this); - mVisualStabilityManager.setUpWithPresenter(this); mGutsManager.setUpWithPresenter(this, stackScrollerController.getNotificationListContainer(), mCheckSaveListener, mOnSettingsClickListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index bdf63c791d28..2768b826fcfe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -41,7 +41,6 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.navigationbar.NavigationBarController; -import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.recents.Recents; @@ -62,7 +61,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; @@ -82,6 +81,7 @@ import com.android.systemui.statusbar.phone.LightsOutNotifController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; @@ -189,7 +189,6 @@ public interface StatusBarPhoneModule { StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, InitController initController, - DarkIconDispatcher darkIconDispatcher, @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, PluginDependencyProvider pluginDependencyProvider, KeyguardDismissUtil keyguardDismissUtil, @@ -200,7 +199,8 @@ public interface StatusBarPhoneModule { DemoModeController demoModeController, Lazy<NotificationShadeDepthController> notificationShadeDepthController, DismissCallbackRegistry dismissCallbackRegistry, - StatusBarTouchableRegionManager statusBarTouchableRegionManager) { + StatusBarTouchableRegionManager statusBarTouchableRegionManager, + NotificationIconAreaController notificationIconAreaController) { return new StatusBar( context, notificationsController, @@ -268,7 +268,6 @@ public interface StatusBarPhoneModule { statusBarKeyguardViewManager, viewMediatorCallback, initController, - darkIconDispatcher, timeTickHandler, pluginDependencyProvider, keyguardDismissUtil, @@ -279,6 +278,7 @@ public interface StatusBarPhoneModule { dismissCallbackRegistry, demoModeController, notificationShadeDepthController, - statusBarTouchableRegionManager); + statusBarTouchableRegionManager, + notificationIconAreaController); } } diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java index e10225cedc7e..ca9cb08c0a59 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java @@ -63,7 +63,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; -import com.android.systemui.wmshell.WindowManagerShellModule; +import com.android.systemui.wmshell.WMShellModule; import javax.inject.Named; @@ -78,7 +78,7 @@ import dagger.Provides; @Module(includes = { DividerModule.class, QSModule.class, - WindowManagerShellModule.class + WMShellModule.class }, subcomponents = { }) diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java new file mode 100644 index 000000000000..ac47660f3221 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 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.wmshell; + +import android.content.Context; +import android.os.Handler; +import android.view.IWindowManager; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.SystemWindows; +import com.android.wm.shell.common.TransactionPool; + +import dagger.Module; +import dagger.Provides; + +/** + * Provides basic dependencies from {@link com.android.wm.shell}, the dependencies declared here + * should be shared among different branches of SystemUI. + */ +// TODO(b/162923491): Move most of these dependencies into WMSingleton scope. +@Module +public class WMShellBaseModule { + @SysUISingleton + @Provides + static TransactionPool provideTransactionPool() { + return new TransactionPool(); + } + + @SysUISingleton + @Provides + static DisplayController provideDisplayController(Context context, @Main Handler handler, + IWindowManager wmService) { + return new DisplayController(context, handler, wmService); + } + + @SysUISingleton + @Provides + static SystemWindows provideSystemWindows(DisplayController displayController, + IWindowManager wmService) { + return new SystemWindows(displayController, wmService); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index 821150ee7ea6..44bb6ac5a49c 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -16,7 +16,6 @@ package com.android.systemui.wmshell; -import android.content.Context; import android.os.Handler; import android.view.IWindowManager; @@ -26,38 +25,18 @@ import com.android.systemui.pip.phone.PipMenuActivity; import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; -import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; import dagger.Module; import dagger.Provides; /** - * Provides dependencies from {@link com.android.wm.shell}. + * Provides dependencies from {@link com.android.wm.shell} which could be customized among different + * branches of SystemUI. */ -@Module -// TODO(b/161116823) Clean up dependencies after wm shell migration finished. -public class WindowManagerShellModule { - @SysUISingleton - @Provides - static TransactionPool provideTransactionPool() { - return new TransactionPool(); - } - - @SysUISingleton - @Provides - static DisplayController provideDisplayController(Context context, @Main Handler handler, - IWindowManager wmService) { - return new DisplayController(context, handler, wmService); - } - - @SysUISingleton - @Provides - static SystemWindows provideSystemWindows(DisplayController displayController, - IWindowManager wmService) { - return new SystemWindows(displayController, wmService); - } - +// TODO(b/162923491): Move most of these dependencies into WMSingleton scope. +@Module(includes = WMShellBaseModule.class) +public class WMShellModule { @SysUISingleton @Provides static DisplayImeController provideDisplayImeController(IWindowManager wmService, diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index a0e5f73b6a4c..11920233e403 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -182,7 +182,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { // IBiometricsFace@1.0 does not support detection, only authentication. when(mFaceSensorProperties.isEmpty()).thenReturn(false); when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorProperties(0 /* id */, - false /* supportsFaceDetection */)); + false /* supportsFaceDetection */, true /* supportsSelfIllumination */)); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt index 118cffc2d5b8..ca8f79d08ef0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt @@ -44,11 +44,11 @@ public class MediaPlayerDataTest : SysuiTestCase() { fun addPlayingThenRemote() { val playerIsPlaying = mock(MediaControlPanel::class.java) whenever(playerIsPlaying.isPlaying).thenReturn(true) - val dataIsPlaying = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying = createMediaData("app1", LOCAL, !RESUMPTION) val playerIsRemote = mock(MediaControlPanel::class.java) whenever(playerIsRemote.isPlaying).thenReturn(false) - val dataIsRemote = createMediaData(!LOCAL, !RESUMPTION) + val dataIsRemote = createMediaData("app2", !LOCAL, !RESUMPTION) MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying) MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote) @@ -62,11 +62,11 @@ public class MediaPlayerDataTest : SysuiTestCase() { fun switchPlayersPlaying() { val playerIsPlaying1 = mock(MediaControlPanel::class.java) whenever(playerIsPlaying1.isPlaying).thenReturn(true) - val dataIsPlaying1 = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying1 = createMediaData("app1", LOCAL, !RESUMPTION) val playerIsPlaying2 = mock(MediaControlPanel::class.java) whenever(playerIsPlaying2.isPlaying).thenReturn(false) - val dataIsPlaying2 = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying2 = createMediaData("app2", LOCAL, !RESUMPTION) MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1) MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2) @@ -86,23 +86,23 @@ public class MediaPlayerDataTest : SysuiTestCase() { fun fullOrderTest() { val playerIsPlaying = mock(MediaControlPanel::class.java) whenever(playerIsPlaying.isPlaying).thenReturn(true) - val dataIsPlaying = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying = createMediaData("app1", LOCAL, !RESUMPTION) val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java) whenever(playerIsPlayingAndRemote.isPlaying).thenReturn(true) - val dataIsPlayingAndRemote = createMediaData(!LOCAL, !RESUMPTION) + val dataIsPlayingAndRemote = createMediaData("app2", !LOCAL, !RESUMPTION) val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java) whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false) - val dataIsStoppedAndLocal = createMediaData(LOCAL, !RESUMPTION) + val dataIsStoppedAndLocal = createMediaData("app3", LOCAL, !RESUMPTION) val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java) whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false) - val dataIsStoppedAndRemote = createMediaData(!LOCAL, !RESUMPTION) + val dataIsStoppedAndRemote = createMediaData("app4", !LOCAL, !RESUMPTION) val playerCanResume = mock(MediaControlPanel::class.java) whenever(playerCanResume.isPlaying).thenReturn(false) - val dataCanResume = createMediaData(LOCAL, RESUMPTION) + val dataCanResume = createMediaData("app5", LOCAL, RESUMPTION) MediaPlayerData.addMediaPlayer("3", dataIsStoppedAndLocal, playerIsStoppedAndLocal) MediaPlayerData.addMediaPlayer("5", dataIsStoppedAndRemote, playerIsStoppedAndRemote) @@ -116,7 +116,7 @@ public class MediaPlayerDataTest : SysuiTestCase() { playerIsStoppedAndLocal, playerCanResume, playerIsStoppedAndRemote).inOrder() } - private fun createMediaData(isLocalSession: Boolean, resumption: Boolean) = - MediaData(0, false, 0, null, null, null, null, null, emptyList(), emptyList<Int>(), "", + private fun createMediaData(app: String, isLocalSession: Boolean, resumption: Boolean) = + MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), "", null, null, null, true, null, isLocalSession, resumption, null, false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index c35ada7c3501..1259d28c3400 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -19,12 +19,10 @@ package com.android.systemui.statusbar; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -46,9 +44,9 @@ import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java index ea1b498801ec..baeedcfc3fc5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java @@ -32,14 +32,17 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -54,109 +57,126 @@ public class VisualStabilityManagerTest extends SysuiTestCase { private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class); private NotificationEntry mEntry; + private StatusBarStateController.StateListener mStatusBarStateListener; + private WakefulnessLifecycle.Observer mWakefulnessObserver; + @Before public void setUp() { + StatusBarStateController statusBarStateController = mock(StatusBarStateController.class); + WakefulnessLifecycle wakefulnessLifecycle = mock(WakefulnessLifecycle.class); + mTestableLooper = TestableLooper.get(this); mVisualStabilityManager = new VisualStabilityManager( mock(NotificationEntryManager.class), - new Handler(mTestableLooper.getLooper())); + new Handler(mTestableLooper.getLooper()), + statusBarStateController, + wakefulnessLifecycle); - mVisualStabilityManager.setUpWithPresenter(mock(NotificationPresenter.class)); mVisualStabilityManager.setVisibilityLocationProvider(mLocationProvider); mEntry = new NotificationEntryBuilder().build(); mEntry.setRow(mRow); when(mRow.getEntry()).thenReturn(mEntry); + + ArgumentCaptor<StatusBarStateController.StateListener> stateListenerCaptor = + ArgumentCaptor.forClass(StatusBarStateController.StateListener.class); + verify(statusBarStateController).addCallback(stateListenerCaptor.capture()); + mStatusBarStateListener = stateListenerCaptor.getValue(); + + ArgumentCaptor<WakefulnessLifecycle.Observer> wakefulnessObserverCaptor = + ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class); + verify(wakefulnessLifecycle).addObserver(wakefulnessObserverCaptor.capture()); + mWakefulnessObserver = wakefulnessObserverCaptor.getValue(); } @Test public void testPanelExpansion() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); - mVisualStabilityManager.setPanelExpanded(false); + setPanelExpanded(false); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testScreenOn() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testReorderingAllowedChangesScreenOn() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.isReorderingAllowed()); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); assertTrue(mVisualStabilityManager.isReorderingAllowed()); } @Test public void testReorderingAllowedChangesPanel() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.isReorderingAllowed()); - mVisualStabilityManager.setPanelExpanded(false); + setPanelExpanded(false); assertTrue(mVisualStabilityManager.isReorderingAllowed()); } @Test public void testCallBackCalledScreenOn() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); verify(mCallback).onChangeAllowed(); } @Test public void testCallBackCalledPanelExpanded() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setPanelExpanded(false); + setPanelExpanded(false); verify(mCallback).onChangeAllowed(); } @Test public void testCallBackExactlyOnce() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setScreenOn(false); - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); + setScreenOn(true); + setScreenOn(false); verify(mCallback).onChangeAllowed(); } @Test public void testCallBackCalledContinuouslyWhenRequested() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, true /* persistent */); - mVisualStabilityManager.setScreenOn(false); - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); + setScreenOn(true); + setScreenOn(false); verify(mCallback, times(2)).onChangeAllowed(); } @Test public void testAddedCanReorder() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.notifyViewAddition(mRow); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testReorderingVisibleHeadsUpNotAllowed() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); when(mLocationProvider.isInVisibleLocation(any(NotificationEntry.class))).thenReturn(true); mVisualStabilityManager.onHeadsUpStateChanged(mEntry, true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); @@ -164,8 +184,8 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testReorderingVisibleHeadsUpAllowed() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); when(mLocationProvider.isInVisibleLocation(any(NotificationEntry.class))).thenReturn(false); mVisualStabilityManager.onHeadsUpStateChanged(mEntry, true); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); @@ -173,8 +193,8 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testReorderingVisibleHeadsUpAllowedOnce() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); when(mLocationProvider.isInVisibleLocation(any(NotificationEntry.class))).thenReturn(false); mVisualStabilityManager.onHeadsUpStateChanged(mEntry, true); mVisualStabilityManager.onReorderingFinished(); @@ -183,33 +203,33 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testPulsing() { - mVisualStabilityManager.setPulsing(true); + setPulsing(true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); - mVisualStabilityManager.setPulsing(false); + setPulsing(false); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testReorderingAllowedChanges_Pulsing() { - mVisualStabilityManager.setPulsing(true); + setPulsing(true); assertFalse(mVisualStabilityManager.isReorderingAllowed()); - mVisualStabilityManager.setPulsing(false); + setPulsing(false); assertTrue(mVisualStabilityManager.isReorderingAllowed()); } @Test public void testCallBackCalled_Pulsing() { - mVisualStabilityManager.setPulsing(true); + setPulsing(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setPulsing(false); + setPulsing(false); verify(mCallback).onChangeAllowed(); } @Test public void testTemporarilyAllowReorderingNotifiesCallbacks() { // GIVEN having the panel open (which would block reordering) - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setPanelExpanded(true); + setScreenOn(true); + setPanelExpanded(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); // WHEN we temprarily allow reordering @@ -223,7 +243,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testTemporarilyAllowReorderingDoesntOverridePulsing() { // GIVEN we are in a pulsing state - mVisualStabilityManager.setPulsing(true); + setPulsing(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); // WHEN we temprarily allow reordering @@ -237,8 +257,8 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testTemporarilyAllowReorderingExpires() { // GIVEN having the panel open (which would block reordering) - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setPanelExpanded(true); + setScreenOn(true); + setPanelExpanded(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); // WHEN we temprarily allow reordering and then wait until the window expires @@ -249,4 +269,20 @@ public class VisualStabilityManagerTest extends SysuiTestCase { // THEN reordering is no longer allowed assertFalse(mVisualStabilityManager.isReorderingAllowed()); } + + private void setPanelExpanded(boolean expanded) { + mStatusBarStateListener.onExpandedChanged(expanded); + } + + private void setPulsing(boolean pulsing) { + mStatusBarStateListener.onPulsingChanged(pulsing); + } + + private void setScreenOn(boolean screenOn) { + if (screenOn) { + mWakefulnessObserver.onStartedWakingUp(); + } else { + mWakefulnessObserver.onFinishedGoingToSleep(); + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java new file mode 100644 index 000000000000..605b4d18d2f1 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2020 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.notification.collection.coordinator; + +import static junit.framework.Assert.assertFalse; + +import static org.junit.Assert.assertTrue; +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.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable; +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; + +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.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class VisualStabilityCoordinatorTest extends SysuiTestCase { + + private VisualStabilityCoordinator mCoordinator; + + // captured listeners and pluggables: + private NotifCollectionListener mCollectionListener; + + @Mock private NotifPipeline mNotifPipeline; + @Mock private WakefulnessLifecycle mWakefulnessLifecycle; + @Mock private StatusBarStateController mStatusBarStateController; + @Mock private Pluggable.PluggableListener<NotifStabilityManager> mInvalidateListener; + @Mock private HeadsUpManager mHeadsUpManager; + + @Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor; + @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor; + @Captor private ArgumentCaptor<NotifStabilityManager> mNotifStabilityManagerCaptor; + @Captor private ArgumentCaptor<NotifCollectionListener> mNotifCollectionListenerCaptor; + + private FakeSystemClock mFakeSystemClock = new FakeSystemClock(); + private FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock); + + private WakefulnessLifecycle.Observer mWakefulnessObserver; + private StatusBarStateController.StateListener mStatusBarStateListener; + private NotifStabilityManager mNotifStabilityManager; + private NotificationEntry mEntry; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mCoordinator = new VisualStabilityCoordinator( + mHeadsUpManager, + mWakefulnessLifecycle, + mStatusBarStateController, + mFakeExecutor); + + mCoordinator.attach(mNotifPipeline); + + // capture arguments: + verify(mWakefulnessLifecycle).addObserver(mWakefulnessObserverCaptor.capture()); + mWakefulnessObserver = mWakefulnessObserverCaptor.getValue(); + + verify(mStatusBarStateController).addCallback(mSBStateListenerCaptor.capture()); + mStatusBarStateListener = mSBStateListenerCaptor.getValue(); + + verify(mNotifPipeline).setVisualStabilityManager(mNotifStabilityManagerCaptor.capture()); + mNotifStabilityManager = mNotifStabilityManagerCaptor.getValue(); + mNotifStabilityManager.setInvalidationListener(mInvalidateListener); + + mEntry = new NotificationEntryBuilder() + .setPkg("testPkg1") + .build(); + + when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(false); + } + + @Test + public void testScreenOff_groupAndSectionChangesAllowed() { + // GIVEN screen is off, panel isn't expanded and device isn't pulsing + setScreenOn(false); + setPanelExpanded(false); + setPulsing(false); + + // THEN group changes are allowed + assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are allowed + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPanelNotExpanded_groupAndSectionChangesAllowed() { + // GIVEN screen is on but the panel isn't expanded and device isn't pulsing + setScreenOn(true); + setPanelExpanded(false); + setPulsing(false); + + // THEN group changes are allowed + assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are allowed + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPanelExpanded_groupAndSectionChangesNotAllowed() { + // GIVEN the panel true expanded and device isn't pulsing + setScreenOn(true); + setPanelExpanded(true); + setPulsing(false); + + // THEN group changes are NOT allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are NOT allowed + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPulsing_screenOff_groupAndSectionChangesNotAllowed() { + // GIVEN the device is pulsing and screen is off + setScreenOn(false); + setPulsing(true); + + // THEN group changes are NOT allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are NOT allowed + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPulsing_panelNotExpanded_groupAndSectionChangesNotAllowed() { + // GIVEN the device is pulsing and screen is off with the panel not expanded + setScreenOn(false); + setPanelExpanded(false); + setPulsing(true); + + // THEN group changes are NOT allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are NOT allowed + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testOverrideReorderingSuppression_onlySectionChangesAllowed() { + // GIVEN section changes typically wouldn't be allowed because the panel is expanded and + // we're not pulsing + setScreenOn(true); + setPanelExpanded(true); + setPulsing(true); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + + // THEN group changes aren't allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are allowed for this notification but not other notifications + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + assertFalse(mNotifStabilityManager.isSectionChangeAllowed( + new NotificationEntryBuilder() + .setPkg("testPkg2") + .build())); + } + + @Test + public void testTemporarilyAllowSectionChanges_callsInvalidate() { + // GIVEN section changes typically wouldn't be allowed because the panel is expanded + setScreenOn(true); + setPanelExpanded(true); + setPulsing(false); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.uptimeMillis()); + + // THEN the notification list is invalidated + verifyInvalidateCalled(true); + } + + @Test + public void testTemporarilyAllowSectionChanges_noInvalidationCalled() { + // GIVEN section changes typically WOULD be allowed + setScreenOn(false); + setPanelExpanded(false); + setPulsing(false); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + + // THEN invalidate is not called because this entry was never suppressed from reordering + verifyInvalidateCalled(false); + } + + @Test + public void testTemporarilyAllowSectionChangesTimeout() { + // GIVEN section changes typically WOULD be allowed + setScreenOn(false); + setPanelExpanded(false); + setPulsing(false); + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + + // THEN invalidate is not called because this entry was never suppressed from reordering; + // THEN section changes are allowed for this notification + verifyInvalidateCalled(false); + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // WHEN we're pulsing (now disallowing reordering) + setPulsing(true); + + // THEN we're still allowed to reorder this section because it's still in the list of + // notifications to allow section changes + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // WHEN the timeout for the temporarily allow section reordering runnable is finsihed + mFakeExecutor.advanceClockToNext(); + mFakeExecutor.runNextReady(); + + // THEN section changes aren't allowed anymore + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testTemporarilyAllowSectionChanges_isPulsingChangeBeforeTimeout() { + // GIVEN section changes typically wouldn't be allowed because the device is pulsing + setScreenOn(false); + setPanelExpanded(false); + setPulsing(true); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + verifyInvalidateCalled(true); // can now reorder, so invalidates + + // WHEN reordering is now allowed because device isn't pulsing anymore + setPulsing(false); + + // THEN invalidate isn't called since reordering was already allowed + verifyInvalidateCalled(false); + } + + @Test + public void testNeverSuppressedChanges_noInvalidationCalled() { + // GIVEN no notifications are currently being suppressed from grouping nor being sorted + + // WHEN device isn't pulsing anymore + setPulsing(false); + + // WHEN screen isn't on + setScreenOn(false); + + // WHEN panel isn't expanded + setPanelExpanded(false); + + // THEN we never see any calls to invalidate since there weren't any notifications that + // were being suppressed from grouping or section changes + verifyInvalidateCalled(false); + } + + @Test + public void testHeadsUp_allowedToChangeGroupAndSection() { + // GIVEN group + section changes disallowed + setScreenOn(true); + setPanelExpanded(true); + setPulsing(true); + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // GIVEN mEntry is a HUN + when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true); + + // THEN group + section changes are allowed + assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + } + + private void setPulsing(boolean pulsing) { + mStatusBarStateListener.onPulsingChanged(pulsing); + } + + private void setScreenOn(boolean screenOn) { + if (screenOn) { + mWakefulnessObserver.onStartedWakingUp(); + } else { + mWakefulnessObserver.onFinishedGoingToSleep(); + } + } + + private void setPanelExpanded(boolean expanded) { + mStatusBarStateListener.onExpandedChanged(expanded); + } + + private void verifyInvalidateCalled(boolean invalidateCalled) { + if (invalidateCalled) { + verify(mInvalidateListener).onPluggableInvalidated(mNotifStabilityManager); + } else { + verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager); + } + + reset(mInvalidateListener); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 83fc82634b60..3c5aa1ae9519 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -79,7 +79,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.BubblesTestActivity; import com.android.systemui.statusbar.SbnBuilder; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.phone.ShadeController; @@ -135,7 +134,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Mock private PackageManager mMockPackageManager; @Mock - private VisualStabilityManager mVisualStabilityManager; + private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private BubbleController mBubbleController; @Mock @@ -244,7 +243,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -268,7 +267,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -293,7 +292,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mLauncherApps, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -319,7 +318,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -344,7 +343,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -368,7 +367,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -403,7 +402,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, entry, @@ -428,7 +427,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -457,7 +456,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -481,7 +480,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -509,7 +508,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -537,7 +536,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -568,7 +567,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -598,7 +597,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -642,7 +641,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -685,7 +684,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -729,7 +728,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -766,7 +765,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -802,7 +801,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -840,7 +839,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -876,7 +875,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -912,7 +911,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -947,7 +946,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -981,7 +980,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -1006,7 +1005,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -1041,7 +1040,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -1081,7 +1080,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 54ccc4d8320d..c2c40cac3d0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -74,7 +74,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; @@ -114,7 +113,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { @Rule public MockitoRule mockito = MockitoJUnit.rule(); @Mock private MetricsLogger mMetricsLogger; - @Mock private VisualStabilityManager mVisualStabilityManager; + @Mock private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private NotificationPresenter mPresenter; @Mock private NotificationActivityStarter mNotificationActivityStarter; @Mock private NotificationListContainer mNotificationListContainer; @@ -143,19 +142,21 @@ public class NotificationGutsManagerTest extends SysuiTestCase { mDependency.injectTestDependency(DeviceProvisionedController.class, mDeviceProvisionedController); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); - mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager); + mDependency.injectTestDependency( + OnUserInteractionCallback.class, + mOnUserInteractionCallback); mDependency.injectTestDependency(BubbleController.class, mBubbleController); mDependency.injectMockDependency(NotificationLockscreenUserManager.class); mHandler = Handler.createAsync(mTestableLooper.getLooper()); mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this)); when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); - mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager, + mGutsManager = new NotificationGutsManager(mContext, () -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider, mINotificationManager, mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker, mProvider, mAssistantFeedbackController, mBubbleController, - new UiEventLoggerFake()); + new UiEventLoggerFake(), mOnUserInteractionCallback); mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer, mCheckSaveListener, mOnSettingsClickListener); mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); @@ -360,7 +361,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { verify(notificationInfoView).bindNotification( any(PackageManager.class), any(INotificationManager.class), - eq(mVisualStabilityManager), + eq(mOnUserInteractionCallback), eq(mChannelEditorDialogController), eq(statusBarNotification.getPackageName()), any(NotificationChannel.class), @@ -394,7 +395,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { verify(notificationInfoView).bindNotification( any(PackageManager.class), any(INotificationManager.class), - eq(mVisualStabilityManager), + eq(mOnUserInteractionCallback), eq(mChannelEditorDialogController), eq(statusBarNotification.getPackageName()), any(NotificationChannel.class), @@ -426,7 +427,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { verify(notificationInfoView).bindNotification( any(PackageManager.class), any(INotificationManager.class), - eq(mVisualStabilityManager), + eq(mOnUserInteractionCallback), eq(mChannelEditorDialogController), eq(statusBarNotification.getPackageName()), any(NotificationChannel.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java index fd8b72bb15db..02a3e11f312b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java @@ -66,7 +66,6 @@ import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; @@ -114,7 +113,7 @@ public class NotificationInfoTest extends SysuiTestCase { @Mock private PackageManager mMockPackageManager; @Mock - private VisualStabilityManager mVisualStabilityManager; + private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private ChannelEditorDialogController mChannelEditorDialogController; @@ -181,7 +180,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -207,7 +206,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -229,7 +228,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -260,7 +259,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -283,7 +282,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -311,7 +310,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -334,7 +333,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -356,7 +355,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mDefaultNotificationChannel, @@ -382,7 +381,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mDefaultNotificationChannel, @@ -404,7 +403,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -427,7 +426,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -455,7 +454,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -478,7 +477,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -502,7 +501,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -518,7 +517,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -541,7 +540,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), @@ -569,7 +568,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -593,7 +592,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -617,7 +616,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -643,7 +642,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -665,7 +664,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -688,7 +687,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -709,7 +708,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -730,7 +729,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -751,7 +750,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -774,7 +773,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -798,7 +797,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -825,7 +824,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -852,7 +851,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -879,7 +878,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -914,7 +913,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -942,7 +941,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -982,7 +981,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1017,7 +1016,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1047,7 +1046,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1082,7 +1081,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1120,7 +1119,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1157,7 +1156,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1175,7 +1174,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.findViewById(R.id.done).performClick(); mNotificationInfo.handleCloseControls(true, false); - verify(mVisualStabilityManager).temporarilyAllowReordering(); + verify(mOnUserInteractionCallback).onImportanceChanged(mEntry); } @Test @@ -1185,7 +1184,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1216,7 +1215,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1250,7 +1249,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1283,7 +1282,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1316,7 +1315,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1342,7 +1341,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index fa2fa04abaa3..9a8678f01870 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -424,7 +424,8 @@ public class NotificationTestHelper { mock(ExpandableNotificationRow.CoordinateOnClickListener.class), mock(FalsingManager.class), mStatusBarStateController, - mPeopleNotificationIdentifier); + mPeopleNotificationIdentifier, + mock(OnUserInteractionCallback.class)); row.setAboveShelfChangedListener(aboveShelf -> { }); mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags); inflateAndWait(entry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index fec467706b7b..9a6674e165e4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -74,13 +74,13 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -239,7 +239,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setScrimController(mock(ScrimController.class)); mStackScroller.setGroupManager(mGroupManager); mStackScroller.setEmptyShadeView(mEmptyShadeView); - mStackScroller.setIconAreaController(mNotificationIconAreaController); // Stub out functionality that isn't necessary to test. doNothing().when(mBar) @@ -437,9 +436,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() { + public void testReInflatesFooterViews() { clearInvocations(mStackScroller); - mStackScroller.onDensityOrFontScaleChanged(); + mStackScroller.reinflateViews(); verify(mStackScroller).setFooterView(any()); verify(mStackScroller).setEmptyShadeView(any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java new file mode 100644 index 000000000000..e3acf0213725 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2020 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.notification.stack; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.tuner.TunerService; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for {@link NotificationStackScrollLayoutController}. + */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class NotificationStackScrollerControllerTest extends SysuiTestCase { + + @Mock + private NotificationGutsManager mNotificationGutsManager; + @Mock + private HeadsUpManagerPhone mHeadsUpManager; + @Mock + private NotificationRoundnessManager mNotificationRoundnessManager; + @Mock + private TunerService mTunerService; + @Mock + private AmbientState mAmbientState; + @Mock + private DynamicPrivacyController mDynamicPrivacyController; + @Mock + private ConfigurationController mConfigurationController; + @Mock + private NotificationStackScrollLayout mNotificationStackScrollLayout; + + NotificationStackScrollLayoutController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mController = new NotificationStackScrollLayoutController( + true, + mNotificationGutsManager, + mHeadsUpManager, + mNotificationRoundnessManager, + mTunerService, + mDynamicPrivacyController, + mConfigurationController + ); + + when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); + } + + + @Test + public void testAttach_viewAlreadyAttached() { + mController.attach(mNotificationStackScrollLayout); + + verify(mConfigurationController).addCallback( + any(ConfigurationController.ConfigurationListener.class)); + } + @Test + public void testAttach_viewAttachedAfterInit() { + when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(false); + + mController.attach(mNotificationStackScrollLayout); + + verify(mConfigurationController, never()).addCallback( + any(ConfigurationController.ConfigurationListener.class)); + + mController.mOnAttachStateChangeListener.onViewAttachedToWindow( + mNotificationStackScrollLayout); + + verify(mConfigurationController).addCallback( + any(ConfigurationController.ConfigurationListener.class)); + } + + @Test + public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() { + mController.attach(mNotificationStackScrollLayout); + mController.mConfigurationListener.onDensityOrFontScaleChanged(); + verify(mNotificationStackScrollLayout).reinflateViews(); + } +} 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 index 713a7c92e1cf..37ccac0b23b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -46,7 +46,6 @@ 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; @@ -70,7 +69,6 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private ScrimController mScrimController; @Mock private DozeScrimController mDozeScrimController; - @Mock private VisualStabilityManager mVisualStabilityManager; @Mock private KeyguardViewMediator mKeyguardViewMediator; @Mock private StatusBarStateControllerImpl mStatusBarStateController; @Mock private BatteryController mBatteryController; @@ -100,13 +98,16 @@ public class DozeServiceHostTest extends SysuiTestCase { mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager, mBatteryController, mScrimController, () -> mBiometricUnlockController, mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, - mKeyguardUpdateMonitor, mVisualStabilityManager, mPulseExpansionHandler, + mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController, mNotificationWakeUpCoordinator, - mLockscreenLockIconController, mAuthController); - - mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController, - mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController, - mNotificationPanel, mAmbientIndicationContainer); + mLockscreenLockIconController, mAuthController, mNotificationIconAreaController); + + mDozeServiceHost.initialize( + mStatusBar, + mStatusBarKeyguardViewManager, + mNotificationShadeWindowViewController, + mNotificationPanel, + mAmbientIndicationContainer); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index 48bf2db0be6a..2239b1b96ac8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -34,9 +34,9 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.AlertingNotificationManager; import com.android.systemui.statusbar.AlertingNotificationManagerTest; import com.android.systemui.statusbar.NotificationShadeWindowController; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java index 18cb6675f384..5222ffff2637 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.phone; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,10 +28,12 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.demomode.DemoModeController; +import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import org.junit.Before; import org.junit.Test; @@ -48,8 +49,6 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase { @Mock private NotificationListener mListener; @Mock - StatusBar mStatusBar; - @Mock StatusBarStateController mStatusBarStateController; @Mock NotificationWakeUpCoordinator mWakeUpCoordinator; @@ -58,28 +57,37 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase { @Mock NotificationMediaManager mNotificationMediaManager; @Mock - NotificationIconContainer mNotificationIconContainer; - @Mock DozeParameters mDozeParameters; @Mock - NotificationShadeWindowView mNotificationShadeWindowView; + CommonNotifCollection mNotifCollection; + @Mock + DarkIconDispatcher mDarkIconDispatcher; + @Mock + StatusBarWindowController mStatusBarWindowController; private NotificationIconAreaController mController; @Mock private BubbleController mBubbleController; @Mock private DemoModeController mDemoModeController; + @Mock + private NotificationIconContainer mAodIcons; @Before public void setup() { MockitoAnnotations.initMocks(this); - when(mStatusBar.getNotificationShadeWindowView()).thenReturn(mNotificationShadeWindowView); - when(mNotificationShadeWindowView.findViewById(anyInt())).thenReturn( - mNotificationIconContainer); - - mController = new NotificationIconAreaController(mContext, mStatusBar, - mStatusBarStateController, mWakeUpCoordinator, mKeyguardBypassController, - mNotificationMediaManager, mListener, mDozeParameters, mBubbleController, - mDemoModeController); + mController = new NotificationIconAreaController( + mContext, + mStatusBarStateController, + mWakeUpCoordinator, + mKeyguardBypassController, + mNotificationMediaManager, + mListener, + mDozeParameters, + mBubbleController, + mDemoModeController, + mDarkIconDispatcher, + mStatusBarWindowController); + mController.setupAodIcons(mAodIcons); } @Test @@ -100,7 +108,7 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase { public void testAppearResetsTranslation() { when(mDozeParameters.shouldControlScreenOff()).thenReturn(false); mController.appearAodIcons(); - verify(mNotificationIconContainer).setTranslationY(0); - verify(mNotificationIconContainer).setAlpha(1.0f); + verify(mAodIcons).setTranslationY(0); + verify(mAodIcons).setAlpha(1.0f); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index a0c0e7979084..c9e9d94d8a79 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -251,9 +251,13 @@ public class NotificationPanelViewTest extends SysuiTestCase { mConversationNotificationManager, mMediaHiearchyManager, mBiometricUnlockController, mStatusBarKeyguardViewManager, () -> mKeyguardClockSwitchController, - mNotificationStackScrollLayoutController); - mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager, - mNotificationShelfController, mNotificationAreaController, mScrimController); + mNotificationStackScrollLayoutController, + mNotificationAreaController); + mNotificationPanelViewController.initDependencies( + mStatusBar, + mGroupManager, + mNotificationShelfController, + mScrimController); mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); mNotificationPanelViewController.setBar(mPanelBar); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index a71b10cf9264..3f631b1f6282 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -73,7 +73,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -132,7 +132,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private Intent mContentIntentInner; @Mock - private OnDismissCallback mOnDismissCallback; + private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private NotificationActivityStarter mNotificationActivityStarter; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -210,7 +210,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mFeatureFlags, mock(MetricsLogger.class), mock(StatusBarNotificationActivityStarterLogger.class), - mOnDismissCallback) + mOnUserInteractionCallback) .setStatusBar(mStatusBar) .setNotificationPresenter(mock(NotificationPresenter.class)) .setNotificationPanelViewController(mock(NotificationPanelViewController.class)) @@ -267,7 +267,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { eq(sbn.getKey()), any(NotificationVisibility.class)); // Notification calls dismiss callback to remove notification due to FLAG_AUTO_CANCEL - verify(mOnDismissCallback).onDismiss(mNotificationRow.getEntry(), REASON_CLICK); + verify(mOnUserInteractionCallback).onDismiss(mNotificationRow.getEntry(), REASON_CLICK); } @Test @@ -296,7 +296,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { verifyZeroInteractions(mContentIntent); // Notification should not be cancelled. - verify(mOnDismissCallback, never()).onDismiss(eq(mNotificationRow.getEntry()), anyInt()); + verify(mOnUserInteractionCallback, never()).onDismiss(eq(mNotificationRow.getEntry()), + anyInt()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java index e46aa04c4504..c0ebfadf6b57 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java @@ -50,9 +50,9 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; 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 8a1d95ea4478..8462386aaf2d 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 @@ -117,9 +117,9 @@ 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.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl; @@ -405,7 +405,6 @@ public class StatusBarTest extends SysuiTestCase { mStatusBarKeyguardViewManager, mViewMediatorCallback, mInitController, - mDarkIconDispatcher, new Handler(TestableLooper.get(this).getLooper()), mPluginDependencyProvider, mKeyguardDismissUtil, @@ -416,7 +415,8 @@ public class StatusBarTest extends SysuiTestCase { mDismissCallbackRegistry, mDemoModeController, mNotificationShadeDepthControllerLazy, - mStatusBarTouchableRegionManager); + mStatusBarTouchableRegionManager, + mNotificationIconAreaController); when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn( mLockIconContainer); @@ -434,7 +434,6 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.mNotificationShadeWindowView = mNotificationShadeWindowView; mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController; mStatusBar.mDozeScrimController = mDozeScrimController; - mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController; mStatusBar.mPresenter = mNotificationPresenter; mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController; mStatusBar.mBarService = mBarService; diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 833aeecc4c47..c41f4007aa59 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1530,12 +1530,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub int serviceCount = userState.mBoundServices.size(); for (int i = 0; i < serviceCount; i++) { AccessibilityServiceConnection service = userState.mBoundServices.get(i); - relevantEventTypes |= isClientInPackageWhitelist(service.getServiceInfo(), client) + relevantEventTypes |= isClientInPackageAllowlist(service.getServiceInfo(), client) ? service.getRelevantEventTypes() : 0; } - relevantEventTypes |= isClientInPackageWhitelist( + relevantEventTypes |= isClientInPackageAllowlist( mUiAutomationManager.getServiceInfo(), client) ? mUiAutomationManager.getRelevantEventTypes() : 0; @@ -1571,7 +1571,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private static boolean isClientInPackageWhitelist( + private static boolean isClientInPackageAllowlist( @Nullable AccessibilityServiceInfo serviceInfo, Client client) { if (serviceInfo == null) return false; @@ -1590,7 +1590,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Slog.d(LOG_TAG, "Dropping events: " + Arrays.toString(clientPackages) + " -> " + serviceInfo.getComponentName().flattenToShortString() - + " due to not being in package whitelist " + + " due to not being in package allowlist " + Arrays.toString(serviceInfo.packageNames)); } } @@ -1991,9 +1991,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } private void updateLegacyCapabilitiesLocked(AccessibilityUserState userState) { - // Up to JB-MR1 we had a white list with services that can enable touch + // Up to JB-MR1 we had a allowlist with services that can enable touch // exploration. When a service is first started we show a dialog to the - // use to get a permission to white list the service. + // use to get a permission to allowlist the service. final int installedServiceCount = userState.mInstalledServices.size(); for (int i = 0; i < installedServiceCount; i++) { AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); @@ -2261,9 +2261,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } if (service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1) { - // Up to JB-MR1 we had a white list with services that can enable touch + // Up to JB-MR1 we had a allowlist with services that can enable touch // exploration. When a service is first started we show a dialog to the - // use to get a permission to white list the service. + // use to get a permission to allowlist the service. if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { return true; } else if (mEnableTouchExplorationDialog == null diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 97f3b373f63e..ee794badad88 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -20,14 +20,14 @@ import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.Manifest.permission.OBSERVE_NETWORK_POLICY; import static android.Manifest.permission.SHUTDOWN; -import static android.net.INetd.FIREWALL_BLACKLIST; +import static android.net.INetd.FIREWALL_ALLOWLIST; import static android.net.INetd.FIREWALL_CHAIN_DOZABLE; import static android.net.INetd.FIREWALL_CHAIN_NONE; import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE; import static android.net.INetd.FIREWALL_CHAIN_STANDBY; +import static android.net.INetd.FIREWALL_DENYLIST; import static android.net.INetd.FIREWALL_RULE_ALLOW; import static android.net.INetd.FIREWALL_RULE_DENY; -import static android.net.INetd.FIREWALL_WHITELIST; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; @@ -1575,7 +1575,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { enforceSystemUid(); try { mNetdService.firewallSetFirewallType( - enabled ? INetd.FIREWALL_WHITELIST : INetd.FIREWALL_BLACKLIST); + enabled ? INetd.FIREWALL_ALLOWLIST : INetd.FIREWALL_DENYLIST); mFirewallEnabled = enabled; } catch (RemoteException | ServiceSpecificException e) { throw new IllegalStateException(e); @@ -1608,7 +1608,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { int numUids = 0; if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName); - if (getFirewallType(chain) == FIREWALL_WHITELIST) { + if (getFirewallType(chain) == FIREWALL_ALLOWLIST) { // Close all sockets on all non-system UIDs... ranges = new UidRangeParcel[] { // TODO: is there a better way of finding all existing users? If so, we could @@ -1714,13 +1714,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private int getFirewallType(int chain) { switch (chain) { case FIREWALL_CHAIN_STANDBY: - return FIREWALL_BLACKLIST; + return FIREWALL_DENYLIST; case FIREWALL_CHAIN_DOZABLE: - return FIREWALL_WHITELIST; + return FIREWALL_ALLOWLIST; case FIREWALL_CHAIN_POWERSAVE: - return FIREWALL_WHITELIST; + return FIREWALL_ALLOWLIST; default: - return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST; + return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST; } } @@ -1822,7 +1822,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private @NonNull String getFirewallRuleName(int chain, int rule) { String ruleName; - if (getFirewallType(chain) == FIREWALL_WHITELIST) { + if (getFirewallType(chain) == FIREWALL_ALLOWLIST) { if (rule == FIREWALL_RULE_ALLOW) { ruleName = "allow"; } else { @@ -1856,7 +1856,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private int getFirewallRuleType(int chain, int rule) { if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { - return getFirewallType(chain) == FIREWALL_WHITELIST + return getFirewallType(chain) == FIREWALL_ALLOWLIST ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW; } return rule; diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index d1d9c0e3a285..b72985cc8f2c 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -1141,13 +1141,6 @@ class StorageManagerService extends IStorageManager.Stub } private void completeUnlockUser(int userId) { - // If user 0 has completed unlock, perform a one-time migration of legacy obb data - // to its new location. This may take time depending on the size of the data to be copied - // so it's done on the StorageManager handler thread. - if (userId == 0) { - mPmInternal.migrateLegacyObbData(); - } - onKeyguardStateChanged(false); // Record user as started so newly mounted volumes kick off events @@ -1540,9 +1533,21 @@ class StorageManagerService extends IStorageManager.Stub mFuseMountedUser.remove(vol.getMountUserId()); } else if (mVoldAppDataIsolationEnabled){ final int userId = vol.getMountUserId(); - mFuseMountedUser.add(userId); // Async remount app storage so it won't block the main thread. new Thread(() -> { + + // If user 0 has completed unlock, perform a one-time migration of legacy + // obb data to its new location. This may take time depending on the size of + // the data to be copied so it's done on the StorageManager worker thread. + // This needs to be finished before start mounting obb directories. + if (userId == 0) { + mPmInternal.migrateLegacyObbData(); + } + + // Add fuse mounted user after migration to prevent ProcessList tries to + // create obb directory before migration is done. + mFuseMountedUser.add(userId); + Map<Integer, String> pidPkgMap = null; // getProcessesWithPendingBindMounts() could fail when a new app process is // starting and it's not planning to mount storage dirs in zygote, but it's diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index df966c1ea6ac..34e63705d781 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -47,8 +47,8 @@ import java.util.ArrayList; * * {@hide} */ -public class SystemServiceManager { - private static final String TAG = "SystemServiceManager"; +public final class SystemServiceManager { + private static final String TAG = SystemServiceManager.class.getSimpleName(); private static final boolean DEBUG = false; private static final int SERVICE_CALL_WARN_TIME_MS = 50; @@ -250,76 +250,76 @@ public class SystemServiceManager { mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); } - private @NonNull TargetUser getTargetUser(@UserIdInt int userHandle) { + private @NonNull TargetUser getTargetUser(@UserIdInt int userId) { final TargetUser targetUser; synchronized (mTargetUsers) { - targetUser = mTargetUsers.get(userHandle); + targetUser = mTargetUsers.get(userId); } - Preconditions.checkState(targetUser != null, "No TargetUser for " + userHandle); + Preconditions.checkState(targetUser != null, "No TargetUser for " + userId); return targetUser; } /** * Starts the given user. */ - public void startUser(final @NonNull TimingsTraceAndSlog t, final @UserIdInt int userHandle) { + public void startUser(@NonNull TimingsTraceAndSlog t, @UserIdInt int userId) { // Create cached TargetUser - final UserInfo userInfo = mUserManagerInternal.getUserInfo(userHandle); - Preconditions.checkState(userInfo != null, "No UserInfo for " + userHandle); + final UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); + Preconditions.checkState(userInfo != null, "No UserInfo for " + userId); synchronized (mTargetUsers) { - mTargetUsers.put(userHandle, new TargetUser(userInfo)); + mTargetUsers.put(userId, new TargetUser(userInfo)); } - onUser(t, START, userHandle); + onUser(t, START, userId); } /** * Unlocks the given user. */ - public void unlockUser(final @UserIdInt int userHandle) { - onUser(UNLOCKING, userHandle); + public void unlockUser(@UserIdInt int userId) { + onUser(UNLOCKING, userId); } /** * Called after the user was unlocked. */ - public void onUserUnlocked(final @UserIdInt int userHandle) { - onUser(UNLOCKED, userHandle); + public void onUserUnlocked(@UserIdInt int userId) { + onUser(UNLOCKED, userId); } /** * Switches to the given user. */ - public void switchUser(final @UserIdInt int from, final @UserIdInt int to) { + public void switchUser(@UserIdInt int from, @UserIdInt int to) { onUser(TimingsTraceAndSlog.newAsyncLog(), SWITCH, to, from); } /** * Stops the given user. */ - public void stopUser(final @UserIdInt int userHandle) { - onUser(STOP, userHandle); + public void stopUser(@UserIdInt int userId) { + onUser(STOP, userId); } /** * Cleans up the given user. */ - public void cleanupUser(final @UserIdInt int userHandle) { - onUser(CLEANUP, userHandle); + public void cleanupUser(@UserIdInt int userId) { + onUser(CLEANUP, userId); // Remove cached TargetUser synchronized (mTargetUsers) { - mTargetUsers.remove(userHandle); + mTargetUsers.remove(userId); } } - private void onUser(@NonNull String onWhat, @UserIdInt int userHandle) { - onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle); + private void onUser(@NonNull String onWhat, @UserIdInt int userId) { + onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userId); } private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, - @UserIdInt int userHandle) { - onUser(t, onWhat, userHandle, UserHandle.USER_NULL); + @UserIdInt int userId) { + onUser(t, onWhat, userId, UserHandle.USER_NULL); } private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 0f2dfcc699e2..757b4e83e120 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -100,15 +100,20 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALL_APPS, int.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.UPDATABLE_DRIVER_ALL_APPS, int.class); sGlobalSettingToTypeMap.put( - Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_DENYLIST, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALLOWLIST, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_DENYLISTS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>( diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 2e8660e1317a..4673ecde7a68 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -2222,7 +2222,8 @@ public final class ProcessList { // access /mnt/user anyway. && app.mountMode != Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE && app.mountMode != Zygote.MOUNT_EXTERNAL_PASS_THROUGH - && app.mountMode != Zygote.MOUNT_EXTERNAL_INSTALLER; + && app.mountMode != Zygote.MOUNT_EXTERNAL_INSTALLER + && app.mountMode != Zygote.MOUNT_EXTERNAL_NONE; } private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index bf7c68a845c5..0a179e89f757 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1283,6 +1283,7 @@ public class AudioService extends IAudioService.Stub } if (isPlatformTelevision()) { + checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller); synchronized (mHdmiClientLock) { if (mHdmiManager != null && mHdmiPlaybackClient != null) { updateHdmiCecSinkLocked(mHdmiCecSink | false); @@ -1302,54 +1303,22 @@ public class AudioService extends IAudioService.Stub } } - /** - * Update volume states for the given device. - * - * This will initialize the volume index if no volume index is available. - * If the device is the currently routed device, fixed/full volume policies will be applied. - * - * @param device a single audio device, ensure that this is not a devices bitmask - * @param caller caller of this method - */ - private void updateVolumeStatesForAudioDevice(int device, String caller) { + private void checkAddAllFixedVolumeDevices(int device, String caller) { final int numStreamTypes = AudioSystem.getNumStreamTypes(); for (int streamType = 0; streamType < numStreamTypes; streamType++) { - updateVolumeStates(device, streamType, caller); - } - } - - /** - * Update volume states for the given device and given stream. - * - * This will initialize the volume index if no volume index is available. - * If the device is the currently routed device, fixed/full volume policies will be applied. - * - * @param device a single audio device, ensure that this is not a devices bitmask - * @param streamType streamType to be updated - * @param caller caller of this method - */ - private void updateVolumeStates(int device, int streamType, String caller) { - if (!mStreamStates[streamType].hasIndexForDevice(device)) { - // set the default value, if device is affected by a full/fix/abs volume rule, it - // will taken into account in checkFixedVolumeDevices() - mStreamStates[streamType].setIndex( - mStreamStates[mStreamVolumeAlias[streamType]] - .getIndex(AudioSystem.DEVICE_OUT_DEFAULT), - device, caller, true /*hasModifyAudioSettings*/); - } - - // Check if device to be updated is routed for the given audio stream - List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributesInt( - new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build()); - for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) { - if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType( - device)) { - mStreamStates[streamType].checkFixedVolumeDevices(); + if (!mStreamStates[streamType].hasIndexForDevice(device)) { + // set the default value, if device is affected by a full/fix/abs volume rule, it + // will taken into account in checkFixedVolumeDevices() + mStreamStates[streamType].setIndex( + mStreamStates[mStreamVolumeAlias[streamType]] + .getIndex(AudioSystem.DEVICE_OUT_DEFAULT), + device, caller, true /*hasModifyAudioSettings*/); + } + mStreamStates[streamType].checkFixedVolumeDevices(); - // Unmute streams if required if device is full volume - if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) { - mStreamStates[streamType].mute(false); - } + // Unmute streams if device is full volume + if (mFullVolumeDevices.contains(device)) { + mStreamStates[streamType].mute(false); } } } @@ -1899,13 +1868,8 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */ public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes( @NonNull AudioAttributes attributes) { - enforceModifyAudioRoutingPermission(); - return getDevicesForAttributesInt(attributes); - } - - protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt( - @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); + enforceModifyAudioRoutingPermission(); return AudioSystem.getDevicesForAttributes(attributes); } @@ -4952,15 +4916,7 @@ public class AudioService extends IAudioService.Stub synchronized (VolumeStreamState.class) { for (int stream = 0; stream < mStreamStates.length; stream++) { if (stream != skipStream) { - int devices = mStreamStates[stream].observeDevicesForStream_syncVSS( - false /*checkOthers*/); - - Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices); - for (Integer device : devicesSet) { - // Update volume states for devices routed for the stream - updateVolumeStates(device, stream, - "AudioService#observeDevicesForStreams"); - } + mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/); } } } @@ -5029,7 +4985,7 @@ public class AudioService extends IAudioService.Stub + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller)); // make sure we have a volume entry for this device, and that volume is updated according // to volume behavior - updateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); + checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); } /** @@ -7251,9 +7207,10 @@ public class AudioService extends IAudioService.Stub // HDMI output removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI); } - updateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI, - "HdmiPlaybackClient.DisplayStatusCallback"); } + + checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, + "HdmiPlaybackClient.DisplayStatusCallback"); } private class MyHdmiControlStatusChangeListenerCallback diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java index 7dd6217016eb..32bb2db77ddc 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java @@ -45,6 +45,7 @@ import android.os.UserManager; import android.provider.Settings; import android.util.Slog; +import com.android.internal.R; import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AcquisitionClient; @@ -275,7 +276,10 @@ class Face10 implements IHwBinder.DeathRecipient { Face10(@NonNull Context context, int sensorId, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { - mFaceSensorProperties = new FaceSensorProperties(sensorId, false /* supportsFaceDetect */); + final boolean supportsSelfIllumination = context.getResources() + .getBoolean(R.bool.config_faceAuthSupportsSelfIllumination); + mFaceSensorProperties = new FaceSensorProperties(sensorId, false /* supportsFaceDetect */, + supportsSelfIllumination); mContext = context; mSensorId = sensorId; mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */); diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java index c0617ca95f9f..54794fecbf5b 100644 --- a/services/core/java/com/android/server/gpu/GpuService.java +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -65,7 +65,7 @@ public class GpuService extends SystemService { private static final String PROD_DRIVER_PROPERTY = "ro.gfx.driver.0"; private static final String DEV_DRIVER_PROPERTY = "ro.gfx.driver.1"; - private static final String GAME_DRIVER_ALLOWLIST_FILENAME = "allowlist.txt"; + private static final String UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST_FILENAME = "allowlist.txt"; private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; private final Context mContext; @@ -77,7 +77,7 @@ public class GpuService extends SystemService { private final boolean mHasProdDriver; private final boolean mHasDevDriver; private ContentResolver mContentResolver; - private long mGameDriverVersionCode; + private long mProdDriverVersionCode; private SettingsObserver mSettingsObserver; private DeviceConfigListener mDeviceConfigListener; @GuardedBy("mLock") @@ -88,7 +88,7 @@ public class GpuService extends SystemService { mContext = context; mProdDriverPackageName = SystemProperties.get(PROD_DRIVER_PROPERTY); - mGameDriverVersionCode = -1; + mProdDriverVersionCode = -1; mDevDriverPackageName = SystemProperties.get(DEV_DRIVER_PROPERTY); mPackageManager = context.getPackageManager(); mHasProdDriver = !TextUtils.isEmpty(mProdDriverPackageName); @@ -117,20 +117,20 @@ public class GpuService extends SystemService { } mSettingsObserver = new SettingsObserver(); mDeviceConfigListener = new DeviceConfigListener(); - fetchGameDriverPackageProperties(); + fetchProductionDriverPackageProperties(); processDenylists(); setDenylist(); - fetchDeveloperDriverPackageProperties(); + fetchPrereleaseDriverPackageProperties(); } } private final class SettingsObserver extends ContentObserver { - private final Uri mGameDriverDenylistsUri = - Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_DENYLISTS); + private final Uri mProdDriverDenylistsUri = + Settings.Global.getUriFor(Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); SettingsObserver() { super(new Handler()); - mContentResolver.registerContentObserver(mGameDriverDenylistsUri, false, this, + mContentResolver.registerContentObserver(mProdDriverDenylistsUri, false, this, UserHandle.USER_ALL); } @@ -140,7 +140,7 @@ public class GpuService extends SystemService { return; } - if (mGameDriverDenylistsUri.equals(uri)) { + if (mProdDriverDenylistsUri.equals(uri)) { processDenylists(); setDenylist(); } @@ -157,9 +157,11 @@ public class GpuService extends SystemService { @Override public void onPropertiesChanged(Properties properties) { synchronized (mDeviceConfigLock) { - if (properties.getKeyset().contains(Settings.Global.GAME_DRIVER_DENYLISTS)) { + if (properties.getKeyset().contains( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS)) { parseDenylists( - properties.getString(Settings.Global.GAME_DRIVER_DENYLISTS, "")); + properties.getString( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, "")); setDenylist(); } } @@ -186,10 +188,10 @@ public class GpuService extends SystemService { case ACTION_PACKAGE_CHANGED: case ACTION_PACKAGE_REMOVED: if (isProdDriver) { - fetchGameDriverPackageProperties(); + fetchProductionDriverPackageProperties(); setDenylist(); } else if (isDevDriver) { - fetchDeveloperDriverPackageProperties(); + fetchPrereleaseDriverPackageProperties(); } break; default: @@ -218,7 +220,7 @@ public class GpuService extends SystemService { } } - private void fetchGameDriverPackageProperties() { + private void fetchProductionDriverPackageProperties() { final ApplicationInfo driverInfo; try { driverInfo = mPackageManager.getApplicationInfo(mProdDriverPackageName, @@ -241,15 +243,16 @@ public class GpuService extends SystemService { // Reset the allowlist. Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_ALLOWLIST, ""); - mGameDriverVersionCode = driverInfo.longVersionCode; + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, ""); + mProdDriverVersionCode = driverInfo.longVersionCode; try { final Context driverContext = mContext.createPackageContext(mProdDriverPackageName, Context.CONTEXT_RESTRICTED); - assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_ALLOWLIST_FILENAME, - Settings.Global.GAME_DRIVER_ALLOWLIST, ","); + assetToSettingsGlobal(mContext, driverContext, + UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST_FILENAME, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, ","); } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { Slog.w(TAG, "driver package '" + mProdDriverPackageName + "' not installed"); @@ -259,11 +262,11 @@ public class GpuService extends SystemService { private void processDenylists() { String base64String = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_GAME_DRIVER, - Settings.Global.GAME_DRIVER_DENYLISTS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); if (base64String == null) { base64String = Settings.Global.getString(mContentResolver, - Settings.Global.GAME_DRIVER_DENYLISTS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); } parseDenylists(base64String != null ? base64String : ""); } @@ -288,16 +291,16 @@ public class GpuService extends SystemService { private void setDenylist() { Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_DENYLIST, ""); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, ""); synchronized (mLock) { if (mDenylists == null) { return; } List<Denylist> denylists = mDenylists.getDenylistsList(); for (Denylist denylist : denylists) { - if (denylist.getVersionCode() == mGameDriverVersionCode) { + if (denylist.getVersionCode() == mProdDriverVersionCode) { Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_DENYLIST, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, String.join(",", denylist.getPackageNamesList())); return; } @@ -305,7 +308,7 @@ public class GpuService extends SystemService { } } - private void fetchDeveloperDriverPackageProperties() { + private void fetchPrereleaseDriverPackageProperties() { final ApplicationInfo driverInfo; try { driverInfo = mPackageManager.getApplicationInfo(mDevDriverPackageName, diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java index 5573eede0d40..e3074dba26ef 100644 --- a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java +++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java @@ -164,9 +164,10 @@ public class BiometricDeferredQueue { mPendingResetLockouts = new ArrayList<>(); } - public void systemReady() { - mFingerprintManager = mContext.getSystemService(FingerprintManager.class); - mFaceManager = mContext.getSystemService(FaceManager.class); + public void systemReady(@Nullable FingerprintManager fingerprintManager, + @Nullable FaceManager faceManager) { + mFingerprintManager = fingerprintManager; + mFaceManager = faceManager; } /** diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 6eaa5faac8cb..0044d8936841 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -804,7 +804,8 @@ public class LockSettingsService extends ILockSettings.Stub { mRebootEscrowManager.loadRebootEscrowDataIfAvailable(); // TODO: maybe skip this for split system user mode. mStorage.prefetchUser(UserHandle.USER_SYSTEM); - mBiometricDeferredQueue.systemReady(); + mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), + mInjector.getFaceManager()); } private void getAuthSecretHal() { diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index a8a0e2e937d0..9521611c241d 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1918,7 +1918,7 @@ public class MediaSessionService extends SystemService implements Monitor { final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier(); final long token = Binder.clearCallingIdentity(); try { - // Don't perform sanity check between controllerPackageName and controllerUid. + // Don't perform 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 diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index c7e49fbac7a3..32ec052a1fe0 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1043,7 +1043,9 @@ class PackageManagerShellCommand extends ShellCommand { + "; isStaged = " + session.isStaged() + "; isReady = " + session.isStagedSessionReady() + "; isApplied = " + session.isStagedSessionApplied() - + "; isFailed = " + session.isStagedSessionFailed() + ";"); + + "; isFailed = " + session.isStagedSessionFailed() + + "; errorMsg = " + session.getStagedSessionErrorMessage() + + ";"); } private Intent parseIntentAndUser() throws URISyntaxException { diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index ac05aabf998f..6d80f08ecbf6 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -591,13 +591,14 @@ public class StagingManager { // If checkpoint is supported, then we only resume sessions if we are in checkpointing // mode. If not, we fail all sessions. if (supportsCheckpoint() && !needsCheckpoint()) { - String errorMsg = "Reverting back to safe state. Marking " + session.sessionId - + " as failed"; - if (!TextUtils.isEmpty(mFailureReason)) { - errorMsg = errorMsg + ": " + mFailureReason; + String revertMsg = "Reverting back to safe state. Marking " + + session.sessionId + " as failed."; + final String reasonForRevert = getReasonForRevert(); + if (!TextUtils.isEmpty(reasonForRevert)) { + revertMsg += " Reason for revert: " + reasonForRevert; } - Slog.d(TAG, errorMsg); - session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, errorMsg); + Slog.d(TAG, revertMsg); + session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg); return; } } catch (RemoteException e) { @@ -702,6 +703,16 @@ public class StagingManager { } } + private String getReasonForRevert() { + if (!TextUtils.isEmpty(mFailureReason)) { + return mFailureReason; + } + if (!TextUtils.isEmpty(mNativeFailureReason)) { + return "Session reverted due to crashing native process: " + mNativeFailureReason; + } + return ""; + } + private List<String> findAPKsInDir(File stageDir) { List<String> ret = new ArrayList<>(); if (stageDir != null && stageDir.exists()) { 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 8685be6567c6..1be74154b53a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2464,7 +2464,28 @@ public class PermissionManagerService extends IPermissionManager.Stub { return null; } final PermissionsState permissionsState = ps.getPermissionsState(); - return permissionsState.getPermissions(userId); + if (!ps.getInstantApp(userId)) { + return permissionsState.getPermissions(userId); + } else { + // Install permission state is shared among all users, but instant app state is + // per-user, so we can only filter it here unless we make install permission state + // per-user as well. + final Set<String> instantPermissions = new ArraySet<>(permissionsState.getPermissions( + userId)); + instantPermissions.removeIf(permissionName -> { + BasePermission permission = mSettings.getPermission(permissionName); + if (permission == null) { + return true; + } + if (!permission.isInstant()) { + EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId, + ps.getAppId()), permissionName); + return true; + } + return false; + }); + return instantPermissions; + } } @Nullable diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 4e05a138c543..64fa6ca590d2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1212,14 +1212,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task; } - /** - * Sets the Task on this activity for the purposes of re-use during launch where we will - * re-use another activity instead of this one for the launch. - */ - void setTaskForReuse(Task task) { - this.task = task; - } - Task getStack() { return task != null ? task.getRootTask() : null; } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 15e88fc44746..f6158383d28a 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1766,8 +1766,8 @@ class ActivityStarter { } else if (mInTask != null) { return mInTask; } else { - final Task stack = getLaunchStack(mStartActivity, mLaunchFlags, - null /* task */, mOptions); + final Task stack = getLaunchStack(mStartActivity, mLaunchFlags, null /* task */, + mOptions); final ActivityRecord top = stack.getTopNonFinishingActivity(); if (top != null) { return top.getTask(); @@ -1870,13 +1870,7 @@ class ActivityStarter { return START_SUCCESS; } - boolean clearTaskForReuse = false; if (reusedTask != null) { - if (mStartActivity.getTask() == null) { - mStartActivity.setTaskForReuse(reusedTask); - clearTaskForReuse = true; - } - if (targetTask.intent == null) { // This task was started because of movement of the activity based on // affinity... @@ -1923,13 +1917,6 @@ class ActivityStarter { complyActivityFlags(targetTask, reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants); - if (clearTaskForReuse) { - // Clear task for re-use so later code to methods - // {@link #setTaskFromReuseOrCreateNewTask}, {@link #setTaskFromSourceRecord}, or - // {@link #setTaskFromInTask} can parent it to the task. - mStartActivity.setTaskForReuse(null); - } - if (mAddingToTask) { return START_SUCCESS; } @@ -2515,8 +2502,8 @@ class ActivityStarter { intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask()); } - final Task launchStack = - getLaunchStack(mStartActivity, mLaunchFlags, intentTask, mOptions); + final Task launchStack = getLaunchStack(mStartActivity, mLaunchFlags, intentTask, + mOptions); if (launchStack == null || launchStack == mTargetStack) { // Do not set mMovedToFront to true below for split-screen-top stack, or // START_TASK_TO_FRONT will be returned and trigger unexpected animations when a diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 8204b36bc551..403f225032e9 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -251,6 +251,7 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AttributeCache; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.SystemService.TargetUser; import com.android.server.SystemServiceManager; import com.android.server.UiThread; import com.android.server.Watchdog; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2e879810c085..0215ead7e5de 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3982,9 +3982,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); - // TODO: Not sure if we really need to set the rotation here since we are updating from - // the display info above... - mDisplayFrames.mRotation = getRotation(); mDisplayPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode); int seq = mLayoutSeq + 1; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index fe2d08f6a4c2..aeaffd98f820 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2816,7 +2816,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> * @param launchParams The resolved launch params to use. * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid} * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid} - * * @return The stack to use for the launch or INVALID_STACK_ID. */ Task getLaunchStack(@Nullable ActivityRecord r, @@ -2965,10 +2964,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // If {@code r} is already in target display area and its task is the same as the candidate // task, the intention should be getting a launch stack for the reusable activity, so we can // use the existing stack. - if (candidateTask != null && (r.getTask() == null || r.getTask() == candidateTask)) { - // TODO(b/153920825): Fix incorrect evaluation of attached state - final TaskDisplayArea attachedTaskDisplayArea = r.getTask() != null - ? r.getTask().getDisplayArea() : r.getDisplayArea(); + if (candidateTask != null) { + final TaskDisplayArea attachedTaskDisplayArea = candidateTask.getDisplayArea(); if (attachedTaskDisplayArea == null || attachedTaskDisplayArea == taskDisplayArea) { return candidateTask.getRootTask(); } diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index bc75dcd91813..12c69eaa0f8d 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -150,7 +150,8 @@ public final class ProfcollectForwardingService extends SystemService { } // Sample for a fraction of app launches. - int traceFrequency = SystemProperties.getInt("profcollectd.applaunch_trace_freq", 2); + int traceFrequency = + SystemProperties.getInt("persist.profcollectd.applaunch_trace_freq", 2); int randomNum = ThreadLocalRandom.current().nextInt(100); if (randomNum < traceFrequency) { try { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java index c29c510b35b5..42ba842f8434 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java @@ -17,23 +17,33 @@ package com.android.server.accessibility.magnification; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyFloat; +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.when; +import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.view.Display; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; +/** + * Mocks the basic logic of window magnification in System UI. We assume the screen size is + * unlimited, so source bounds is always on the center of the mirror window bounds. + */ class MockWindowMagnificationConnection { + public static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; private final IWindowMagnificationConnection mConnection; private final Binder mBinder; private IBinder.DeathRecipient mDeathRecipient; private IWindowMagnificationConnectionCallback mIMirrorWindowCallback; + private Rect mMirrorWindowFrame = new Rect(0, 0, 500, 500); MockWindowMagnificationConnection() throws RemoteException { mConnection = mock(IWindowMagnificationConnection.class); @@ -50,6 +60,30 @@ class MockWindowMagnificationConnection { return null; }).when(mBinder).linkToDeath( any(IBinder.DeathRecipient.class), eq(0)); + stubConnection(); + } + + private void stubConnection() throws RemoteException { + doAnswer((invocation) -> { + final int displayId = invocation.getArgument(0); + if (displayId != TEST_DISPLAY) { + throw new IllegalArgumentException("only support default display :" + displayId); + } + computeMirrorWindowFrame(invocation.getArgument(1), invocation.getArgument(2)); + + mIMirrorWindowCallback.onWindowMagnifierBoundsChanged(TEST_DISPLAY, + mMirrorWindowFrame); + return null; + }).when(mConnection).enableWindowMagnification(anyInt(), + anyFloat(), anyFloat(), anyFloat()); + } + + private void computeMirrorWindowFrame(float centerX, float centerY) { + final float offsetX = Float.isNaN(centerX) ? 0 + : centerX - mMirrorWindowFrame.exactCenterX(); + final float offsetY = Float.isNaN(centerY) ? 0 + : centerY - mMirrorWindowFrame.exactCenterY(); + mMirrorWindowFrame.offset((int) offsetX, (int) offsetY); } IWindowMagnificationConnection getConnection() { @@ -60,12 +94,16 @@ class MockWindowMagnificationConnection { return mBinder; } - public IBinder.DeathRecipient getDeathRecipient() { + IBinder.DeathRecipient getDeathRecipient() { return mDeathRecipient; } - public IWindowMagnificationConnectionCallback getConnectionCallback() { + IWindowMagnificationConnectionCallback getConnectionCallback() { return mIMirrorWindowCallback; } + + public Rect getMirrorWindowFrame() { + return new Rect(mMirrorWindowFrame); + } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java index 2b1bdc59d9c8..ed8dc4e470de 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownTest.java @@ -87,15 +87,15 @@ public class TwoFingersDownTest { secondPointerCoords.x = DEFAULT_X + 10; secondPointerCoords.y = DEFAULT_Y + 10; - final MotionEvent pointerDownEvent = TouchEventGenerator.pointerDownEvent( + final MotionEvent twoPointersDownEvent = TouchEventGenerator.twoPointersDownEvent( Display.DEFAULT_DISPLAY, defPointerCoords, secondPointerCoords); mGesturesObserver.onMotionEvent(downEvent, downEvent, 0); - mGesturesObserver.onMotionEvent(pointerDownEvent, pointerDownEvent, 0); + mGesturesObserver.onMotionEvent(twoPointersDownEvent, twoPointersDownEvent, 0); verify(mListener, timeout(sTimeoutMillis)).onGestureCompleted( - MagnificationGestureMatcher.GESTURE_TWO_FINGER_DOWN, pointerDownEvent, - pointerDownEvent, 0); + MagnificationGestureMatcher.GESTURE_TWO_FINGER_DOWN, twoPointersDownEvent, + twoPointersDownEvent, 0); } @Test diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java index e580340a29f7..bec9f26672f4 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java @@ -16,14 +16,9 @@ package com.android.server.accessibility.magnification; -import static android.view.MotionEvent.ACTION_POINTER_DOWN; - import static com.android.server.testutils.TestUtils.strictMock; import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import android.content.Context; @@ -63,11 +58,9 @@ public class WindowMagnificationGestureHandlerTest { public static final int LAST_STATE = STATE_SHOW_MAGNIFIER_TRIPLE_TAP; // Co-prime x and y, to potentially catch x-y-swapped errors - public static final float DEFAULT_X = 301; - public static final float DEFAULT_Y = 299; - //Assume first pointer position (DEFAULT_X,DEFAULT_Y) is in the window. - public static Rect DEFAULT_WINDOW_FRAME = new Rect(0, 0, 500, 500); - private static final int DISPLAY_0 = 0; + public static final float DEFAULT_TAP_X = 301; + public static final float DEFAULT_TAP_Y = 299; + private static final int DISPLAY_0 = MockWindowMagnificationConnection.TEST_DISPLAY; private Context mContext; private WindowMagnificationManager mWindowMagnificationManager; @@ -83,14 +76,6 @@ public class WindowMagnificationGestureHandlerTest { mContext, mWindowMagnificationManager, mock(ScaleChangedListener.class), /** detectTripleTap= */true, /** detectShortcutTrigger= */true, DISPLAY_0); mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mMockConnection.getConnectionCallback().onWindowMagnifierBoundsChanged(DISPLAY_0, - DEFAULT_WINDOW_FRAME); - doAnswer((invocation) -> { - mMockConnection.getConnectionCallback().onWindowMagnifierBoundsChanged(DISPLAY_0, - DEFAULT_WINDOW_FRAME); - return null; - }).when(mMockConnection.getConnection()).enableWindowMagnification(eq(DISPLAY_0), - anyFloat(), anyFloat(), anyFloat()); mWindowMagnificationGestureHandler.setNext(strictMock(EventStreamTransformation.class)); } @@ -208,10 +193,11 @@ public class WindowMagnificationGestureHandlerTest { break; case STATE_TWO_FINGERS_DOWN: { goFromStateIdleTo(STATE_SHOW_MAGNIFIER); - send(downEvent()); + final Rect frame = mMockConnection.getMirrorWindowFrame(); + send(downEvent(frame.centerX(), frame.centerY())); //Second finger is outside the window. - send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_WINDOW_FRAME.right + 10, - DEFAULT_WINDOW_FRAME.bottom + 10)); + send(twoPointerDownEvent(new float[]{frame.centerX(), frame.centerX() + 10}, + new float[]{frame.centerY(), frame.centerY() + 10})); } break; case STATE_SHOW_MAGNIFIER_TRIPLE_TAP: { @@ -243,7 +229,8 @@ public class WindowMagnificationGestureHandlerTest { } break; case STATE_TWO_FINGERS_DOWN: { - send(upEvent()); + final Rect frame = mMockConnection.getMirrorWindowFrame(); + send(upEvent(frame.centerX(), frame.centerY())); returnToNormalFrom(STATE_SHOW_MAGNIFIER); } break; @@ -286,12 +273,8 @@ public class WindowMagnificationGestureHandlerTest { } } - private MotionEvent downEvent() { - return TouchEventGenerator.downEvent(DISPLAY_0, DEFAULT_X, DEFAULT_Y); - } - - private MotionEvent upEvent() { - return upEvent(DEFAULT_X, DEFAULT_Y); + private MotionEvent downEvent(float x, float y) { + return TouchEventGenerator.downEvent(DISPLAY_0, x, y); } private MotionEvent upEvent(float x, float y) { @@ -299,18 +282,18 @@ public class WindowMagnificationGestureHandlerTest { } private void tap() { - send(downEvent()); - send(upEvent()); + send(downEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y)); + send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y)); } - private MotionEvent pointerEvent(int action, float x, float y) { + private MotionEvent twoPointerDownEvent(float[] x, float[] y) { final MotionEvent.PointerCoords defPointerCoords = new MotionEvent.PointerCoords(); - defPointerCoords.x = DEFAULT_X; - defPointerCoords.y = DEFAULT_Y; + defPointerCoords.x = x[0]; + defPointerCoords.y = y[0]; final MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); - pointerCoords.x = x; - pointerCoords.y = y; - return TouchEventGenerator.pointerDownEvent(DISPLAY_0, defPointerCoords, pointerCoords); + pointerCoords.x = x[1]; + pointerCoords.y = y[1]; + return TouchEventGenerator.twoPointersDownEvent(DISPLAY_0, defPointerCoords, pointerCoords); } private String stateDump() { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java b/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java index 7cbf3ee46594..a05881f78892 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/utils/TouchEventGenerator.java @@ -43,9 +43,9 @@ public class TouchEventGenerator { return generateSingleTouchEvent(displayId, ACTION_UP, x, y); } - public static MotionEvent pointerDownEvent(int displayId, PointerCoords defPointerCoords, + public static MotionEvent twoPointersDownEvent(int displayId, PointerCoords defPointerCoords, PointerCoords pointerCoords) { - return generatePointerEvent(displayId, ACTION_POINTER_DOWN, defPointerCoords, + return generateTwoPointersEvent(displayId, ACTION_POINTER_DOWN, defPointerCoords, pointerCoords); } @@ -59,7 +59,7 @@ public class TouchEventGenerator { return ev; } - private static MotionEvent generatePointerEvent(int displayId, int action, + private static MotionEvent generateTwoPointersEvent(int displayId, int action, PointerCoords defPointerCoords, PointerCoords pointerCoords) { final long downTime = SystemClock.uptimeMillis(); MotionEvent.PointerProperties defPointerProperties = new MotionEvent.PointerProperties(); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java index 1ec9bd24ad59..b89d16807a6e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -890,8 +890,8 @@ public class RootActivityContainerTests extends WindowTestsBase { // Make sure the root task is valid and can be reused on default display. final Task stack = mRootWindowContainer.getValidLaunchStackInTaskDisplayArea( - mRootWindowContainer.getDefaultTaskDisplayArea(), activity, task, null, - null); + mRootWindowContainer.getDefaultTaskDisplayArea(), activity, task, + null /* options */, null /* launchParams */); assertEquals(task, stack); } diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt index 09c16595e2c7..52e0953813a0 100644 --- a/telephony/api/system-current.txt +++ b/telephony/api/system-current.txt @@ -1625,6 +1625,7 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); + field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43 field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index e34bbfcde492..06c34dcf290a 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -37,7 +37,7 @@ public final class CellIdentityNr extends CellIdentity { private static final String TAG = "CellIdentityNr"; private static final int MAX_PCI = 1007; - private static final int MAX_TAC = 65535; + private static final int MAX_TAC = 16777215; // 0xffffff private static final int MAX_NRARFCN = 3279165; private static final long MAX_NCI = 68719476735L; @@ -53,7 +53,7 @@ public final class CellIdentityNr extends CellIdentity { /** * * @param pci Physical Cell Id in range [0, 1007]. - * @param tac 16-bit Tracking Area Code. + * @param tac 24-bit Tracking Area Code. * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165]. * @param bands Bands used by the cell. Band number defined in 3GPP TS 38.101-1 and TS 38.101-2. * @param mccStr 3-digit Mobile Country Code in string format. @@ -199,9 +199,9 @@ public final class CellIdentityNr extends CellIdentity { /** * Get the tracking area code. - * @return a 16 bit integer or {@link CellInfo#UNAVAILABLE} if unknown. + * @return a 24 bit integer or {@link CellInfo#UNAVAILABLE} if unknown. */ - @IntRange(from = 0, to = 65535) + @IntRange(from = 0, to = 16777215) public int getTac() { return mTac; } diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 1a606b7ae6a7..2a073a1f1d81 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -851,6 +851,19 @@ public class ProvisioningManager { public static final int KEY_RTT_ENABLED = 66; /** + * An obfuscated string defined by the carrier to indicate VoWiFi entitlement status. + * + * <p>Implementation note: how to generate the value and how it affects VoWiFi service + * should follow carrier requirements. For example, set an empty string could result in + * VoWiFi being disabled by IMS service, and set to a specific string could enable. + * + * <p>Value is in String format. + * @see #setProvisioningStringValue(int, String) + * @see #getProvisioningStringValue(int) + */ + public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; + + /** * Callback for IMS provisioning changes. */ public static class Callback { diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java index d0cec52dfc86..487786045b8e 100644 --- a/telephony/java/com/android/ims/ImsConfig.java +++ b/telephony/java/com/android/ims/ImsConfig.java @@ -729,7 +729,8 @@ public class ImsConfig { // Expand the operator config items as needed here, need to change // PROVISIONED_CONFIG_END after that. - public static final int PROVISIONED_CONFIG_END = RTT_SETTING_ENABLED; + public static final int PROVISIONED_CONFIG_END = + ProvisioningManager.KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID; // Expand the operator config items as needed here. } |