Loading quickstep/res/layout/task.xml +17 −0 Original line number Diff line number Diff line Loading @@ -34,4 +34,21 @@ android:layout_gravity="top|center_horizontal" android:focusable="false" android:importantForAccessibility="no" /> <com.android.quickstep.views.DigitalWellBeingToast android:id="@+id/digital_well_being_toast" android:layout_width="match_parent" android:layout_height="100dp" android:importantForAccessibility="noHideDescendants" android:background="#800000FF" android:layout_gravity="bottom" > <TextView android:id="@+id/remaining_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textColor="@android:color/white" /> </com.android.quickstep.views.DigitalWellBeingToast> </com.android.quickstep.views.TaskView> No newline at end of file quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java 0 → 100644 +97 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep.views; import android.app.ActivityOptions; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.systemui.shared.recents.model.Task; public final class DigitalWellBeingToast extends LinearLayout { public interface InitializeCallback { void call(long t, boolean b); } private static final String TAG = DigitalWellBeingToast.class.getSimpleName(); private Task mTask; public DigitalWellBeingToast(Context context, AttributeSet attrs) { super(context, attrs); setLayoutDirection(Utilities.isRtl(getResources()) ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); setOnClickListener((view) -> openAppUsageSettings()); } private void setRemainingTime(long remainingTime, boolean isGroupLimit) { final TextView remainingTimeText = findViewById(R.id.remaining_time); if (remainingTime <= 0) { setVisibility(GONE); } else { setVisibility(VISIBLE); remainingTimeText.setText(getText(remainingTime, isGroupLimit)); } } public void initialize(Task task, InitializeCallback callback) { mTask = task; Utilities.THREAD_POOL_EXECUTOR.execute(() -> { final long appRemainingTimeMs = -1; final boolean isGroupLimit = true; post(() -> { setRemainingTime(appRemainingTimeMs, isGroupLimit); callback.call(appRemainingTimeMs, isGroupLimit); }); }); } public static String getText(long remainingTime, boolean isGroupLimit) { return "Remaining time:" + (remainingTime + 119999) / 120000 + " min " + (isGroupLimit ? "for group" : "for the app"); } public void openAppUsageSettings() { final Intent intent = new Intent(TaskView.SEE_TIME_IN_APP_TEMPLATE) .putExtra(Intent.EXTRA_PACKAGE_NAME, mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { final Launcher launcher = Launcher.getLauncher(getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation( this, 0, 0, getWidth(), getHeight()); launcher.startActivity(intent, options.toBundle()); launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this); } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " + mTask.getTopComponent().getPackageName(), e); } } } quickstep/src/com/android/quickstep/views/TaskView.java +24 −33 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.app.ActivityOptions; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.res.Resources; Loading @@ -46,10 +45,8 @@ import android.widget.FrameLayout; import android.widget.Toast; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.quickstep.RecentsModel; Loading Loading @@ -140,6 +137,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { private TaskThumbnailView mSnapshotView; private TaskMenuView mMenuView; private IconView mIconView; private DigitalWellBeingToast mDigitalWellBeingToast; private float mCurveScale; private float mZoomScale; private boolean mIsFullscreen; Loading Loading @@ -183,6 +181,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { super.onFinishInflate(); mSnapshotView = findViewById(R.id.snapshot); mIconView = findViewById(R.id.icon); mDigitalWellBeingToast = findViewById(R.id.digital_well_being_toast); } /** Loading Loading @@ -266,8 +265,18 @@ public class TaskView extends FrameLayout implements PageCallbacks { (task) -> mSnapshotView.setThumbnail(task, task.thumbnail)); mIconLoadRequest = iconCache.updateIconInBackground(mTask, (task) -> { setContentDescription(task.titleDescription); setIcon(task.icon); mDigitalWellBeingToast.initialize( mTask, (appRemainingTimeMs, isGroupLimit) -> { mAppRemainingTimeMs = appRemainingTimeMs; setContentDescription( hasRemainingTime() ? task.titleDescription + ". " + DigitalWellBeingToast.getText( appRemainingTimeMs, isGroupLimit) : task.titleDescription); }); }); } else { if (mThumbnailLoadRequest != null) { Loading Loading @@ -464,7 +473,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { } if (action == R.string.accessibility_app_usage_settings) { openAppUsageSettings(this); mDigitalWellBeingToast.openAppUsageSettings(); return true; } Loading @@ -486,24 +495,6 @@ public class TaskView extends FrameLayout implements PageCallbacks { return super.performAccessibilityAction(action, arguments); } private void openAppUsageSettings(View view) { final Intent intent = new Intent(SEE_TIME_IN_APP_TEMPLATE) .putExtra(Intent.EXTRA_PACKAGE_NAME, mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { final Launcher launcher = Launcher.getLauncher(getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight()); launcher.startActivity(intent, options.toBundle()); launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this); } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " + mTask.getTopComponent().getPackageName(), e); } } private RecentsView getRecentsView() { return (RecentsView) getParent(); } Loading Loading
quickstep/res/layout/task.xml +17 −0 Original line number Diff line number Diff line Loading @@ -34,4 +34,21 @@ android:layout_gravity="top|center_horizontal" android:focusable="false" android:importantForAccessibility="no" /> <com.android.quickstep.views.DigitalWellBeingToast android:id="@+id/digital_well_being_toast" android:layout_width="match_parent" android:layout_height="100dp" android:importantForAccessibility="noHideDescendants" android:background="#800000FF" android:layout_gravity="bottom" > <TextView android:id="@+id/remaining_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textColor="@android:color/white" /> </com.android.quickstep.views.DigitalWellBeingToast> </com.android.quickstep.views.TaskView> No newline at end of file
quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java 0 → 100644 +97 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep.views; import android.app.ActivityOptions; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.systemui.shared.recents.model.Task; public final class DigitalWellBeingToast extends LinearLayout { public interface InitializeCallback { void call(long t, boolean b); } private static final String TAG = DigitalWellBeingToast.class.getSimpleName(); private Task mTask; public DigitalWellBeingToast(Context context, AttributeSet attrs) { super(context, attrs); setLayoutDirection(Utilities.isRtl(getResources()) ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); setOnClickListener((view) -> openAppUsageSettings()); } private void setRemainingTime(long remainingTime, boolean isGroupLimit) { final TextView remainingTimeText = findViewById(R.id.remaining_time); if (remainingTime <= 0) { setVisibility(GONE); } else { setVisibility(VISIBLE); remainingTimeText.setText(getText(remainingTime, isGroupLimit)); } } public void initialize(Task task, InitializeCallback callback) { mTask = task; Utilities.THREAD_POOL_EXECUTOR.execute(() -> { final long appRemainingTimeMs = -1; final boolean isGroupLimit = true; post(() -> { setRemainingTime(appRemainingTimeMs, isGroupLimit); callback.call(appRemainingTimeMs, isGroupLimit); }); }); } public static String getText(long remainingTime, boolean isGroupLimit) { return "Remaining time:" + (remainingTime + 119999) / 120000 + " min " + (isGroupLimit ? "for group" : "for the app"); } public void openAppUsageSettings() { final Intent intent = new Intent(TaskView.SEE_TIME_IN_APP_TEMPLATE) .putExtra(Intent.EXTRA_PACKAGE_NAME, mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { final Launcher launcher = Launcher.getLauncher(getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation( this, 0, 0, getWidth(), getHeight()); launcher.startActivity(intent, options.toBundle()); launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this); } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " + mTask.getTopComponent().getPackageName(), e); } } }
quickstep/src/com/android/quickstep/views/TaskView.java +24 −33 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.app.ActivityOptions; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.res.Resources; Loading @@ -46,10 +45,8 @@ import android.widget.FrameLayout; import android.widget.Toast; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.quickstep.RecentsModel; Loading Loading @@ -140,6 +137,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { private TaskThumbnailView mSnapshotView; private TaskMenuView mMenuView; private IconView mIconView; private DigitalWellBeingToast mDigitalWellBeingToast; private float mCurveScale; private float mZoomScale; private boolean mIsFullscreen; Loading Loading @@ -183,6 +181,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { super.onFinishInflate(); mSnapshotView = findViewById(R.id.snapshot); mIconView = findViewById(R.id.icon); mDigitalWellBeingToast = findViewById(R.id.digital_well_being_toast); } /** Loading Loading @@ -266,8 +265,18 @@ public class TaskView extends FrameLayout implements PageCallbacks { (task) -> mSnapshotView.setThumbnail(task, task.thumbnail)); mIconLoadRequest = iconCache.updateIconInBackground(mTask, (task) -> { setContentDescription(task.titleDescription); setIcon(task.icon); mDigitalWellBeingToast.initialize( mTask, (appRemainingTimeMs, isGroupLimit) -> { mAppRemainingTimeMs = appRemainingTimeMs; setContentDescription( hasRemainingTime() ? task.titleDescription + ". " + DigitalWellBeingToast.getText( appRemainingTimeMs, isGroupLimit) : task.titleDescription); }); }); } else { if (mThumbnailLoadRequest != null) { Loading Loading @@ -464,7 +473,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { } if (action == R.string.accessibility_app_usage_settings) { openAppUsageSettings(this); mDigitalWellBeingToast.openAppUsageSettings(); return true; } Loading @@ -486,24 +495,6 @@ public class TaskView extends FrameLayout implements PageCallbacks { return super.performAccessibilityAction(action, arguments); } private void openAppUsageSettings(View view) { final Intent intent = new Intent(SEE_TIME_IN_APP_TEMPLATE) .putExtra(Intent.EXTRA_PACKAGE_NAME, mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { final Launcher launcher = Launcher.getLauncher(getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight()); launcher.startActivity(intent, options.toBundle()); launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this); } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " + mTask.getTopComponent().getPackageName(), e); } } private RecentsView getRecentsView() { return (RecentsView) getParent(); } Loading