diff options
20 files changed, 68 insertions, 75 deletions
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 5ec90941aa88..85655a5dfc6b 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -55,7 +55,7 @@ oneway interface IStatusBar boolean showImeSwitcher); void setWindowState(int window, int state); - void showRecentApps(boolean triggeredFromAltTab, boolean fromHome); + void showRecentApps(boolean triggeredFromAltTab); void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); void toggleRecentApps(); void toggleSplitScreen(); diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java index 880ae709b59d..f9dbf4a15e5c 100644 --- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java @@ -21,7 +21,7 @@ import android.view.Display; import android.view.View; public interface RecentsComponent { - void showRecentApps(boolean triggeredFromAltTab, boolean fromHome); + void showRecentApps(boolean triggeredFromAltTab); void showNextAffiliatedTask(); void showPrevAffiliatedTask(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl index 5ae7f22c4905..fc1831d55c9d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl +++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl @@ -27,7 +27,7 @@ oneway interface IRecentsNonSystemUserCallbacks { void preloadRecents(); void cancelPreloadingRecents(); void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate, - boolean reloadTasks, boolean fromHome, int recentsGrowTarget); + int recentsGrowTarget); void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); void toggleRecents(int recentsGrowTarget); void onConfigurationChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index 5b62c7d3c002..1da4deb61176 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -240,7 +240,7 @@ public class Recents extends SystemUI * Shows the Recents. */ @Override - public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { + public void showRecentApps(boolean triggeredFromAltTab) { // Ensure the device has been provisioned before allowing the user to interact with // recents if (!isUserSetup()) { @@ -252,7 +252,7 @@ public class Recents extends SystemUI int currentUser = sSystemServicesProxy.getCurrentUser(); if (sSystemServicesProxy.isSystemUser(currentUser)) { mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */, - true /* animate */, false /* reloadTasks */, fromHome, recentsGrowTarget); + true /* animate */, recentsGrowTarget); } else { if (mSystemToUserCallbacks != null) { IRecentsNonSystemUserCallbacks callbacks = @@ -260,8 +260,7 @@ public class Recents extends SystemUI if (callbacks != null) { try { callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */, - true /* animate */, false /* reloadTasks */, fromHome, - recentsGrowTarget); + true /* animate */, recentsGrowTarget); } catch (RemoteException e) { Log.e(TAG, "Callback failed", e); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 06dfd183b3aa..b0a2fadf1f84 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -356,15 +356,15 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD registerReceiver(mSystemBroadcastReceiver, filter); getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION); - - // Reload the stack view - reloadStackView(); } @Override protected void onStart() { super.onStart(); + // Reload the stack view whenever we are made visible again + reloadStackView(); + // Notify that recents is now visible EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true)); MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY); @@ -411,14 +411,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD } } - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - // Reload the stack view - reloadStackView(); - } - /** * Reloads the stack views upon launching Recents. */ @@ -530,7 +522,11 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD // Set the window background mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode); - reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */); + // Reload the task stack view if we are still visible to pick up the change in tasks that + // result from entering/exiting multi-window + if (mIsVisible) { + reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 8359690b4fe3..ee1b09109d38 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -255,7 +255,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // When this fires, then the user has not released alt-tab for at least // FAST_ALT_TAB_DELAY_MS milliseconds showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */, - false /* reloadTasks */, false /* fromHome */, DividerView.INVALID_RECENTS_GROW_TARGET); } }); @@ -322,8 +321,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, - boolean animate, boolean launchedWhileDockingTask, boolean fromHome, - int growTarget) { + boolean animate, int growTarget) { + final SystemServicesProxy ssp = Recents.getSystemServices(); + final MutableBoolean isHomeStackVisible = new MutableBoolean(true); + final boolean isRecentsVisible = Recents.getSystemServices().isRecentsActivityVisible( + isHomeStackVisible); + final boolean fromHome = isHomeStackVisible.value; + final boolean launchedWhileDockingTask = + Recents.getSystemServices().getSplitScreenPrimaryStack() != null; + mTriggeredFromAltTab = triggeredFromAltTab; mDraggingInRecents = draggingInRecents; mLaunchedWhileDocking = launchedWhileDockingTask; @@ -349,10 +355,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener try { // Check if the top task is in the home stack, and start the recents activity - SystemServicesProxy ssp = Recents.getSystemServices(); - boolean forceVisible = launchedWhileDockingTask || draggingInRecents; - MutableBoolean isHomeStackVisible = new MutableBoolean(forceVisible); - if (forceVisible || !ssp.isRecentsActivityVisible(isHomeStackVisible)) { + final boolean forceVisible = launchedWhileDockingTask || draggingInRecents; + if (forceVisible || !isRecentsVisible) { ActivityManager.RunningTaskInfo runningTask = ActivityManagerWrapper.getInstance().getRunningTask(); startRecentsActivityAndDismissKeyguardIfNeeded(runningTask, diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java index 9493c78f6278..beec4b395e9c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java @@ -58,15 +58,12 @@ public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub { @Override public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate, - boolean reloadTasks, boolean fromHome, int growTarget) - throws RemoteException { + int growTarget) throws RemoteException { SomeArgs args = SomeArgs.obtain(); args.argi1 = triggeredFromAltTab ? 1 : 0; args.argi2 = draggingInRecents ? 1 : 0; args.argi3 = animate ? 1 : 0; - args.argi4 = reloadTasks ? 1 : 0; - args.argi5 = fromHome ? 1 : 0; - args.argi6 = growTarget; + args.argi4 = growTarget; mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_RECENTS, args)); } @@ -130,7 +127,7 @@ public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub { case MSG_SHOW_RECENTS: args = (SomeArgs) msg.obj; mImpl.showRecents(args.argi1 != 0, args.argi2 != 0, args.argi3 != 0, - args.argi4 != 0, args.argi5 != 0, args.argi6); + args.argi4); break; case MSG_HIDE_RECENTS: mImpl.hideRecents(msg.arg1 != 0, msg.arg2 != 0); diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 130a5e310fd1..613d9fbb985c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -274,20 +274,21 @@ public class SystemServicesProxy { return false; } + public ActivityManager.StackInfo getSplitScreenPrimaryStack() { + try { + return mIam.getStackInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED); + } catch (RemoteException e) { + return null; + } + } + /** * @return whether there are any docked tasks for the current user. */ public boolean hasDockedTask() { if (mIam == null) return false; - ActivityManager.StackInfo stackInfo = null; - try { - stackInfo = - mIam.getStackInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED); - } catch (RemoteException e) { - e.printStackTrace(); - } - + ActivityManager.StackInfo stackInfo = getSplitScreenPrimaryStack(); if (stackInfo != null) { int userId = getCurrentUser(); boolean hasUserTask = false; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 36c9095fe8ae..5be2900831b3 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -210,7 +210,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private boolean mStackActionButtonVisible; // Percentage of last ScrollP from the min to max scrollP that lives after configuration changes - private float mLastScrollPPercent; + private float mLastScrollPPercent = -1; // We keep track of the task view focused by user interaction and draw a frame around it in the // grid layout. @@ -647,14 +647,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * an animation provided in {@param animationOverrides}, that will be used instead. */ private void relayoutTaskViews(AnimationProps animation, - ArrayMap<Task, AnimationProps> animationOverrides, - boolean ignoreTaskOverrides) { + ArrayMap<Task, AnimationProps> animationOverrides, boolean ignoreTaskOverrides) { // If we had a deferred animation, cancel that cancelDeferredTaskViewLayoutAnimation(); // Synchronize the current set of TaskViews - bindVisibleTaskViews(mStackScroller.getStackScroll(), - ignoreTaskOverrides /* ignoreTaskOverrides */); + bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTaskOverrides); // Animate them to their final transforms with the given animation List<TaskView> taskViews = getTaskViews(); @@ -2067,8 +2065,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Update the Clear All button in case we're switching in or out of grid layout. updateStackActionButtonVisibility(); - // Trigger a new layout and update to the initial state if necessary - if (event.fromMultiWindow) { + // Trigger a new layout and update to the initial state if necessary. When entering split + // screen, the multi-window configuration change event can happen after the stack is already + // reloaded (but pending measure/layout), in this case, do not override the intiial state + // and just wait for the upcoming measure/layout pass. + if (event.fromMultiWindow && mInitialState == INITIAL_STATE_UPDATE_NONE) { mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY; requestLayout(); } else if (event.fromDeviceOrientationChange) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 8e1b10432a3d..657b9534f3a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -116,7 +116,7 @@ public class CommandQueue extends IStatusBar.Stub { default void topAppWindowChanged(boolean visible) { } default void setImeWindowStatus(IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { } - default void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { } + default void showRecentApps(boolean triggeredFromAltTab) { } default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { } default void toggleRecentApps() { } default void toggleSplitScreen() { } @@ -268,11 +268,11 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { + public void showRecentApps(boolean triggeredFromAltTab) { synchronized (mLock) { mHandler.removeMessages(MSG_SHOW_RECENT_APPS); - mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, - triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0, null).sendToTarget(); + mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, triggeredFromAltTab ? 1 : 0, 0, + null).sendToTarget(); } } @@ -541,7 +541,7 @@ public class CommandQueue extends IStatusBar.Stub { break; case MSG_SHOW_RECENT_APPS: for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).showRecentApps(msg.arg1 != 0, msg.arg2 != 0); + mCallbacks.get(i).showRecentApps(msg.arg1 != 0); } break; case MSG_HIDE_RECENT_APPS: diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index 960320722c56..a02ef98f834d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -119,9 +119,9 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testShowRecentApps() { - mCommandQueue.showRecentApps(true, false); + mCommandQueue.showRecentApps(true); waitForIdleSync(); - verify(mCallbacks).showRecentApps(eq(true), eq(false)); + verify(mCallbacks).showRecentApps(eq(true)); } @Test diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index f496a672e8d7..9d06b0dbab64 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -606,7 +606,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai true /* onTop */); recentStack.moveToFront("setWindowingMode"); // If task moved to docked stack - show recents if needed. - mService.mWindowManager.showRecentApps(false /* fromHome */); + mService.mWindowManager.showRecentApps(); } wm.continueSurfaceLayout(); } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index b131e86d83ed..809f19f64317 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -749,12 +749,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(), DEFAULT_DISPLAY, toStack); - boolean successful = (preferredStack == toStack); - if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { - // If task moved to docked stack - show recents if needed. - mService.mWindowManager.showRecentApps(false /* fromHome */); - } - return successful; + return (preferredStack == toStack); } /** diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 88e4270ad07e..63449976587e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -850,7 +850,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); break; case MSG_DISPATCH_SHOW_RECENTS: - showRecentApps(false, msg.arg1 != 0); + showRecentApps(false); break; case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS: showGlobalActionsInternal(); @@ -3817,7 +3817,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { mRecentAppsHeldModifiers = shiftlessModifiers; - showRecentApps(true, false); + showRecentApps(true); return -1; } } @@ -4164,16 +4164,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public void showRecentApps(boolean fromHome) { + public void showRecentApps() { mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); - mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget(); + mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS).sendToTarget(); } - private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { + private void showRecentApps(boolean triggeredFromAltTab) { mPreloadedRecentApps = false; // preloading no longer needs to be canceled StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); if (statusbar != null) { - statusbar.showRecentApps(triggeredFromAltTab, fromHome); + statusbar.showRecentApps(triggeredFromAltTab); } } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index c05dd2af3e5b..e9c4c5c8138f 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -1571,7 +1571,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * Show the recents task list app. * @hide */ - public void showRecentApps(boolean fromHome); + public void showRecentApps(); /** * Show the global actions dialog. diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 3792bc6777ed..b5d0c60efae8 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -30,7 +30,7 @@ public interface StatusBarManagerInternal { void cancelPreloadRecentApps(); - void showRecentApps(boolean triggeredFromAltTab, boolean fromHome); + void showRecentApps(boolean triggeredFromAltTab); void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index c7c03b48a778..79d3dbbe8c83 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -282,10 +282,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } @Override - public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { + public void showRecentApps(boolean triggeredFromAltTab) { if (mBar != null) { try { - mBar.showRecentApps(triggeredFromAltTab, fromHome); + mBar.showRecentApps(triggeredFromAltTab); } catch (RemoteException ex) {} } } diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 36e5d100edb6..7ae1f24b0cd6 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -607,7 +607,7 @@ public class DockedStackDividerController { if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps) && appTransition != TRANSIT_NONE && !AppTransition.isKeyguardGoingAwayTransit(appTransition)) { - mService.showRecentApps(true /* fromHome */); + mService.showRecentApps(); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 53086f714a79..de1e7ecb2bb9 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5967,8 +5967,8 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.lockNow(options); } - public void showRecentApps(boolean fromHome) { - mPolicy.showRecentApps(fromHome); + public void showRecentApps() { + mPolicy.showRecentApps(); } @Override diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 5ed17ccc6d9b..35ca493e909f 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -539,7 +539,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public void showRecentApps(boolean fromHome) { + public void showRecentApps() { } |