Loading packages/SystemUI/res/values/dimens.xml +6 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,12 @@ <!-- The radius of the rounded corners on a task view. --> <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen> <!-- The min translation in the Z index for the last task. --> <dimen name="recents_task_view_z_min">3dp</dimen> <!-- The translation in the Z index for each task above the last task. --> <dimen name="recents_task_view_z_increment">5dp</dimen> <!-- The amount of space a user has to scroll to dismiss any info panes. --> <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen> Loading packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +101 −49 Original line number Diff line number Diff line Loading @@ -64,6 +64,17 @@ public class AlternateRecentsComponent { mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight); mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT); mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight); Console.log(Constants.DebugFlags.App.RecentsComponent, "[RecentsComponent|RecentsMessageHandler|handleMessage]", "singleTaskRect: " + mSingleCountFirstTaskRect + " multipleTaskRect: " + mMultipleCountFirstTaskRect); // If we had the update the animation rects as a result of onServiceConnected, then // we check for whether we need to toggle the recents here. if (mToggleRecentsUponServiceBound) { startAlternateRecentsActivity(); mToggleRecentsUponServiceBound = false; } } } } Loading @@ -78,12 +89,17 @@ public class AlternateRecentsComponent { mService = new Messenger(service); mServiceIsBound = true; // Toggle recents if this service connection was triggered by hitting the recents button if (hasValidTaskRects()) { // Toggle recents if this new service connection was triggered by hitting recents if (mToggleRecentsUponServiceBound) { startAlternateRecentsActivity(); } mToggleRecentsUponServiceBound = false; } } else { // Otherwise, update the animation rects before starting the recents if requested updateAnimationRects(); } } @Override public void onServiceDisconnected(ComponentName className) { Loading Loading @@ -191,6 +207,26 @@ public class AlternateRecentsComponent { } public void onConfigurationChanged(Configuration newConfig) { updateAnimationRects(); } /** Binds to the recents implementation */ private void bindToRecentsService(boolean toggleRecentsUponConnection) { mToggleRecentsUponServiceBound = toggleRecentsUponConnection; Intent intent = new Intent(); intent.setClassName(sRecentsPackage, sRecentsService); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } /** Returns whether we have valid task rects to animate to. */ boolean hasValidTaskRects() { return mSingleCountFirstTaskRect != null && mSingleCountFirstTaskRect.width() > 0 && mSingleCountFirstTaskRect.height() > 0 && mMultipleCountFirstTaskRect != null && mMultipleCountFirstTaskRect.width() > 0 && mMultipleCountFirstTaskRect.height() > 0; } /** Updates each of the task animation rects. */ void updateAnimationRects() { if (mServiceIsBound) { Resources res = mContext.getResources(); int statusBarHeight = res.getDimensionPixelSize( Loading @@ -216,14 +252,6 @@ public class AlternateRecentsComponent { } } /** Binds to the recents implementation */ private void bindToRecentsService(boolean toggleRecentsUponConnection) { mToggleRecentsUponServiceBound = toggleRecentsUponConnection; Intent intent = new Intent(); intent.setClassName(sRecentsPackage, sRecentsService); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } /** Loads the first task thumbnail */ Bitmap loadFirstTaskThumbnail() { SystemServicesProxy ssp = mSystemServicesProxy; Loading Loading @@ -300,6 +328,49 @@ public class AlternateRecentsComponent { return SurfaceControl.screenshot((int) dims[0], (int) dims[1]); } /** Creates the activity options for a thumbnail transition. */ ActivityOptions getThumbnailTransitionActivityOptions(Rect taskRect) { // Loading from thumbnail Bitmap thumbnail; Bitmap firstThumbnail = loadFirstTaskThumbnail(); if (firstThumbnail != null) { // Create the thumbnail thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight()); Canvas c = new Canvas(thumbnail); c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the old thumbnail firstThumbnail.recycle(); } else { // Load the thumbnail from the screenshot if can't get one from the system WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Bitmap screenshot = takeScreenshot(display); if (screenshot != null) { Resources res = mContext.getResources(); int size = Math.min(screenshot.getWidth(), screenshot.getHeight()); int statusBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(thumbnail); c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the temporary screenshot screenshot.recycle(); } else { return null; } } return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail, taskRect.left, taskRect.top, null); } /** Starts the recents activity */ void startAlternateRecentsActivity() { // If the user has toggled it too quickly, then just eat up the event here (it's better than Loading Loading @@ -351,47 +422,28 @@ public class AlternateRecentsComponent { // number of items in the list. List<ActivityManager.RecentTaskInfo> recentTasks = ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier()); boolean hasMultipleTasks = hasMultipleRecentsTask(recentTasks); Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect; boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks); Rect taskRect = hasMultipleTasks ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect; if (!isTopTaskHome && !isTaskExcludedFromRecents && (taskRect != null) && (taskRect.width() > 0) && (taskRect.height() > 0)) { // Loading from thumbnail Bitmap thumbnail; Bitmap firstThumbnail = loadFirstTaskThumbnail(); if (firstThumbnail != null) {// Create the thumbnail thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight()); Canvas c = new Canvas(thumbnail); c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the old thumbnail firstThumbnail.recycle(); } else { // Load the thumbnail from the screenshot if can't get one from the system WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Bitmap screenshot = takeScreenshot(display); Resources res = mContext.getResources(); int size = Math.min(screenshot.getWidth(), screenshot.getHeight()); int statusBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(thumbnail); c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the temporary screenshot screenshot.recycle(); } boolean useThumbnailTransition = !isTopTaskHome && !isTaskExcludedFromRecents && hasValidTaskRects(); ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail, taskRect.left, taskRect.top, null); if (useThumbnailTransition) { // Try starting with a thumbnail transition ActivityOptions opts = getThumbnailTransitionActivityOptions(taskRect); if (opts != null) { startAlternateRecentsActivity(opts, true); } else { // Fall through below to the non-thumbnail transition useThumbnailTransition = false; } } // If there is no thumbnail transition, then just use a generic transition // XXX: This should be different between home and from a recents-excluded app, perhaps the // recents-excluded app should still show up in recents, when the app is in the // foreground if (!useThumbnailTransition) { ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, R.anim.recents_from_launcher_enter, R.anim.recents_from_launcher_exit); Loading packages/SystemUI/src/com/android/systemui/recents/Constants.java +1 −4 Original line number Diff line number Diff line Loading @@ -91,11 +91,8 @@ public class Constants { public static final int TaskStackOverscrollRange = 150; public static final int FilterStartDelay = 25; // The amount to inverse scale the movement if we are overscrolling public static final float TouchOverscrollScaleFactor = 3f; // The padding will be applied to the smallest dimension, and then applied to all sides public static final float StackPaddingPct = 0.15f; public static final float StackPaddingPct = 0.1f; // The overlap height relative to the task height public static final float StackOverlapPct = 0.65f; // The height of the peek space relative to the stack height Loading packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +5 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ public class RecentsConfiguration { public int taskStackScrollDismissInfoPaneDistance; public int taskStackMaxDim; public int taskViewInfoPaneAnimDuration; public int taskViewTranslationZMinPx; public int taskViewTranslationZIncrementPx; public int taskViewRoundedCornerRadiusPx; public int searchBarSpaceHeightPx; Loading Loading @@ -108,6 +110,9 @@ public class RecentsConfiguration { res.getInteger(R.integer.recents_animate_task_view_info_pane_duration); taskViewRoundedCornerRadiusPx = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min); taskViewTranslationZIncrementPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment); searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height); Loading packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java +11 −0 Original line number Diff line number Diff line Loading @@ -20,10 +20,12 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.TouchFeedbackDrawable; import android.util.AttributeSet; import android.widget.Button; import android.widget.FrameLayout; Loading Loading @@ -151,6 +153,15 @@ class TaskInfoView extends FrameLayout { RecentsConfiguration configuration = RecentsConfiguration.getInstance(); if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) { setBackgroundColor(t.colorPrimary); // Workaround: The button currently doesn't support setting a custom background tint // not defined in the theme. Just lower the alpha on the button to make it blend more // into the background. if (mAppInfoButton.getBackground() instanceof TouchFeedbackDrawable) { TouchFeedbackDrawable d = (TouchFeedbackDrawable) mAppInfoButton.getBackground(); if (d != null) { d.setAlpha(96); } } } else { setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor); } Loading Loading
packages/SystemUI/res/values/dimens.xml +6 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,12 @@ <!-- The radius of the rounded corners on a task view. --> <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen> <!-- The min translation in the Z index for the last task. --> <dimen name="recents_task_view_z_min">3dp</dimen> <!-- The translation in the Z index for each task above the last task. --> <dimen name="recents_task_view_z_increment">5dp</dimen> <!-- The amount of space a user has to scroll to dismiss any info panes. --> <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen> Loading
packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +101 −49 Original line number Diff line number Diff line Loading @@ -64,6 +64,17 @@ public class AlternateRecentsComponent { mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight); mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT); mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight); Console.log(Constants.DebugFlags.App.RecentsComponent, "[RecentsComponent|RecentsMessageHandler|handleMessage]", "singleTaskRect: " + mSingleCountFirstTaskRect + " multipleTaskRect: " + mMultipleCountFirstTaskRect); // If we had the update the animation rects as a result of onServiceConnected, then // we check for whether we need to toggle the recents here. if (mToggleRecentsUponServiceBound) { startAlternateRecentsActivity(); mToggleRecentsUponServiceBound = false; } } } } Loading @@ -78,12 +89,17 @@ public class AlternateRecentsComponent { mService = new Messenger(service); mServiceIsBound = true; // Toggle recents if this service connection was triggered by hitting the recents button if (hasValidTaskRects()) { // Toggle recents if this new service connection was triggered by hitting recents if (mToggleRecentsUponServiceBound) { startAlternateRecentsActivity(); } mToggleRecentsUponServiceBound = false; } } else { // Otherwise, update the animation rects before starting the recents if requested updateAnimationRects(); } } @Override public void onServiceDisconnected(ComponentName className) { Loading Loading @@ -191,6 +207,26 @@ public class AlternateRecentsComponent { } public void onConfigurationChanged(Configuration newConfig) { updateAnimationRects(); } /** Binds to the recents implementation */ private void bindToRecentsService(boolean toggleRecentsUponConnection) { mToggleRecentsUponServiceBound = toggleRecentsUponConnection; Intent intent = new Intent(); intent.setClassName(sRecentsPackage, sRecentsService); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } /** Returns whether we have valid task rects to animate to. */ boolean hasValidTaskRects() { return mSingleCountFirstTaskRect != null && mSingleCountFirstTaskRect.width() > 0 && mSingleCountFirstTaskRect.height() > 0 && mMultipleCountFirstTaskRect != null && mMultipleCountFirstTaskRect.width() > 0 && mMultipleCountFirstTaskRect.height() > 0; } /** Updates each of the task animation rects. */ void updateAnimationRects() { if (mServiceIsBound) { Resources res = mContext.getResources(); int statusBarHeight = res.getDimensionPixelSize( Loading @@ -216,14 +252,6 @@ public class AlternateRecentsComponent { } } /** Binds to the recents implementation */ private void bindToRecentsService(boolean toggleRecentsUponConnection) { mToggleRecentsUponServiceBound = toggleRecentsUponConnection; Intent intent = new Intent(); intent.setClassName(sRecentsPackage, sRecentsService); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } /** Loads the first task thumbnail */ Bitmap loadFirstTaskThumbnail() { SystemServicesProxy ssp = mSystemServicesProxy; Loading Loading @@ -300,6 +328,49 @@ public class AlternateRecentsComponent { return SurfaceControl.screenshot((int) dims[0], (int) dims[1]); } /** Creates the activity options for a thumbnail transition. */ ActivityOptions getThumbnailTransitionActivityOptions(Rect taskRect) { // Loading from thumbnail Bitmap thumbnail; Bitmap firstThumbnail = loadFirstTaskThumbnail(); if (firstThumbnail != null) { // Create the thumbnail thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight()); Canvas c = new Canvas(thumbnail); c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the old thumbnail firstThumbnail.recycle(); } else { // Load the thumbnail from the screenshot if can't get one from the system WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Bitmap screenshot = takeScreenshot(display); if (screenshot != null) { Resources res = mContext.getResources(); int size = Math.min(screenshot.getWidth(), screenshot.getHeight()); int statusBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(thumbnail); c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the temporary screenshot screenshot.recycle(); } else { return null; } } return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail, taskRect.left, taskRect.top, null); } /** Starts the recents activity */ void startAlternateRecentsActivity() { // If the user has toggled it too quickly, then just eat up the event here (it's better than Loading Loading @@ -351,47 +422,28 @@ public class AlternateRecentsComponent { // number of items in the list. List<ActivityManager.RecentTaskInfo> recentTasks = ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier()); boolean hasMultipleTasks = hasMultipleRecentsTask(recentTasks); Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect; boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks); Rect taskRect = hasMultipleTasks ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect; if (!isTopTaskHome && !isTaskExcludedFromRecents && (taskRect != null) && (taskRect.width() > 0) && (taskRect.height() > 0)) { // Loading from thumbnail Bitmap thumbnail; Bitmap firstThumbnail = loadFirstTaskThumbnail(); if (firstThumbnail != null) {// Create the thumbnail thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight()); Canvas c = new Canvas(thumbnail); c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the old thumbnail firstThumbnail.recycle(); } else { // Load the thumbnail from the screenshot if can't get one from the system WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Bitmap screenshot = takeScreenshot(display); Resources res = mContext.getResources(); int size = Math.min(screenshot.getWidth(), screenshot.getHeight()); int statusBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(thumbnail); c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size), new Rect(0, 0, taskRect.width(), taskRect.height()), null); c.setBitmap(null); // Recycle the temporary screenshot screenshot.recycle(); } boolean useThumbnailTransition = !isTopTaskHome && !isTaskExcludedFromRecents && hasValidTaskRects(); ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail, taskRect.left, taskRect.top, null); if (useThumbnailTransition) { // Try starting with a thumbnail transition ActivityOptions opts = getThumbnailTransitionActivityOptions(taskRect); if (opts != null) { startAlternateRecentsActivity(opts, true); } else { // Fall through below to the non-thumbnail transition useThumbnailTransition = false; } } // If there is no thumbnail transition, then just use a generic transition // XXX: This should be different between home and from a recents-excluded app, perhaps the // recents-excluded app should still show up in recents, when the app is in the // foreground if (!useThumbnailTransition) { ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, R.anim.recents_from_launcher_enter, R.anim.recents_from_launcher_exit); Loading
packages/SystemUI/src/com/android/systemui/recents/Constants.java +1 −4 Original line number Diff line number Diff line Loading @@ -91,11 +91,8 @@ public class Constants { public static final int TaskStackOverscrollRange = 150; public static final int FilterStartDelay = 25; // The amount to inverse scale the movement if we are overscrolling public static final float TouchOverscrollScaleFactor = 3f; // The padding will be applied to the smallest dimension, and then applied to all sides public static final float StackPaddingPct = 0.15f; public static final float StackPaddingPct = 0.1f; // The overlap height relative to the task height public static final float StackOverlapPct = 0.65f; // The height of the peek space relative to the stack height Loading
packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +5 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ public class RecentsConfiguration { public int taskStackScrollDismissInfoPaneDistance; public int taskStackMaxDim; public int taskViewInfoPaneAnimDuration; public int taskViewTranslationZMinPx; public int taskViewTranslationZIncrementPx; public int taskViewRoundedCornerRadiusPx; public int searchBarSpaceHeightPx; Loading Loading @@ -108,6 +110,9 @@ public class RecentsConfiguration { res.getInteger(R.integer.recents_animate_task_view_info_pane_duration); taskViewRoundedCornerRadiusPx = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min); taskViewTranslationZIncrementPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment); searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height); Loading
packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java +11 −0 Original line number Diff line number Diff line Loading @@ -20,10 +20,12 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.TouchFeedbackDrawable; import android.util.AttributeSet; import android.widget.Button; import android.widget.FrameLayout; Loading Loading @@ -151,6 +153,15 @@ class TaskInfoView extends FrameLayout { RecentsConfiguration configuration = RecentsConfiguration.getInstance(); if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) { setBackgroundColor(t.colorPrimary); // Workaround: The button currently doesn't support setting a custom background tint // not defined in the theme. Just lower the alpha on the button to make it blend more // into the background. if (mAppInfoButton.getBackground() instanceof TouchFeedbackDrawable) { TouchFeedbackDrawable d = (TouchFeedbackDrawable) mAppInfoButton.getBackground(); if (d != null) { d.setAlpha(96); } } } else { setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor); } Loading